aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf3
-rw-r--r--dist/changes-5.3.074
-rw-r--r--examples/qml/dynamicscene/content/PaletteItem.qml2
-rw-r--r--examples/qml/dynamicscene/content/PerspectiveItem.qml4
-rw-r--r--examples/qml/dynamicscene/content/Sun.qml2
-rw-r--r--examples/qml/dynamicscene/content/itemCreation.js2
-rw-r--r--examples/qml/networkaccessmanagerfactory/networkaccessmanagerfactory.pro2
-rw-r--r--examples/qml/qml.pro6
-rw-r--r--examples/qml/referenceexamples/adding/adding.pro4
-rw-r--r--examples/qml/referenceexamples/attached/attached.pro2
-rw-r--r--examples/qml/referenceexamples/binding/binding.pro2
-rw-r--r--examples/qml/referenceexamples/binding/happybirthdaysong.cpp4
-rw-r--r--examples/qml/referenceexamples/binding/main.cpp2
-rw-r--r--examples/qml/referenceexamples/coercion/coercion.pro4
-rw-r--r--examples/qml/referenceexamples/default/default.pro4
-rw-r--r--examples/qml/referenceexamples/extended/extended.pro2
-rw-r--r--examples/qml/referenceexamples/extended/lineedit.cpp6
-rw-r--r--examples/qml/referenceexamples/grouped/grouped.pro2
-rw-r--r--examples/qml/referenceexamples/methods/methods.pro4
-rw-r--r--examples/qml/referenceexamples/properties/properties.pro4
-rw-r--r--examples/qml/referenceexamples/referenceexamples.pro12
-rw-r--r--examples/qml/referenceexamples/signal/main.cpp2
-rw-r--r--examples/qml/referenceexamples/signal/signal.pro2
-rw-r--r--examples/qml/referenceexamples/valuesource/example.qml14
-rw-r--r--examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp2
-rw-r--r--examples/qml/referenceexamples/valuesource/main.cpp2
-rw-r--r--examples/qml/referenceexamples/valuesource/valuesource.pro2
-rw-r--r--examples/qml/shell/main.cpp4
-rw-r--r--examples/qml/shell/shell.pro2
-rw-r--r--examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml4
-rw-r--r--examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro2
-rw-r--r--examples/qml/tutorials/extending/chapter5-listproperties/app.qml10
-rw-r--r--examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro2
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/app.qml10
-rw-r--r--examples/qml/tutorials/extending/extending.pro2
-rw-r--r--examples/qmltest/qmltest/tst_basic.qml2
-rw-r--r--examples/quick/animation/behaviors/SideRect.qml4
-rw-r--r--examples/quick/animation/behaviors/tvtennis.qml2
-rw-r--r--examples/quick/animation/states/states.qml2
-rw-r--r--examples/quick/animation/states/transitions.qml4
-rw-r--r--examples/quick/customitems/flipable/content/Card.qml2
-rw-r--r--examples/quick/customitems/flipable/flipable.qml2
-rw-r--r--examples/quick/customitems/searchbox/SearchBox.qml4
-rw-r--r--examples/quick/customitems/slideswitch/content/Switch.qml2
-rw-r--r--examples/quick/demos/tweetsearch/content/FlipBar.qml4
-rw-r--r--examples/quick/dialogs/dialogs.pro4
-rw-r--r--examples/quick/dialogs/systemdialogs/ColorDialogs.qml146
-rw-r--r--examples/quick/dialogs/systemdialogs/FileDialogs.qml180
-rw-r--r--examples/quick/dialogs/systemdialogs/FontDialogs.qml153
-rw-r--r--examples/quick/dialogs/systemdialogs/MessageDialogs.qml307
-rw-r--r--examples/quick/dialogs/systemdialogs/doc/images/systemdialogs-example.jpgbin47413 -> 0 bytes
-rw-r--r--examples/quick/dialogs/systemdialogs/doc/src/systemdialogs.qdoc48
-rw-r--r--examples/quick/dialogs/systemdialogs/systemdialogs.pro15
-rw-r--r--examples/quick/dialogs/systemdialogs/systemdialogs.qrc9
-rw-r--r--examples/quick/imageelements/content/ImageCell.qml2
-rw-r--r--examples/quick/imageprovider/imageprovider.cpp2
-rw-r--r--examples/quick/keyinteraction/focus/Core/ContextMenu.qml2
-rw-r--r--examples/quick/keyinteraction/focus/Core/GridMenu.qml2
-rw-r--r--examples/quick/keyinteraction/focus/Core/ListMenu.qml2
-rw-r--r--examples/quick/keyinteraction/focus/Core/TabMenu.qml2
-rw-r--r--examples/quick/keyinteraction/focus/focus.qml6
-rw-r--r--examples/quick/models/abstractitemmodel/model.h2
-rw-r--r--examples/quick/models/stringlistmodel/stringlistmodel.pro2
-rw-r--r--examples/quick/particles/affectors/content/spritegoal.qml6
-rw-r--r--examples/quick/particles/affectors/content/wander.qml2
-rw-r--r--examples/quick/particles/customparticle/content/blurparticles.qml4
-rw-r--r--examples/quick/particles/customparticle/content/fragmentshader.qml2
-rw-r--r--examples/quick/particles/customparticle/content/imagecolors.qml2
-rw-r--r--examples/quick/particles/imageparticle/content/allatonce.qml2
-rw-r--r--examples/quick/particles/itemparticle/content/Delegate2.qml2
-rw-r--r--examples/quick/particles/itemparticle/content/ExpandingDelegate.qml4
-rw-r--r--examples/quick/particles/itemparticle/particleview.qml2
-rw-r--r--examples/quick/positioners/positioners-transitions.qml20
-rw-r--r--examples/quick/quick.pro1
-rw-r--r--examples/quick/text/textselection/textselection.qml20
-rw-r--r--examples/quick/touchinteraction/flickable/corkboards.qml4
-rw-r--r--examples/quick/tutorials/samegame/samegame1/samegame.qml2
-rw-r--r--examples/quick/tutorials/samegame/samegame3/Block.qml2
-rw-r--r--examples/quick/tutorials/samegame/samegame3/samegame.js2
-rwxr-xr-xexamples/quick/tutorials/samegame/samegame4/content/samegame.js2
-rwxr-xr-xexamples/quick/tutorials/samegame/samegame4/highscores/scores.php6
-rw-r--r--examples/quick/views/listview/content/RecipesModel.qml108
-rw-r--r--examples/quick/views/listview/displaymargin.qml (renamed from src/imports/dialogs/qml/DefaultWindowDecoration.qml)76
-rw-r--r--examples/quick/views/listview/dynamiclist.qml6
-rw-r--r--examples/quick/views/listview/expandingdelegates.qml2
-rw-r--r--examples/quick/views/listview/highlight.qml2
-rw-r--r--examples/quick/views/listview/highlightranges.qml4
-rw-r--r--examples/quick/views/listview/sections.qml2
-rw-r--r--examples/quick/views/parallax/parallax.qml2
-rw-r--r--examples/quick/views/views.qml1
-rw-r--r--examples/quick/views/views.qrc1
-rw-r--r--examples/quickwidgets/quickwidget/main.cpp (renamed from src/imports/dialogs/WidgetColorDialog.qml)41
-rw-r--r--examples/quickwidgets/quickwidget/quickwidget.pro8
-rw-r--r--examples/quickwidgets/quickwidget/quickwidget.qrc5
-rw-r--r--examples/quickwidgets/quickwidget/rotatingsquare.qml (renamed from examples/quick/dialogs/systemdialogs/main.cpp)25
-rw-r--r--examples/quickwidgets/quickwidgets.pro2
-rw-r--r--qtdeclarative.pro2
-rw-r--r--src/3rdparty/double-conversion/README2
-rw-r--r--src/3rdparty/double-conversion/bignum-dtoa.cc11
-rw-r--r--src/3rdparty/double-conversion/bignum.cc24
-rw-r--r--src/3rdparty/double-conversion/cached-powers.cc1
-rw-r--r--src/3rdparty/double-conversion/double-conversion.cc194
-rw-r--r--src/3rdparty/double-conversion/double-conversion.h33
-rw-r--r--src/3rdparty/double-conversion/fast-dtoa.cc19
-rw-r--r--src/3rdparty/double-conversion/fixed-dtoa.cc14
-rw-r--r--src/3rdparty/double-conversion/ieee.h4
-rw-r--r--src/3rdparty/double-conversion/strtod.cc5
-rw-r--r--src/3rdparty/double-conversion/utils.h20
-rw-r--r--src/3rdparty/masm/masm-defs.pri2
-rw-r--r--src/imports/dialogs-private/dialogs-private.pro17
-rw-r--r--src/imports/dialogs-private/qmldir4
-rw-r--r--src/imports/dialogs-private/qquickfontlistmodel.cpp290
-rw-r--r--src/imports/dialogs-private/qquickfontlistmodel_p.h125
-rw-r--r--src/imports/dialogs-private/qquickwritingsystemlistmodel.cpp176
-rw-r--r--src/imports/dialogs/DefaultColorDialog.qml362
-rw-r--r--src/imports/dialogs/DefaultFileDialog.qml394
-rw-r--r--src/imports/dialogs/DefaultFontDialog.qml483
-rw-r--r--src/imports/dialogs/DefaultMessageDialog.qml330
-rw-r--r--src/imports/dialogs/WidgetFileDialog.qml44
-rw-r--r--src/imports/dialogs/WidgetFontDialog.qml44
-rw-r--r--src/imports/dialogs/WidgetMessageDialog.qml44
-rw-r--r--src/imports/dialogs/dialogs.pro97
-rw-r--r--src/imports/dialogs/doc/images/critical.pngbin253 -> 0 bytes
-rw-r--r--src/imports/dialogs/doc/images/information.pngbin254 -> 0 bytes
-rw-r--r--src/imports/dialogs/doc/images/question.pngbin257 -> 0 bytes
-rw-r--r--src/imports/dialogs/doc/images/replacefile.pngbin4304 -> 0 bytes
-rw-r--r--src/imports/dialogs/doc/images/warning.pngbin224 -> 0 bytes
-rw-r--r--src/imports/dialogs/doc/qtquickdialogs.qdocconf41
-rw-r--r--src/imports/dialogs/doc/src/qtquickdialogs-examples.qdoc36
-rw-r--r--src/imports/dialogs/doc/src/qtquickdialogs-index.qdoc58
-rw-r--r--src/imports/dialogs/images/checkers.pngbin149 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/checkmark.pngbin809 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/copy.pngbin1338 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/critical.pngbin253 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/crosshairs.pngbin876 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/folder.pngbin1841 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/information.pngbin254 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/question.pngbin257 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/slider_handle.pngbin1551 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/sunken_frame.pngbin623 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/up.pngbin662 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/warning.pngbin224 -> 0 bytes
-rw-r--r--src/imports/dialogs/images/window_border.pngbin588 -> 0 bytes
-rw-r--r--src/imports/dialogs/plugin.cpp214
-rw-r--r--src/imports/dialogs/plugins.qmltypes654
-rw-r--r--src/imports/dialogs/qml/Button.qml86
-rw-r--r--src/imports/dialogs/qml/CheckBox.qml96
-rwxr-xr-xsrc/imports/dialogs/qml/ColorSlider.qml138
-rw-r--r--src/imports/dialogs/qml/EdgeFade.qml63
-rw-r--r--src/imports/dialogs/qml/TextField.qml89
-rw-r--r--src/imports/dialogs/qml/qmldir5
-rw-r--r--src/imports/dialogs/qmldir4
-rw-r--r--src/imports/dialogs/qquickabstractcolordialog.cpp134
-rw-r--r--src/imports/dialogs/qquickabstractcolordialog_p.h113
-rw-r--r--src/imports/dialogs/qquickabstractdialog.cpp337
-rw-r--r--src/imports/dialogs/qquickabstractdialog_p.h145
-rw-r--r--src/imports/dialogs/qquickabstractfiledialog.cpp194
-rw-r--r--src/imports/dialogs/qquickabstractfiledialog_p.h122
-rw-r--r--src/imports/dialogs/qquickabstractfontdialog.cpp150
-rw-r--r--src/imports/dialogs/qquickabstractfontdialog_p.h113
-rw-r--r--src/imports/dialogs/qquickabstractmessagedialog.cpp179
-rw-r--r--src/imports/dialogs/qquickabstractmessagedialog_p.h165
-rw-r--r--src/imports/dialogs/qquickcolordialog.cpp119
-rw-r--r--src/imports/dialogs/qquickcolordialog_p.h80
-rw-r--r--src/imports/dialogs/qquickfiledialog.cpp172
-rw-r--r--src/imports/dialogs/qquickfontdialog.cpp120
-rw-r--r--src/imports/dialogs/qquickmessagedialog.cpp133
-rw-r--r--src/imports/dialogs/qquickplatformcolordialog.cpp254
-rw-r--r--src/imports/dialogs/qquickplatformfiledialog.cpp314
-rw-r--r--src/imports/dialogs/qquickplatformfontdialog.cpp252
-rw-r--r--src/imports/dialogs/qquickplatformmessagedialog.cpp398
-rw-r--r--src/imports/dialogs/qquickplatformmessagedialog_p.h78
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp8
-rw-r--r--src/imports/imports.pro4
-rw-r--r--src/imports/localstorage/plugin.cpp11
-rw-r--r--src/imports/settings/qqmlsettings.cpp3
-rw-r--r--src/imports/widgets/plugins.qmltypes302
-rw-r--r--src/imports/widgets/qmessageboxhelper_p.h107
-rw-r--r--src/imports/widgets/qmldir4
-rw-r--r--src/imports/widgets/qquickqcolordialog.cpp175
-rw-r--r--src/imports/widgets/qquickqfiledialog.cpp215
-rw-r--r--src/imports/widgets/qquickqfontdialog.cpp178
-rw-r--r--src/imports/widgets/qquickqmessagebox.cpp144
-rw-r--r--src/imports/widgets/widgets.pro32
-rw-r--r--src/imports/widgets/widgetsplugin.cpp89
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel.cpp10
-rw-r--r--src/particles/qquickitemparticle.cpp7
-rw-r--r--src/particles/qquickv4particledata.cpp6
-rw-r--r--src/particles/qquickv4particledata_p.h2
-rw-r--r--src/plugins/accessible/quick/qaccessiblequickitem.cpp54
-rw-r--r--src/plugins/accessible/shared/qqmlaccessible.cpp2
-rw-r--r--src/plugins/qmltooling/shared/qpacketprotocol.cpp2
-rw-r--r--src/qml/animations/animations.pri2
-rw-r--r--src/qml/animations/qabstractanimationjob.cpp9
-rw-r--r--src/qml/animations/qabstractanimationjob_p.h3
-rw-r--r--src/qml/animations/qcontinuinganimationgroupjob.cpp122
-rw-r--r--src/qml/animations/qcontinuinganimationgroupjob_p.h (renamed from src/imports/widgets/qquickqfontdialog_p.h)43
-rw-r--r--src/qml/compiler/compiler.pri10
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp795
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h225
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp1951
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h249
-rw-r--r--src/qml/compiler/qv4codegen.cpp519
-rw-r--r--src/qml/compiler/qv4codegen_p.h68
-rw-r--r--src/qml/compiler/qv4compileddata.cpp78
-rw-r--r--src/qml/compiler/qv4compileddata_p.h113
-rw-r--r--src/qml/compiler/qv4compiler.cpp55
-rw-r--r--src/qml/compiler/qv4compiler_p.h18
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h119
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp2648
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp627
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h144
-rw-r--r--src/qml/compiler/qv4isel_p.cpp158
-rw-r--r--src/qml/compiler/qv4isel_p.h128
-rw-r--r--src/qml/compiler/qv4isel_util_p.h132
-rw-r--r--src/qml/compiler/qv4jsir.cpp78
-rw-r--r--src/qml/compiler/qv4jsir_p.h28
-rw-r--r--src/qml/compiler/qv4ssa.cpp510
-rw-r--r--src/qml/compiler/qv4ssa_p.h18
-rw-r--r--src/qml/debugger/debugger.pri20
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter.cpp166
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h (renamed from src/imports/dialogs/qquickfiledialog_p.h)69
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice.cpp96
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice_p.h (renamed from src/imports/dialogs/qquickmessagedialog_p.h)40
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice_p_p.h (renamed from src/imports/widgets/qquickqcolordialog_p.h)32
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp417
-rw-r--r--src/qml/debugger/qqmldebugserver_p.h6
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp18
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h10
-rw-r--r--src/qml/debugger/qqmlenginecontrolservice.cpp145
-rw-r--r--src/qml/debugger/qqmlenginecontrolservice_p.h (renamed from src/imports/dialogs/qquickplatformfontdialog_p.h)52
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp18
-rw-r--r--src/qml/debugger/qqmlenginedebugservice_p.h4
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp205
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h368
-rw-r--r--src/qml/debugger/qqmlprofilerdefinitions_p.h (renamed from src/imports/widgets/qquickqfiledialog_p.h)116
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp632
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h306
-rw-r--r--src/qml/debugger/qv4debugservice.cpp45
-rw-r--r--src/qml/debugger/qv4debugservice_p.h9
-rw-r--r--src/qml/debugger/qv4profileradapter.cpp109
-rw-r--r--src/qml/debugger/qv4profileradapter_p.h (renamed from src/imports/widgets/qquickqmessagebox_p.h)36
-rw-r--r--src/qml/debugger/qv4profilerservice.cpp (renamed from src/qml/debugger/qv8profilerservice.cpp)101
-rw-r--r--src/qml/debugger/qv4profilerservice_p.h (renamed from src/qml/debugger/qv8profilerservice_p.h)37
-rw-r--r--src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml2
-rw-r--r--src/qml/doc/snippets/qml/SelfDestroyingRect.qml4
-rw-r--r--src/qml/doc/snippets/qml/createQmlObject.qml2
-rw-r--r--src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml2
-rw-r--r--src/qml/doc/snippets/qml/qml-documents/inline-component.qml4
-rw-r--r--src/qml/doc/snippets/qml/qml-documents/inline-text-component.qml4
-rw-r--r--src/qml/doc/snippets/qml/qml-documents/non-trivial.qml4
-rw-r--r--src/qml/doc/snippets/qml/qml-documents/qmldocuments.qml2
-rw-r--r--src/qml/doc/snippets/qml/qtobject.qml2
-rw-r--r--src/qml/jit/jit.pri20
-rw-r--r--src/qml/jit/qv4assembler.cpp468
-rw-r--r--src/qml/jit/qv4assembler_p.h (renamed from src/qml/compiler/qv4isel_masm_p.h)474
-rw-r--r--src/qml/jit/qv4binop.cpp428
-rw-r--r--src/qml/jit/qv4binop_p.h76
-rw-r--r--src/qml/jit/qv4isel_masm.cpp1771
-rw-r--r--src/qml/jit/qv4isel_masm_p.h273
-rw-r--r--src/qml/jit/qv4regalloc.cpp (renamed from src/qml/compiler/qv4regalloc.cpp)145
-rw-r--r--src/qml/jit/qv4regalloc_p.h (renamed from src/qml/compiler/qv4regalloc_p.h)26
-rw-r--r--src/qml/jit/qv4unop.cpp139
-rw-r--r--src/qml/jit/qv4unop_p.h (renamed from src/imports/dialogs/qquickdialogassets_p.h)46
-rw-r--r--src/qml/jsapi/qjsvalue.cpp6
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp27
-rw-r--r--src/qml/jsapi/qjsvalueiterator_p.h6
-rw-r--r--src/qml/jsruntime/jsruntime.pri12
-rw-r--r--src/qml/jsruntime/qv4alloca_p.h4
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp50
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h17
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp771
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h219
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp190
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4context.cpp47
-rw-r--r--src/qml/jsruntime/qv4context_p.h27
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp9
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h11
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp10
-rw-r--r--src/qml/jsruntime/qv4engine.cpp144
-rw-r--r--src/qml/jsruntime/qv4engine_p.h128
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp41
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h34
-rw-r--r--src/qml/jsruntime/qv4function.cpp2
-rw-r--r--src/qml/jsruntime/qv4function_p.h4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp75
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h38
-rw-r--r--src/qml/jsruntime/qv4global_p.h16
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4include.cpp6
-rw-r--r--src/qml/jsruntime/qv4include_p.h2
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp2
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp28
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp193
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h15
-rw-r--r--src/qml/jsruntime/qv4managed.cpp97
-rw-r--r--src/qml/jsruntime/qv4managed_p.h261
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4mm.cpp13
-rw-r--r--src/qml/jsruntime/qv4mm_p.h2
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp754
-rw-r--r--src/qml/jsruntime/qv4object_p.h331
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp77
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h17
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp125
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h2
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp255
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h167
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp101
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h169
-rw-r--r--src/qml/jsruntime/qv4property_p.h43
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp85
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h14
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp70
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h12
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp26
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp124
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h65
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h327
-rw-r--r--src/qml/jsruntime/qv4script.cpp22
-rw-r--r--src/qml/jsruntime/qv4script_p.h2
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp48
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp17
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h2
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp90
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h41
-rw-r--r--src/qml/jsruntime/qv4string.cpp22
-rw-r--r--src/qml/jsruntime/qv4string_p.h20
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp48
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4value.cpp216
-rw-r--r--src/qml/jsruntime/qv4value_def_p.h476
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h285
-rw-r--r--src/qml/jsruntime/qv4value_p.h718
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h6
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp137
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h7
-rw-r--r--src/qml/parser/qqmljslexer.cpp2
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h2
-rw-r--r--src/qml/qml.pro1
-rw-r--r--src/qml/qml/ftw/qbitfield_p.h8
-rw-r--r--src/qml/qml/ftw/qfieldlist_p.h4
-rw-r--r--src/qml/qml/ftw/qfinitestack_p.h10
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp6
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h68
-rw-r--r--src/qml/qml/ftw/qhashfield_p.h4
-rw-r--r--src/qml/qml/ftw/qintrusivelist.cpp4
-rw-r--r--src/qml/qml/ftw/qintrusivelist_p.h82
-rw-r--r--src/qml/qml/ftw/qqmlpool_p.h18
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h32
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp20
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h2
-rw-r--r--src/qml/qml/ftw/qrecursionwatcher_p.h2
-rw-r--r--src/qml/qml/qqml.h32
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h4
-rw-r--r--src/qml/qml/qqmlbinding.cpp9
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp11
-rw-r--r--src/qml/qml/qqmlcleanup.cpp4
-rw-r--r--src/qml/qml/qqmlcleanup_p.h2
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp26
-rw-r--r--src/qml/qml/qqmlcompiler.cpp389
-rw-r--r--src/qml/qml/qqmlcompiler_p.h52
-rw-r--r--src/qml/qml/qqmlcomponent.cpp25
-rw-r--r--src/qml/qml/qqmlcomponent.h2
-rw-r--r--src/qml/qml/qqmlcomponent_p.h8
-rw-r--r--src/qml/qml/qqmlcontext.cpp6
-rw-r--r--src/qml/qml/qqmlcontext_p.h2
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp10
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h6
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp85
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h25
-rw-r--r--src/qml/qml/qqmldata_p.h9
-rw-r--r--src/qml/qml/qqmlengine.cpp30
-rw-r--r--src/qml/qml/qqmlengine_p.h57
-rw-r--r--src/qml/qml/qqmlerror.cpp4
-rw-r--r--src/qml/qml/qqmlglobal_p.h10
-rw-r--r--src/qml/qml/qqmlguard_p.h14
-rw-r--r--src/qml/qml/qqmlimport.cpp25
-rw-r--r--src/qml/qml/qqmlincubator.cpp107
-rw-r--r--src/qml/qml/qqmlincubator.h10
-rw-r--r--src/qml/qml/qqmlincubator_p.h9
-rw-r--r--src/qml/qml/qqmlinfo.cpp4
-rw-r--r--src/qml/qml/qqmlinstruction_p.h17
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp2
-rw-r--r--src/qml/qml/qqmllist.cpp26
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp20
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h6
-rw-r--r--src/qml/qml/qqmllocale.cpp90
-rw-r--r--src/qml/qml/qqmllocale_p.h58
-rw-r--r--src/qml/qml/qqmlmetatype.cpp20
-rw-r--r--src/qml/qml/qqmlmetatype_p.h4
-rw-r--r--src/qml/qml/qqmlnotifier.cpp2
-rw-r--r--src/qml/qml/qqmlnotifier_p.h4
-rw-r--r--src/qml/qml/qqmlnullablevalue_p_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp1631
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h138
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlparserstatus.cpp2
-rw-r--r--src/qml/qml/qqmlparserstatus.h1
-rw-r--r--src/qml/qml/qqmlprivate.h8
-rw-r--r--src/qml/qml/qqmlproperty.cpp2
-rw-r--r--src/qml/qml/qqmlproperty.h2
-rw-r--r--src/qml/qml/qqmlproperty_p.h4
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp6
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h4
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp4
-rw-r--r--src/qml/qml/qqmlscript.cpp94
-rw-r--r--src/qml/qml/qqmlscript_p.h26
-rw-r--r--src/qml/qml/qqmlscriptstring.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp316
-rw-r--r--src/qml/qml/qqmltypeloader_p.h18
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp8
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp4
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvme.cpp157
-rw-r--r--src/qml/qml/qqmlvme_p.h57
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp45
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h4
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp94
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp40
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp62
-rw-r--r--src/qml/qml/v8/qv8engine_p.h8
-rw-r--r--src/qml/qml/v8/v8.pri1
-rw-r--r--src/qml/types/qqmlconnections.cpp38
-rw-r--r--src/qml/types/qqmlconnections_p.h1
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp67
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h4
-rw-r--r--src/qml/types/qqmllistmodel.cpp175
-rw-r--r--src/qml/types/qqmllistmodel_p.h6
-rw-r--r--src/qml/types/qquickworkerscript.cpp14
-rw-r--r--src/qml/util/qqmladaptormodel.cpp5
-rw-r--r--src/quick/doc/snippets/qml/animatedimage.qml2
-rw-r--r--src/quick/doc/snippets/qml/listview/listview.qml2
-rw-r--r--src/quick/doc/snippets/qml/loader/connections.qml2
-rw-r--r--src/quick/doc/snippets/qml/loader/simple.qml2
-rw-r--r--src/quick/doc/snippets/qml/parentanimation.qml4
-rw-r--r--src/quick/doc/snippets/qml/parentchange.qml4
-rw-r--r--src/quick/doc/snippets/qml/propertyanimation.qml4
-rw-r--r--src/quick/doc/snippets/qml/propertychanges.qml4
-rw-r--r--src/quick/doc/snippets/qml/repeaters/repeater.qml6
-rw-r--r--src/quick/doc/snippets/qml/rotationanimation.qml4
-rw-r--r--src/quick/doc/snippets/qml/row.qml2
-rw-r--r--src/quick/doc/snippets/qml/state.qml4
-rw-r--r--src/quick/doc/snippets/qml/transition-from-to.qml2
-rw-r--r--src/quick/doc/snippets/qml/transition-reversible.qml2
-rw-r--r--src/quick/doc/snippets/qml/transition.qml4
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc3
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp8
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp75
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h2
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp2
-rw-r--r--src/quick/items/items.pri2
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp51
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h80
-rw-r--r--src/quick/items/qquickborderimage.cpp1
-rw-r--r--src/quick/items/qquickflickable.cpp2
-rw-r--r--src/quick/items/qquickgridview.cpp40
-rw-r--r--src/quick/items/qquickimage.cpp64
-rw-r--r--src/quick/items/qquickimage_p.h5
-rw-r--r--src/quick/items/qquickimage_p_p.h1
-rw-r--r--src/quick/items/qquickitem.cpp250
-rw-r--r--src/quick/items/qquickitem.h8
-rw-r--r--src/quick/items/qquickitem_p.h17
-rw-r--r--src/quick/items/qquickitemsmodule.cpp6
-rw-r--r--src/quick/items/qquickitemview.cpp40
-rw-r--r--src/quick/items/qquickitemview_p.h10
-rw-r--r--src/quick/items/qquickitemview_p_p.h2
-rw-r--r--src/quick/items/qquicklistview.cpp39
-rw-r--r--src/quick/items/qquickloader_p_p.h2
-rw-r--r--src/quick/items/qquickmousearea.cpp5
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp5
-rw-r--r--src/quick/items/qquickrectangle.cpp14
-rw-r--r--src/quick/items/qquickrendercontrol.cpp228
-rw-r--r--src/quick/items/qquickrendercontrol_p.h94
-rw-r--r--src/quick/items/qquickscreen.cpp2
-rw-r--r--src/quick/items/qquickshadereffect.cpp21
-rw-r--r--src/quick/items/qquicktext.cpp86
-rw-r--r--src/quick/items/qquicktext_p.h3
-rw-r--r--src/quick/items/qquicktext_p_p.h9
-rw-r--r--src/quick/items/qquicktextedit.cpp28
-rw-r--r--src/quick/items/qquicktextedit_p.h2
-rw-r--r--src/quick/items/qquicktextinput.cpp32
-rw-r--r--src/quick/items/qquicktextinput_p_p.h1
-rw-r--r--src/quick/items/qquicktextnode.cpp8
-rw-r--r--src/quick/items/qquicktranslate.cpp75
-rw-r--r--src/quick/items/qquicktranslate_p.h23
-rw-r--r--src/quick/items/qquickview.cpp39
-rw-r--r--src/quick/items/qquickview_p.h22
-rw-r--r--src/quick/items/qquickwindow.cpp248
-rw-r--r--src/quick/items/qquickwindow.h11
-rw-r--r--src/quick/items/qquickwindow_p.h11
-rw-r--r--src/quick/qtquick2.cpp4
-rw-r--r--src/quick/quick.pro3
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp361
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h24
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp10
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp19
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h2
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp15
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp24
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h3
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp30
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h4
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp67
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p_p.h4
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp28
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp44
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp73
-rw-r--r--src/quick/scenegraph/scenegraph.pri4
-rw-r--r--src/quick/scenegraph/scenegraph.qrc2
-rw-r--r--src/quick/scenegraph/shaders/visualization.frag11
-rw-r--r--src/quick/scenegraph/shaders/visualization.vert22
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp45
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture_p.h4
-rw-r--r--src/quick/scenegraph/util/qsgpainternode.cpp1
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp50
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h4
-rw-r--r--src/quick/util/qquickanimatorjob.cpp2
-rw-r--r--src/quick/util/qquickbehavior.cpp13
-rw-r--r--src/quick/util/qquickglobal.cpp2
-rw-r--r--src/quick/util/qquickimageprovider.cpp18
-rw-r--r--src/quick/util/qquickpixmapcache.cpp76
-rw-r--r--src/quick/util/qquickprofiler.cpp205
-rw-r--r--src/quick/util/qquickprofiler_p.h228
-rw-r--r--src/quick/util/qquickpropertychanges.cpp61
-rw-r--r--src/quick/util/qquickpropertychanges_p.h2
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp18
-rw-r--r--src/quick/util/qquicksmoothedanimation_p_p.h4
-rw-r--r--src/quick/util/qquickspringanimation.cpp24
-rw-r--r--src/quick/util/qquickstate_p_p.h2
-rw-r--r--src/quick/util/qquicktimeline.cpp27
-rw-r--r--src/quick/util/qquicktransitionmanager.cpp12
-rw-r--r--src/quick/util/qquicktransitionmanager_p_p.h2
-rw-r--r--src/quick/util/util.pri6
-rw-r--r--src/quickwidgets/qquickwidget.cpp846
-rw-r--r--src/quickwidgets/qquickwidget.h131
-rw-r--r--src/quickwidgets/qquickwidget_p.h (renamed from src/imports/dialogs-private/qquickwritingsystemlistmodel_p.h)95
-rw-r--r--src/quickwidgets/qtquickwidgetsglobal.h (renamed from src/qml/qml/v8/qv8profiler_p.h)23
-rw-r--r--src/quickwidgets/quickwidgets.pro19
-rw-r--r--src/src.pro2
-rw-r--r--sync.profile1
-rw-r--r--tests/auto/particles/qquickgroupgoal/data/basic.qml2
-rw-r--r--tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp3
-rw-r--r--tests/auto/qml/debugger/debugger.pro5
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp43
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/data/exit.qml9
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/data/test.qml (renamed from tests/auto/qml/debugger/qv8profilerservice/data/test.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro18
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp228
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml17
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro7
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp82
-rw-r--r--tests/auto/qml/debugger/qv4profilerservice/data/console.qml (renamed from tests/auto/qml/debugger/qv8profilerservice/data/console.qml)0
-rw-r--r--tests/auto/qml/debugger/qv4profilerservice/data/exit.qml (renamed from tests/auto/qml/debugger/qv8profilerservice/data/exit.qml)0
-rw-r--r--tests/auto/qml/debugger/qv4profilerservice/data/test.qml5
-rw-r--r--tests/auto/qml/debugger/qv4profilerservice/qv4profilerservice.pro (renamed from tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro)4
-rw-r--r--tests/auto/qml/debugger/qv4profilerservice/tst_qv4profilerservice.cpp (renamed from tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp)64
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugclient.cpp2
-rw-r--r--tests/auto/qml/parserstress/tests/shell.js36
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp7
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp33
-rw-r--r--tests/auto/qml/qqmlcomponent/data/incubateObject.qml4
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/aliasBindingsAssignCorrectly.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/aliasBindingsOverrideTarget.3.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/aliasPropertyAndBinding.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/bindingLoop.qml20
-rw-r--r--tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.2.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.4.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/deletedEngine.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/dynamicDeletion.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/eval.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include_callback.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include_remote.js8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include_remote_missing.js4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include_shared.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/creationContext.qml24
-rw-r--r--tests/auto/qml/qqmlecmascript/data/methods.1.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/methods.2.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/outerBindingOverridesInnerBinding.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertySplicing.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVar.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.3.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scope.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.1.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.2.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.3.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.4.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.5.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.6.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptDisconnect.1.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptDisconnect.2.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptDisconnect.3.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptDisconnect.4.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptErrors.js2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/selfDeletingBinding.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/signalAssignment.1.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/signalAssignment.2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/signalHandlers.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/data/signalTriggeredBindings.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h6
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp79
-rw-r--r--tests/auto/qml/qqmlengine/qqmlengine.pro2
-rw-r--r--tests/auto/qml/qqmlerror/tst_qqmlerror.cpp2
-rw-r--r--tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp2
-rw-r--r--tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/data/NestedAlias.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/OnCompletedType.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/OnDestructionType.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.4.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.5.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/defaultPropertyListOrder.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.2.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/interfaceQList.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidAttachedProperty.11.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.7.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/nonexistantProperty.3.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/nullDotProperty.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/onCompleted.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/onDestruction.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/scriptString.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp20
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h4
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp30
-rw-r--r--tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp6
-rw-r--r--tests/auto/qml/qqmllistmodel/data/multipleroles.qml6
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp1
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp36
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp6
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp6
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.2.qml2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.qml2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp7
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp6
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.h8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/conflicting.1.qml2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/conflicting.2.qml2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/conflicting.3.qml2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp28
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/element.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml36
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml52
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/invalidMethodUsage.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/redirectError.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/redirectRecur.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/redirects.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/status.qml36
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml36
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp18
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp4
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp2
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp2
-rw-r--r--tests/auto/quick/qquickaccessible/data/checkbuttons.qml11
-rw-r--r--tests/auto/quick/qquickaccessible/qquickaccessible.pro2
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp137
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp4
-rw-r--r--tests/auto/quick/qquickanimations/data/runningTrueBug.qml2
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp3
-rw-r--r--tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning.qml14
-rw-r--r--tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning2.qml14
-rw-r--r--tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml (renamed from examples/quick/dialogs/systemdialogs/systemdialogs.qml)50
-rw-r--r--tests/auto/quick/qquickbehaviors/data/qtbug21549.qml18
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp141
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml3
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml15
-rw-r--r--tests/auto/quick/qquickgridview/data/displayMargin.qml (renamed from src/imports/dialogs/qquickplatformcolordialog_p.h)71
-rw-r--r--tests/auto/quick/qquickgridview/data/gridview-enforcerange.qml2
-rw-r--r--tests/auto/quick/qquickgridview/data/propertychangestest.qml8
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp39
-rw-r--r--tests/auto/quick/qquickimage/data/aspectratio.qml2
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp12
-rw-r--r--tests/auto/quick/qquickitem/data/visualParentOwnership.qml14
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp126
-rw-r--r--tests/auto/quick/qquickitem2/data/childrenRectBug3.qml2
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp4
-rw-r--r--tests/auto/quick/qquicklistview/data/displayMargin.qml (renamed from src/imports/dialogs/qquickplatformfiledialog_p.h)70
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-enforcerange.qml2
-rw-r--r--tests/auto/quick/qquicklistview/data/propertychangestest.qml8
-rw-r--r--tests/auto/quick/qquicklistview/incrementalmodel.cpp6
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp38
-rw-r--r--tests/auto/quick/qquickmousearea/data/dragproperties.qml2
-rw-r--r--tests/auto/quick/qquickmousearea/data/dragreset.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/propertychanges.qml4
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp57
-rw-r--r--tests/auto/quick/qquickrepeater/data/properties.qml10
-rw-r--r--tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp3
-rw-r--r--tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp2
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayoutHAlign.qml20
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp50
-rw-r--r--tests/auto/quick/qquicktextedit/data/http/cursorHttpTest.qml4
-rw-r--r--tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail1.qml4
-rw-r--r--tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail2.qml4
-rw-r--r--tests/auto/quick/qquicktextedit/data/http/cursorHttpTestPass.qml4
-rw-r--r--tests/auto/quick/qquicktextedit/data/inputmethodhints.qml2
-rw-r--r--tests/auto/quick/qquicktextedit/data/navigation.qml4
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp8
-rw-r--r--tests/auto/quick/qquicktextinput/data/navigation.qml4
-rw-r--r--tests/auto/quick/qquicktextinput/data/validators.qml2
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp104
-rw-r--r--tests/auto/quick/qquicktimeline/qquicktimeline.pro9
-rw-r--r--tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp67
-rw-r--r--tests/auto/quick/qquickview/tst_qquickview.cpp2
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp112
-rw-r--r--tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp10
-rw-r--r--tests/auto/quick/quick.pro1
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp16
-rw-r--r--tests/auto/quick/scenegraph/data/blacknwhite.pngbin0 -> 156 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/mipmap_large.pngbin0 -> 4465 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/mipmap_small.pngbin0 -> 170 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/render_ImageFiltering.qml (renamed from src/imports/dialogs/qquickfontdialog_p.h)65
-rw-r--r--tests/auto/quick/scenegraph/data/render_Mipmap.qml (renamed from src/imports/dialogs-private/dialogsprivateplugin.cpp)51
-rw-r--r--tests/auto/quick/scenegraph/scenegraph.pro3
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp2
-rw-r--r--tests/auto/shared/testhttpserver.cpp6
-rw-r--r--tests/benchmarks/qml/binding/data/localproperty.txt2
-rw-r--r--tests/benchmarks/qml/javascript/testtypes.h4
-rw-r--r--tests/benchmarks/qml/painting/paintbenchmark.cpp4
-rw-r--r--tests/benchmarks/qml/qmltime/qmltime.cpp6
-rw-r--r--tests/benchmarks/qml/qmltime/qmltime.pro2
-rw-r--r--tests/benchmarks/qml/qqmlmetaproperty/qqmlmetaproperty.pro2
-rw-r--r--tests/benchmarks/qml/script/data/slot_complex.qml2
-rw-r--r--tests/manual/httpserver/httpserver.pro13
-rw-r--r--tests/manual/httpserver/main.cpp119
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_sinhala.qml16
-rw-r--r--tests/manual/v4/TestExpectations14
-rw-r--r--tests/manual/v4/sparsearraytest.js55
-rwxr-xr-xtests/manual/v4/test262.py12
-rw-r--r--tests/manual/v4/v8-bench.js16
-rw-r--r--tools/qmljs/main.cpp20
-rw-r--r--tools/qmlplugindump/main.cpp18
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro2
-rw-r--r--tools/qmlprofiler/qpacketprotocol.cpp2
-rw-r--r--tools/qmlprofiler/qqmldebugclient.cpp2
769 files changed, 23054 insertions, 22924 deletions
diff --git a/.qmake.conf b/.qmake.conf
index bb65e47d07..88d13d1eef 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,5 +2,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.2.2
-
+MODULE_VERSION = 5.3.0
diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0
new file mode 100644
index 0000000000..05550765d4
--- /dev/null
+++ b/dist/changes-5.3.0
@@ -0,0 +1,74 @@
+Qt 5.3 introduces many new features and improvements as well as bugfixes
+over the 5.2.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+ http://qt-project.org/doc/qt-5.2
+
+The Qt version 5.3 series is binary compatible with the 5.2.x series.
+Applications compiled for 5.2 will continue to run with 5.3.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ http://bugreports.qt-project.org/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* General *
+****************************************************************************
+
+General Improvements
+--------------------
+
+Third party components
+----------------------
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+- Signals declared in QML that take "var" parameters, are now using QJSValue
+ as C++ type for these parameters, instead of QVariant.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtQml
+------
+
+QtQuick
+------
+
+- Introduced QQuickWidget. This is the equivalent of QQuickView in the
+ QWidget world. It allows easy and flexible embedding of QtQuick
+ scenes into widget-based application windows without the
+ restrictions imposed by QWidget::createWindowContainer().
+
+
+****************************************************************************
+* Database Drivers *
+****************************************************************************
+
+
+****************************************************************************
+* Platform Specific Changes *
+****************************************************************************
+
+
+****************************************************************************
+* Compiler Specific Changes *
+****************************************************************************
+
+
+****************************************************************************
+* Tools *
+****************************************************************************
+
+
+****************************************************************************
+* Plugins *
+****************************************************************************
+
diff --git a/examples/qml/dynamicscene/content/PaletteItem.qml b/examples/qml/dynamicscene/content/PaletteItem.qml
index a74d7b6413..62d6efedc6 100644
--- a/examples/qml/dynamicscene/content/PaletteItem.qml
+++ b/examples/qml/dynamicscene/content/PaletteItem.qml
@@ -49,7 +49,7 @@ Image {
source: image
- MouseArea {
+ MouseArea {
anchors.fill: parent
onPressed: Code.startDrag(mouse);
diff --git a/examples/qml/dynamicscene/content/PerspectiveItem.qml b/examples/qml/dynamicscene/content/PerspectiveItem.qml
index 509d29320f..d0d1da9228 100644
--- a/examples/qml/dynamicscene/content/PerspectiveItem.qml
+++ b/examples/qml/dynamicscene/content/PerspectiveItem.qml
@@ -44,9 +44,9 @@ Image {
id: rootItem
property bool created: false
- property string image
+ property string image
- property double scaledBottom: y + (height + height*scale) / 2
+ property double scaledBottom: y + (height + height*scale) / 2
property bool onLand: scaledBottom > (window.height / 2 + window.centerOffset)
source: image
diff --git a/examples/qml/dynamicscene/content/Sun.qml b/examples/qml/dynamicscene/content/Sun.qml
index e2101a252b..5e867e45aa 100644
--- a/examples/qml/dynamicscene/content/Sun.qml
+++ b/examples/qml/dynamicscene/content/Sun.qml
@@ -49,7 +49,7 @@ Image {
source: image
onCreatedChanged: {
if (created) {
- sun.z = 1; // above the sky but below the ground layer
+ sun.z = 1; // above the sky but below the ground layer
window.activeSuns++;
// once item is created, start moving offscreen
dropYAnim.duration = (window.height + window.centerOffset - sun.y) * 16;
diff --git a/examples/qml/dynamicscene/content/itemCreation.js b/examples/qml/dynamicscene/content/itemCreation.js
index 40f5415f9f..2829a83410 100644
--- a/examples/qml/dynamicscene/content/itemCreation.js
+++ b/examples/qml/dynamicscene/content/itemCreation.js
@@ -22,7 +22,7 @@ function loadComponent() {
itemComponent = Qt.createComponent(paletteItem.componentFile);
if (itemComponent.status == Component.Loading) //Depending on the content, it can be ready or error immediately
component.statusChanged.connect(createItem);
- else
+ else
createItem();
}
diff --git a/examples/qml/networkaccessmanagerfactory/networkaccessmanagerfactory.pro b/examples/qml/networkaccessmanagerfactory/networkaccessmanagerfactory.pro
index 5994ab221e..b4d6d827fd 100644
--- a/examples/qml/networkaccessmanagerfactory/networkaccessmanagerfactory.pro
+++ b/examples/qml/networkaccessmanagerfactory/networkaccessmanagerfactory.pro
@@ -1,7 +1,7 @@
TEMPLATE = app
QT += qml quick network
-SOURCES += main.cpp
+SOURCES += main.cpp
RESOURCES += networkaccessmanagerfactory.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/qml/networkaccessmanagerfactory
diff --git a/examples/qml/qml.pro b/examples/qml/qml.pro
index 5ab155cb40..d5f9fa8a9e 100644
--- a/examples/qml/qml.pro
+++ b/examples/qml/qml.pro
@@ -1,9 +1,11 @@
TEMPLATE = subdirs
-qtHaveModule(quick): SUBDIRS += networkaccessmanagerfactory xmlhttprequest
+qtHaveModule(quick): SUBDIRS += \
+ networkaccessmanagerfactory \
+ qmlextensionplugins \
+ xmlhttprequest
SUBDIRS += \
- qmlextensionplugins \
referenceexamples \
shell
diff --git a/examples/qml/referenceexamples/adding/adding.pro b/examples/qml/referenceexamples/adding/adding.pro
index 86c830bda9..ae135c7925 100644
--- a/examples/qml/referenceexamples/adding/adding.pro
+++ b/examples/qml/referenceexamples/adding/adding.pro
@@ -1,7 +1,7 @@
-QT += qml
+QT = core qml
SOURCES += main.cpp \
- person.cpp
+ person.cpp
HEADERS += person.h
RESOURCES += adding.qrc
diff --git a/examples/qml/referenceexamples/attached/attached.pro b/examples/qml/referenceexamples/attached/attached.pro
index 1225a5fcfd..16b585bc45 100644
--- a/examples/qml/referenceexamples/attached/attached.pro
+++ b/examples/qml/referenceexamples/attached/attached.pro
@@ -2,7 +2,7 @@ QT += qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += attached.qrc
diff --git a/examples/qml/referenceexamples/binding/binding.pro b/examples/qml/referenceexamples/binding/binding.pro
index 3c1f9565ed..636d0a10f1 100644
--- a/examples/qml/referenceexamples/binding/binding.pro
+++ b/examples/qml/referenceexamples/binding/binding.pro
@@ -3,7 +3,7 @@ QT += qml
SOURCES += main.cpp \
person.cpp \
birthdayparty.cpp \
- happybirthdaysong.cpp
+ happybirthdaysong.cpp
HEADERS += person.h \
birthdayparty.h \
happybirthdaysong.h
diff --git a/examples/qml/referenceexamples/binding/happybirthdaysong.cpp b/examples/qml/referenceexamples/binding/happybirthdaysong.cpp
index af60dd329c..6e3a9fcf6d 100644
--- a/examples/qml/referenceexamples/binding/happybirthdaysong.cpp
+++ b/examples/qml/referenceexamples/binding/happybirthdaysong.cpp
@@ -72,10 +72,10 @@ void HappyBirthdaySong::setName(const QString &name)
m_lyrics << "Happy birthday dear " + m_name + ",";
m_lyrics << "Happy birthday to you!";
m_lyrics << "";
-
+
emit nameChanged();
}
-
+
void HappyBirthdaySong::advance()
{
m_line = (m_line + 1) % m_lyrics.count();
diff --git a/examples/qml/referenceexamples/binding/main.cpp b/examples/qml/referenceexamples/binding/main.cpp
index 0d4b13d63f..f09b45fed2 100644
--- a/examples/qml/referenceexamples/binding/main.cpp
+++ b/examples/qml/referenceexamples/binding/main.cpp
@@ -72,7 +72,7 @@ int main(int argc, char ** argv)
Person *guest = party->guest(ii);
QDate rsvpDate;
- QObject *attached =
+ QObject *attached =
qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
if (attached)
rsvpDate = attached->property("rsvp").toDate();
diff --git a/examples/qml/referenceexamples/coercion/coercion.pro b/examples/qml/referenceexamples/coercion/coercion.pro
index c501b9cda2..373a15fc28 100644
--- a/examples/qml/referenceexamples/coercion/coercion.pro
+++ b/examples/qml/referenceexamples/coercion/coercion.pro
@@ -1,8 +1,8 @@
-QT += qml
+QT = core qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += coercion.qrc
diff --git a/examples/qml/referenceexamples/default/default.pro b/examples/qml/referenceexamples/default/default.pro
index db4b88413b..c119ef0d2e 100644
--- a/examples/qml/referenceexamples/default/default.pro
+++ b/examples/qml/referenceexamples/default/default.pro
@@ -1,8 +1,8 @@
-QT += qml
+QT = core qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += default.qrc
diff --git a/examples/qml/referenceexamples/extended/extended.pro b/examples/qml/referenceexamples/extended/extended.pro
index b38a1753b9..22d8ded708 100644
--- a/examples/qml/referenceexamples/extended/extended.pro
+++ b/examples/qml/referenceexamples/extended/extended.pro
@@ -1,7 +1,7 @@
QT += qml widgets
SOURCES += main.cpp \
- lineedit.cpp
+ lineedit.cpp
HEADERS += lineedit.h
RESOURCES += extended.qrc
diff --git a/examples/qml/referenceexamples/extended/lineedit.cpp b/examples/qml/referenceexamples/extended/lineedit.cpp
index 522f8074ea..9c916a1bd8 100644
--- a/examples/qml/referenceexamples/extended/lineedit.cpp
+++ b/examples/qml/referenceexamples/extended/lineedit.cpp
@@ -66,7 +66,7 @@ int LineEditExtension::rightMargin() const
return r;
}
-void LineEditExtension::setRightMargin(int m)
+void LineEditExtension::setRightMargin(int m)
{
int l, r, t, b;
m_lineedit->getTextMargins(&l, &t, &r, &b);
@@ -80,7 +80,7 @@ int LineEditExtension::topMargin() const
return t;
}
-void LineEditExtension::setTopMargin(int m)
+void LineEditExtension::setTopMargin(int m)
{
int l, r, t, b;
m_lineedit->getTextMargins(&l, &t, &r, &b);
@@ -94,7 +94,7 @@ int LineEditExtension::bottomMargin() const
return b;
}
-void LineEditExtension::setBottomMargin(int m)
+void LineEditExtension::setBottomMargin(int m)
{
int l, r, t, b;
m_lineedit->getTextMargins(&l, &t, &r, &b);
diff --git a/examples/qml/referenceexamples/grouped/grouped.pro b/examples/qml/referenceexamples/grouped/grouped.pro
index 7014d9680d..ef66ea3e1d 100644
--- a/examples/qml/referenceexamples/grouped/grouped.pro
+++ b/examples/qml/referenceexamples/grouped/grouped.pro
@@ -2,7 +2,7 @@ QT += qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += grouped.qrc
diff --git a/examples/qml/referenceexamples/methods/methods.pro b/examples/qml/referenceexamples/methods/methods.pro
index c1be0713e6..008ba19d96 100644
--- a/examples/qml/referenceexamples/methods/methods.pro
+++ b/examples/qml/referenceexamples/methods/methods.pro
@@ -1,8 +1,8 @@
-QT += qml
+QT = core qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += methods.qrc
diff --git a/examples/qml/referenceexamples/properties/properties.pro b/examples/qml/referenceexamples/properties/properties.pro
index cd1ffeddcc..101c878abd 100644
--- a/examples/qml/referenceexamples/properties/properties.pro
+++ b/examples/qml/referenceexamples/properties/properties.pro
@@ -1,8 +1,8 @@
-QT += qml
+QT = core qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += properties.qrc
diff --git a/examples/qml/referenceexamples/referenceexamples.pro b/examples/qml/referenceexamples/referenceexamples.pro
index ae3b884592..3f4bbcf75d 100644
--- a/examples/qml/referenceexamples/referenceexamples.pro
+++ b/examples/qml/referenceexamples/referenceexamples.pro
@@ -2,14 +2,16 @@ TEMPLATE = subdirs
SUBDIRS += \
adding \
- attached \
- binding \
coercion \
default \
- grouped \
properties \
- signal \
- valuesource \
methods
qtHaveModule(widgets): SUBDIRS += extended
+
+qtHaveModule(quick): SUBDIRS += \
+ attached \
+ binding \
+ grouped \
+ signal \
+ valuesource
diff --git a/examples/qml/referenceexamples/signal/main.cpp b/examples/qml/referenceexamples/signal/main.cpp
index 8abb7d4234..dce5f71a9d 100644
--- a/examples/qml/referenceexamples/signal/main.cpp
+++ b/examples/qml/referenceexamples/signal/main.cpp
@@ -71,7 +71,7 @@ int main(int argc, char ** argv)
Person *guest = party->guest(ii);
QDate rsvpDate;
- QObject *attached =
+ QObject *attached =
qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
if (attached)
rsvpDate = attached->property("rsvp").toDate();
diff --git a/examples/qml/referenceexamples/signal/signal.pro b/examples/qml/referenceexamples/signal/signal.pro
index 81692d3676..2dbc8e624b 100644
--- a/examples/qml/referenceexamples/signal/signal.pro
+++ b/examples/qml/referenceexamples/signal/signal.pro
@@ -2,7 +2,7 @@ QT += qml
SOURCES += main.cpp \
person.cpp \
- birthdayparty.cpp
+ birthdayparty.cpp
HEADERS += person.h \
birthdayparty.h
RESOURCES += signal.qrc
diff --git a/examples/qml/referenceexamples/valuesource/example.qml b/examples/qml/referenceexamples/valuesource/example.qml
index e36cf7fc4f..1357536f5f 100644
--- a/examples/qml/referenceexamples/valuesource/example.qml
+++ b/examples/qml/referenceexamples/valuesource/example.qml
@@ -54,22 +54,22 @@ BirthdayParty {
shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
}
- Boy {
- name: "Leo Hodges"
+ Boy {
+ name: "Leo Hodges"
BirthdayParty.rsvp: "2009-07-06"
shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
}
- Boy {
- name: "Jack Smith"
+ Boy {
+ name: "Jack Smith"
shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
}
- Girl {
- name: "Anne Brown"
+ Girl {
+ name: "Anne Brown"
BirthdayParty.rsvp: "2009-07-01"
shoe.size: 7
shoe.color: "red"
shoe.brand: "Marc Jacobs"
- shoe.price: 699.99
+ shoe.price: 699.99
}
// ![1]
diff --git a/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp b/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp
index e41e3ea074..50fbea6e3c 100644
--- a/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp
+++ b/examples/qml/referenceexamples/valuesource/happybirthdaysong.cpp
@@ -70,7 +70,7 @@ void HappyBirthdaySong::setName(const QString &name)
m_lyrics << "Happy birthday to you!";
m_lyrics << "";
}
-
+
void HappyBirthdaySong::advance()
{
m_line = (m_line + 1) % m_lyrics.count();
diff --git a/examples/qml/referenceexamples/valuesource/main.cpp b/examples/qml/referenceexamples/valuesource/main.cpp
index a7fba9e95e..ec88333ede 100644
--- a/examples/qml/referenceexamples/valuesource/main.cpp
+++ b/examples/qml/referenceexamples/valuesource/main.cpp
@@ -73,7 +73,7 @@ int main(int argc, char ** argv)
Person *guest = party->guest(ii);
QDate rsvpDate;
- QObject *attached =
+ QObject *attached =
qmlAttachedPropertiesObject<BirthdayParty>(guest, false);
if (attached)
rsvpDate = attached->property("rsvp").toDate();
diff --git a/examples/qml/referenceexamples/valuesource/valuesource.pro b/examples/qml/referenceexamples/valuesource/valuesource.pro
index 4ec77ff83b..01cfeeb6d8 100644
--- a/examples/qml/referenceexamples/valuesource/valuesource.pro
+++ b/examples/qml/referenceexamples/valuesource/valuesource.pro
@@ -3,7 +3,7 @@ QT += qml
SOURCES += main.cpp \
person.cpp \
birthdayparty.cpp \
- happybirthdaysong.cpp
+ happybirthdaysong.cpp
HEADERS += person.h \
birthdayparty.h \
happybirthdaysong.h
diff --git a/examples/qml/shell/main.cpp b/examples/qml/shell/main.cpp
index 45701027f4..4e8e57ab17 100644
--- a/examples/qml/shell/main.cpp
+++ b/examples/qml/shell/main.cpp
@@ -44,7 +44,7 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qscopedpointer.h>
-#include <QtGui/QGuiApplication>
+#include <QtCore/QCoreApplication>
#include <QtQml/qjsengine.h>
@@ -95,7 +95,7 @@ static void interactive(QJSEngine *eng)
int main(int argc, char *argv[])
{
- QGuiApplication app(argc, argv);
+ QCoreApplication app(argc, argv);
QScopedPointer<QJSEngine> eng(new QJSEngine());
{
QJSValue globalObject = eng->globalObject();
diff --git a/examples/qml/shell/shell.pro b/examples/qml/shell/shell.pro
index da97590189..9215108e6d 100644
--- a/examples/qml/shell/shell.pro
+++ b/examples/qml/shell/shell.pro
@@ -1,4 +1,4 @@
-QT += qml
+QT = core qml
win32: CONFIG += console
mac:CONFIG -= app_bundle
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml
index 441b7f9b82..c757fdaedd 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml
+++ b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml
@@ -49,9 +49,9 @@ Item {
anchors.centerIn: parent
width: 100; height: 100
- pieSlice: PieSlice {
+ pieSlice: PieSlice {
anchors.fill: parent
- color: "red"
+ color: "red"
}
}
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
index 6d5c7acb6c..1742334107 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
+++ b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
@@ -1,7 +1,7 @@
QT += qml quick
HEADERS += piechart.h \
- pieslice.h
+ pieslice.h
SOURCES += piechart.cpp \
pieslice.cpp \
main.cpp
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/app.qml b/examples/qml/tutorials/extending/chapter5-listproperties/app.qml
index a57d1b833f..68aa6e0c1d 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/app.qml
+++ b/examples/qml/tutorials/extending/chapter5-listproperties/app.qml
@@ -49,17 +49,17 @@ Item {
width: 100; height: 100
slices: [
- PieSlice {
+ PieSlice {
anchors.fill: parent
color: "red"
- fromAngle: 0; angleSpan: 110
+ fromAngle: 0; angleSpan: 110
},
- PieSlice {
+ PieSlice {
anchors.fill: parent
color: "black"
- fromAngle: 110; angleSpan: 50
+ fromAngle: 110; angleSpan: 50
},
- PieSlice {
+ PieSlice {
anchors.fill: parent
color: "blue"
fromAngle: 160; angleSpan: 100
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro b/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
index 7cc2b40488..ba51dd9093 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
+++ b/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
@@ -1,7 +1,7 @@
QT += qml quick
HEADERS += piechart.h \
- pieslice.h
+ pieslice.h
SOURCES += piechart.cpp \
pieslice.cpp \
main.cpp
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/app.qml b/examples/qml/tutorials/extending/chapter6-plugins/app.qml
index 417fc6651a..d5a474b8d3 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/app.qml
+++ b/examples/qml/tutorials/extending/chapter6-plugins/app.qml
@@ -48,17 +48,17 @@ Item {
width: 100; height: 100
slices: [
- PieSlice {
+ PieSlice {
anchors.fill: parent
color: "red"
- fromAngle: 0; angleSpan: 110
+ fromAngle: 0; angleSpan: 110
},
- PieSlice {
+ PieSlice {
anchors.fill: parent
color: "black"
- fromAngle: 110; angleSpan: 50
+ fromAngle: 110; angleSpan: 50
},
- PieSlice {
+ PieSlice {
anchors.fill: parent
color: "blue"
fromAngle: 160; angleSpan: 100
diff --git a/examples/qml/tutorials/extending/extending.pro b/examples/qml/tutorials/extending/extending.pro
index 967473fda0..a665975382 100644
--- a/examples/qml/tutorials/extending/extending.pro
+++ b/examples/qml/tutorials/extending/extending.pro
@@ -6,5 +6,5 @@ SUBDIRS += \
chapter3-bindings \
chapter4-customPropertyTypes \
chapter5-listproperties \
- chapter6-plugins
+ chapter6-plugins
diff --git a/examples/qmltest/qmltest/tst_basic.qml b/examples/qmltest/qmltest/tst_basic.qml
index 79bf81ab36..ee157cf155 100644
--- a/examples/qmltest/qmltest/tst_basic.qml
+++ b/examples/qmltest/qmltest/tst_basic.qml
@@ -39,7 +39,7 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.0
import QtTest 1.0
TestCase {
diff --git a/examples/quick/animation/behaviors/SideRect.qml b/examples/quick/animation/behaviors/SideRect.qml
index be7dad3466..e8b0bea826 100644
--- a/examples/quick/animation/behaviors/SideRect.qml
+++ b/examples/quick/animation/behaviors/SideRect.qml
@@ -54,8 +54,8 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
onEntered: {
- focusRect.x = myRect.x;
- focusRect.y = myRect.y;
+ focusRect.x = myRect.x;
+ focusRect.y = myRect.y;
focusRect.text = myRect.text;
}
}
diff --git a/examples/quick/animation/behaviors/tvtennis.qml b/examples/quick/animation/behaviors/tvtennis.qml
index 4ca909cd8c..b5ad2e8667 100644
--- a/examples/quick/animation/behaviors/tvtennis.qml
+++ b/examples/quick/animation/behaviors/tvtennis.qml
@@ -64,7 +64,7 @@ Rectangle {
PropertyAction { target: ball; property: "direction"; value: "right" }
}
- // Make y move with a velocity of 200
+ // Make y move with a velocity of 200
Behavior on y { SpringAnimation{ velocity: 200; }
}
diff --git a/examples/quick/animation/states/states.qml b/examples/quick/animation/states/states.qml
index 26acaf7bf0..7f3b840956 100644
--- a/examples/quick/animation/states/states.qml
+++ b/examples/quick/animation/states/states.qml
@@ -45,7 +45,7 @@ Rectangle {
width: 640; height: 480
color: "#343434"
- Image {
+ Image {
id: userIcon
x: topLeftRect.x; y: topLeftRect.y
source: "qt-logo.png"
diff --git a/examples/quick/animation/states/transitions.qml b/examples/quick/animation/states/transitions.qml
index 8216182c06..e90dde35d8 100644
--- a/examples/quick/animation/states/transitions.qml
+++ b/examples/quick/animation/states/transitions.qml
@@ -42,7 +42,7 @@ import QtQuick 2.0
/*
This is exactly the same as states.qml, except that we have appended
- a set of transitions to apply animations when the item changes
+ a set of transitions to apply animations when the item changes
between each state.
*/
@@ -51,7 +51,7 @@ Rectangle {
width: 640; height: 480
color: "#343434"
- Image {
+ Image {
id: userIcon
x: topLeftRect.x; y: topLeftRect.y
source: "qt-logo.png"
diff --git a/examples/quick/customitems/flipable/content/Card.qml b/examples/quick/customitems/flipable/content/Card.qml
index 776a8ac1b0..c34dfb288c 100644
--- a/examples/quick/customitems/flipable/content/Card.qml
+++ b/examples/quick/customitems/flipable/content/Card.qml
@@ -49,7 +49,7 @@ Flipable {
property int yAxis: 0
property int angle: 0
- width: front.width; height: front.height
+ width: front.width; height: front.height
front: Image { id: frontImage }
back: Image { source: "back.png" }
diff --git a/examples/quick/customitems/flipable/flipable.qml b/examples/quick/customitems/flipable/flipable.qml
index f47444a64d..5e809c2085 100644
--- a/examples/quick/customitems/flipable/flipable.qml
+++ b/examples/quick/customitems/flipable/flipable.qml
@@ -43,7 +43,7 @@ import "content"
Rectangle {
id: window
-
+
width: 480; height: 320
color: "darkgreen"
diff --git a/examples/quick/customitems/searchbox/SearchBox.qml b/examples/quick/customitems/searchbox/SearchBox.qml
index cab0058bce..306640ec4d 100644
--- a/examples/quick/customitems/searchbox/SearchBox.qml
+++ b/examples/quick/customitems/searchbox/SearchBox.qml
@@ -66,7 +66,7 @@ FocusScope {
font.italic: true
}
- MouseArea {
+ MouseArea {
anchors.fill: parent
onClicked: { focusScope.focus = true; Qt.inputMethod.show(); }
}
@@ -84,7 +84,7 @@ FocusScope {
source: "images/clear.png"
opacity: 0
- MouseArea {
+ MouseArea {
anchors.fill: parent
onClicked: { textInput.text = ''; focusScope.focus = true; textInput.openSoftwareInputPanel(); }
}
diff --git a/examples/quick/customitems/slideswitch/content/Switch.qml b/examples/quick/customitems/slideswitch/content/Switch.qml
index 889ceb27bc..51b7185b72 100644
--- a/examples/quick/customitems/slideswitch/content/Switch.qml
+++ b/examples/quick/customitems/slideswitch/content/Switch.qml
@@ -53,7 +53,7 @@ Item {
function toggle() {
if (toggleswitch.state == "on")
toggleswitch.state = "off";
- else
+ else
toggleswitch.state = "on";
}
//![2]
diff --git a/examples/quick/demos/tweetsearch/content/FlipBar.qml b/examples/quick/demos/tweetsearch/content/FlipBar.qml
index 4b6cd48f93..729bf68c5a 100644
--- a/examples/quick/demos/tweetsearch/content/FlipBar.qml
+++ b/examples/quick/demos/tweetsearch/content/FlipBar.qml
@@ -59,7 +59,7 @@ Item {
width: cur.width
height: cur.height
- onFrontChanged: resync();
+ onFrontChanged: resync();
onBackChanged: resync();
function resync() {//TODO: Are the items ever actually visible?
@@ -128,7 +128,7 @@ Item {
sourceItem: back
hideSource: effect.visible
}
-
+
fragmentShader: "
uniform lowp float qt_Opacity;
uniform sampler2D sourceA;
diff --git a/examples/quick/dialogs/dialogs.pro b/examples/quick/dialogs/dialogs.pro
deleted file mode 100644
index 538e75686c..0000000000
--- a/examples/quick/dialogs/dialogs.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-TEMPLATE = subdirs
-
-SUBDIRS = \
- systemdialogs
diff --git a/examples/quick/dialogs/systemdialogs/ColorDialogs.qml b/examples/quick/dialogs/systemdialogs/ColorDialogs.qml
deleted file mode 100644
index 0cb42a01aa..0000000000
--- a/examples/quick/dialogs/systemdialogs/ColorDialogs.qml
+++ /dev/null
@@ -1,146 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Dialogs 1.0
-import "../../shared"
-
-Rectangle {
- width: 320
- height: 240
- color: palette.window
- SystemPalette { id: palette }
- clip: true
-
- //! [colordialog]
- ColorDialog {
- id: colorDialog
- visible: colorDialogVisible.checked
- modality: colorDialogModal.checked ? Qt.WindowModal : Qt.NonModal
- title: "Choose a color"
- color: "green"
- showAlphaChannel: colorDialogAlpha.checked
- onAccepted: { console.log("Accepted: " + color) }
- onRejected: { console.log("Rejected") }
- }
- //! [colordialog]
-
- Column {
- anchors.fill: parent
- anchors.margins: 12
- spacing: 8
- Text {
- font.bold: true
- text: "Color dialog properties:"
- }
- CheckBox {
- id: colorDialogModal
- text: "Modal"
- checked: true
- Binding on checked { value: colorDialog.modality != Qt.NonModal }
- }
- CheckBox {
- id: colorDialogAlpha
- text: "Show alpha channel"
- Binding on checked { value: colorDialog.showAlphaChannel }
- }
- CheckBox {
- id: colorDialogVisible
- text: "Visible"
- Binding on checked { value: colorDialog.visible }
- }
- Row {
- id: colorRow
- spacing: parent.spacing
- height: colorLabel.implicitHeight * 2.0
- Rectangle {
- color: colorDialog.color
- height: parent.height
- width: height * 2
- border.color: "black"
- MouseArea {
- anchors.fill: parent
- onClicked: colorDialog.open()
- }
- }
- Text {
- id: colorLabel
- color: palette.windowText
- text: "<b>current color:</b> " + colorDialog.color
- anchors.verticalCenter: parent.verticalCenter
- }
- }
- }
-
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- height: buttonRow.height * 1.2
- color: Qt.darker(palette.window, 1.1)
- border.color: Qt.darker(palette.window, 1.3)
- Row {
- id: buttonRow
- spacing: 6
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 12
- height: implicitHeight
- width: parent.width
- Button {
- text: "Open"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: colorDialog.open()
- }
- Button {
- text: "Close"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: colorDialog.close()
- }
- Button {
- text: "set to green"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: colorDialog.color = "green"
- }
- }
- }
-}
diff --git a/examples/quick/dialogs/systemdialogs/FileDialogs.qml b/examples/quick/dialogs/systemdialogs/FileDialogs.qml
deleted file mode 100644
index d6ee1a13ca..0000000000
--- a/examples/quick/dialogs/systemdialogs/FileDialogs.qml
+++ /dev/null
@@ -1,180 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Dialogs 1.0
-import QtQuick.Window 2.0
-import "../../shared"
-
-Rectangle {
- width: 580
- height: 400
- color: palette.window
- SystemPalette { id: palette }
- clip: true
-
- //! [filedialog]
- FileDialog {
- id: fileDialog
- visible: fileDialogVisible.checked
- modality: fileDialogModal.checked ? Qt.WindowModal : Qt.NonModal
- title: fileDialogSelectFolder.checked ? "Choose a folder" :
- (fileDialogSelectMultiple.checked ? "Choose some files" : "Choose a file")
- selectExisting: fileDialogSelectExisting.checked
- selectMultiple: fileDialogSelectMultiple.checked
- selectFolder: fileDialogSelectFolder.checked
- nameFilters: [ "Image files (*.png *.jpg)", "All files (*)" ]
- selectedNameFilter: "All files (*)"
- onAccepted: {
- console.log("Accepted: " + fileUrls)
- if (fileDialogOpenFiles.checked)
- for (var i = 0; i < fileUrls.length; ++i)
- Qt.openUrlExternally(fileUrls[i])
- }
- onRejected: { console.log("Rejected") }
- }
- //! [filedialog]
-
- Column {
- anchors.fill: parent
- anchors.margins: 12
- spacing: 8
- Text {
- color: palette.windowText
- font.bold: true
- text: "File dialog properties:"
- }
- CheckBox {
- id: fileDialogModal
- text: "Modal"
- checked: true
- Binding on checked { value: fileDialog.modality != Qt.NonModal }
- }
- CheckBox {
- id: fileDialogSelectFolder
- text: "Select Folder"
- Binding on checked { value: fileDialog.selectFolder }
- }
- CheckBox {
- id: fileDialogSelectExisting
- text: "Select Existing Files"
- checked: true
- Binding on checked { value: fileDialog.selectExisting }
- }
- CheckBox {
- id: fileDialogSelectMultiple
- text: "Select Multiple Files"
- Binding on checked { value: fileDialog.selectMultiple }
- }
- CheckBox {
- id: fileDialogOpenFiles
- text: "Open Files After Accepting"
- }
- CheckBox {
- id: fileDialogVisible
- text: "Visible"
- Binding on checked { value: fileDialog.visible }
- }
- Text {
- color: palette.windowText
- text: "<b>current view folder:</b> " + fileDialog.folder
- }
- Text {
- color: palette.windowText
- text: "<b>name filters:</b> {" + fileDialog.nameFilters + "}"
- width: parent.width
- wrapMode: Text.Wrap
- }
- Text {
- color: palette.windowText
- text: "<b>current filter:</b>" + fileDialog.selectedNameFilter
- width: parent.width
- wrapMode: Text.Wrap
- }
- Text {
- color: palette.windowText
- text: "<b>chosen files:</b> " + fileDialog.fileUrls
- width: parent.width
- wrapMode: Text.Wrap
- }
- Text {
- color: palette.windowText
- text: "<b>chosen single path:</b> " + fileDialog.fileUrl
- width: parent.width
- wrapMode: Text.Wrap
- }
- }
-
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- height: buttonRow.height * 1.2
- color: Qt.darker(palette.window, 1.1)
- border.color: Qt.darker(palette.window, 1.3)
- Row {
- id: buttonRow
- spacing: 6
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 12
- height: implicitHeight
- width: parent.width
- Button {
- text: "Open"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: fileDialog.open()
- }
- Button {
- text: "Close"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: fileDialog.close()
- }
- Button {
- text: "go to /tmp"
- anchors.verticalCenter: parent.verticalCenter
- // TODO: QTBUG-29814 This isn't portable, but we don't expose QDir::tempPath to QML yet.
- onClicked: fileDialog.folder = (Qt.platform.os === "windows" ? "/c:/temp" : "/tmp")
- }
- }
- }
-}
diff --git a/examples/quick/dialogs/systemdialogs/FontDialogs.qml b/examples/quick/dialogs/systemdialogs/FontDialogs.qml
deleted file mode 100644
index 7d4328994b..0000000000
--- a/examples/quick/dialogs/systemdialogs/FontDialogs.qml
+++ /dev/null
@@ -1,153 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-import QtQuick.Dialogs 1.1
-import "../../shared"
-
-Rectangle {
- width: 320
- height: 360
- color: palette.window
- SystemPalette { id: palette }
- clip: true
-
- FontDialog {
- id: fontDialog
- visible: fontDialogVisible.checked
- modality: fontDialogModal.checked ? Qt.WindowModal : Qt.NonModal
- scalableFonts: fontDialogScalableFonts.checked
- nonScalableFonts: fontDialogNonScalableFonts.checked
- monospacedFonts: fontDialogMonospacedFonts.checked
- proportionalFonts: fontDialogProportionalFonts.checked
- title: "Choose a font"
- font: Qt.font({ family: "Arial", pointSize: 24, weight: Font.Normal })
- onAccepted: { console.log("Accepted: " + font) }
- onRejected: { console.log("Rejected") }
- }
-
- Column {
- id: optionsColumn
- anchors.fill: parent
- anchors.margins: 12
- spacing: 8
- Text {
- font.bold: true
- text: "Font dialog properties:"
- }
- CheckBox {
- id: fontDialogModal
- text: "Modal"
- checked: true
- Binding on checked { value: fontDialog.modality != Qt.NonModal }
- }
- CheckBox {
- id: fontDialogScalableFonts
- text: "Scalable fonts"
- Binding on checked { value: fontDialog.scalableFonts }
- }
- CheckBox {
- id: fontDialogNonScalableFonts
- text: "Non scalable fonts"
- Binding on checked { value: fontDialog.nonScalableFonts }
- }
- CheckBox {
- id: fontDialogMonospacedFonts
- text: "Monospaced fonts"
- Binding on checked { value: fontDialog.monospacedFonts }
- }
- CheckBox {
- id: fontDialogProportionalFonts
- text: "Proportional fonts"
- Binding on checked { value: fontDialog.proportionalFonts }
- }
- CheckBox {
- id: fontDialogVisible
- text: "Visible"
- Binding on checked { value: fontDialog.visible }
- }
- Text {
- text: "Current font:"
- }
- Text {
- id: fontLabel
- color: palette.windowText
- text: "<b>" + fontDialog.font.family + " - " + fontDialog.font.pointSize + "</b>"
- MouseArea {
- anchors.fill: parent
- onClicked: fontDialog.open()
- }
- }
- }
-
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- height: buttonRow.height * 1.2
- color: Qt.darker(palette.window, 1.1)
- border.color: Qt.darker(palette.window, 1.3)
- Row {
- id: buttonRow
- spacing: 6
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 12
- width: parent.width
- Button {
- text: "Open"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: fontDialog.open()
- }
- Button {
- text: "Close"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: fontDialog.close()
- }
- Button {
- text: "set to default"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: fontDialog.font = Qt.font({ family: "Arial", pointSize: 24, weight: Font.Normal })
- }
- }
- }
-}
diff --git a/examples/quick/dialogs/systemdialogs/MessageDialogs.qml b/examples/quick/dialogs/systemdialogs/MessageDialogs.qml
deleted file mode 100644
index 9c70228046..0000000000
--- a/examples/quick/dialogs/systemdialogs/MessageDialogs.qml
+++ /dev/null
@@ -1,307 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Dialogs 1.1
-import QtQuick.Window 2.0
-import "../../shared"
-
-Rectangle {
- width: 580
- height: 400
- color: palette.window
- SystemPalette { id: palette }
- clip: true
-
- //! [messagedialog]
- MessageDialog {
- id: messageDialog
- visible: messageDialogVisible.checked
- modality: messageDialogModal.checked ? Qt.WindowModal : Qt.NonModal
- title: windowTitleField.text
- text: customizeText.checked ? textField.text : ""
- informativeText: customizeInformativeText.checked ? informativeTextField.text : ""
- detailedText: customizeDetailedText.checked ? detailedTextField.text : ""
- onButtonClicked: console.log("clicked button " + clickedButton)
- onAccepted: lastChosen.text = "Accepted " +
- (clickedButton == StandardButton.Ok ? "(OK)" : (clickedButton == StandardButton.Retry ? "(Retry)" : "(Ignore)"))
- onRejected: lastChosen.text = "Rejected " +
- (clickedButton == StandardButton.Close ? "(Close)" : (clickedButton == StandardButton.Abort ? "(Abort)" : "(Cancel)"))
- onHelp: lastChosen.text = "Yelped for help!"
- onYes: lastChosen.text = (clickedButton == StandardButton.Yes ? "Yeessss!!" : "Yes, now and always")
- onNo: lastChosen.text = (clickedButton == StandardButton.No ? "Oh No." : "No, no, a thousand times no!")
- onApply: lastChosen.text = "Apply"
- onReset: lastChosen.text = "Reset"
- }
- //! [messagedialog]
-
- Column {
- anchors.fill: parent
- anchors.margins: 12
- spacing: 8
- Text {
- color: palette.windowText
- font.bold: true
- text: "Message dialog properties:"
- }
- CheckBox {
- id: messageDialogModal
- text: "Modal"
- checked: true
- Binding on checked { value: messageDialog.modality != Qt.NonModal }
- }
- CheckBox {
- id: customizeTitle
- text: "Window Title"
- checked: true
- width: parent.width
- TextField {
- id: windowTitleField
- anchors.right: parent.right
- width: informativeTextField.width
- text: "Alert"
- }
- }
- Row {
- spacing: 8
- property bool updating: false
- function updateIcon(icon, checked) {
- if (updating) return
- updating = true
- messageDialog.icon = (checked ? icon : StandardIcon.NoIcon)
- for (var i = 0; i < children.length; ++i)
- if (children[i].icon !== icon)
- children[i].checked = false
- updating = false
- }
-
- CheckBox {
- id: iconInformation
- text: "Information"
- property int icon: StandardIcon.Information
- onCheckedChanged: parent.updateIcon(icon, checked)
- }
-
- CheckBox {
- id: iconWarning
- text: "Warning"
- checked: true
- property int icon: StandardIcon.Warning
- onCheckedChanged: parent.updateIcon(icon, checked)
- Component.onCompleted: parent.updateIcon(icon, true)
- }
-
- CheckBox {
- id: iconCritical
- text: "Critical"
- property int icon: StandardIcon.Critical
- onCheckedChanged: parent.updateIcon(icon, checked)
- }
-
- CheckBox {
- id: iconQuestion
- text: "Question"
- property int icon: StandardIcon.Question
- onCheckedChanged: parent.updateIcon(icon, checked)
- }
- }
-
- CheckBox {
- id: customizeText
- text: "Primary Text"
- checked: true
- width: parent.width
- TextField {
- id: textField
- anchors.right: parent.right
- width: informativeTextField.width
- text: "Attention Please"
- }
- }
- CheckBox {
- id: customizeInformativeText
- text: "Informative Text"
- checked: true
- width: parent.width
- TextField {
- id: informativeTextField
- anchors.right: parent.right
- width: parent.width - parent.row.spacing - parent.row.width
- text: "Be alert!"
- }
- }
- Text {
- text: "Buttons:"
- }
- Flow {
- spacing: 8
- width: parent.width
- property bool updating: false
- function updateButtons(button, checked) {
- if (updating) return
- updating = true
- var buttons = 0
- for (var i = 0; i < children.length; ++i)
- if (children[i].checked)
- buttons |= children[i].button
- if (!buttons)
- buttons = StandardButton.Ok
- messageDialog.standardButtons = buttons
- updating = false
- }
-
- CheckBox {
- text: "Help"
- property int button: StandardButton.Help
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "Abort"
- property int button: StandardButton.Abort
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "Close"
- property int button: StandardButton.Close
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "Cancel"
- property int button: StandardButton.Cancel
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "NoToAll"
- property int button: StandardButton.NoToAll
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "No"
- property int button: StandardButton.No
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "YesToAll"
- property int button: StandardButton.YesToAll
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "Yes"
- property int button: StandardButton.Yes
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "Ignore"
- property int button: StandardButton.Ignore
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "Retry"
- property int button: StandardButton.Retry
- onCheckedChanged: parent.updateButtons(button, checked)
- }
-
- CheckBox {
- text: "OK"
- checked: true
- property int button: StandardButton.Ok
- onCheckedChanged: parent.updateButtons(button, checked)
- }
- }
- CheckBox {
- id: customizeDetailedText
- text: "Detailed Text"
- checked: true
- width: parent.width
- TextField {
- id: detailedTextField
- anchors.right: parent.right
- width: informativeTextField.width
- text: "The world needs more lerts."
- }
- }
- CheckBox {
- id: messageDialogVisible
- text: "Visible"
- Binding on checked { value: messageDialog.visible }
- }
- Text {
- id: lastChosen
- }
- }
-
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- height: buttonRow.height * 1.2
- color: Qt.darker(palette.window, 1.1)
- border.color: Qt.darker(palette.window, 1.3)
- Row {
- id: buttonRow
- spacing: 6
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 12
- width: parent.width
- Button {
- text: "Open"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: messageDialog.open()
- }
- Button {
- text: "Close"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: messageDialog.close()
- }
- }
- }
-}
diff --git a/examples/quick/dialogs/systemdialogs/doc/images/systemdialogs-example.jpg b/examples/quick/dialogs/systemdialogs/doc/images/systemdialogs-example.jpg
deleted file mode 100644
index 4517a39308..0000000000
--- a/examples/quick/dialogs/systemdialogs/doc/images/systemdialogs-example.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/dialogs/systemdialogs/doc/src/systemdialogs.qdoc b/examples/quick/dialogs/systemdialogs/doc/src/systemdialogs.qdoc
deleted file mode 100644
index 9788be7343..0000000000
--- a/examples/quick/dialogs/systemdialogs/doc/src/systemdialogs.qdoc
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-/*!
- \title Qt Quick System Dialog Examples
- \example systemdialogs
- \brief This example demonstrates the system dialog types in QML
- \image systemdialogs-example.jpg
- \ingroup qtquickdialog_examples
-
- This example demonstrates the system dialogs in the \l{Qt Quick Dialogs}
- module. The appearance and behavior is platform-dependent.
-
- A \l FileDialog is used to choose a single file, multiple files or a
- single directory, depending on how it is configured.
- \snippet systemdialogs/FileDialogs.qml filedialog
-
- A \l ColorDialog is used to choose a color, with or without alpha (transparency)
- depending on how it is configured.
- \snippet systemdialogs/ColorDialogs.qml colordialog
-
- The example can be built as a standalone executable, but each
- type of dialog is demonstrated in a separate QML file which can
- also be run separately with qmlscene.
-*/
diff --git a/examples/quick/dialogs/systemdialogs/systemdialogs.pro b/examples/quick/dialogs/systemdialogs/systemdialogs.pro
deleted file mode 100644
index 323ea2fac7..0000000000
--- a/examples/quick/dialogs/systemdialogs/systemdialogs.pro
+++ /dev/null
@@ -1,15 +0,0 @@
-TEMPLATE = app
-
-QT += quick qml
-SOURCES += main.cpp
-RESOURCES += systemdialogs.qrc ../../shared/shared.qrc
-
-OTHER_FILES += \
- systemdialogs.qml \
- FileDialogs.qml \
- ColorDialogs.qml \
- FontDialogs.qml \
- MessageDialogs.qml
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/dialogs/systemdialogs
-INSTALLS += target
diff --git a/examples/quick/dialogs/systemdialogs/systemdialogs.qrc b/examples/quick/dialogs/systemdialogs/systemdialogs.qrc
deleted file mode 100644
index 2193088cb9..0000000000
--- a/examples/quick/dialogs/systemdialogs/systemdialogs.qrc
+++ /dev/null
@@ -1,9 +0,0 @@
-<RCC>
- <qresource prefix="/dialogs/systemdialogs">
- <file>systemdialogs.qml</file>
- <file>FileDialogs.qml</file>
- <file>ColorDialogs.qml</file>
- <file>FontDialogs.qml</file>
- <file>MessageDialogs.qml</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/imageelements/content/ImageCell.qml b/examples/quick/imageelements/content/ImageCell.qml
index 4b3fee3522..d7679e3fff 100644
--- a/examples/quick/imageelements/content/ImageCell.qml
+++ b/examples/quick/imageelements/content/ImageCell.qml
@@ -52,7 +52,7 @@ Item {
clip: true // only makes a difference if mode is PreserveAspectCrop
}
- Text {
+ Text {
id: captionItem
anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom
}
diff --git a/examples/quick/imageprovider/imageprovider.cpp b/examples/quick/imageprovider/imageprovider.cpp
index 873b812d8a..31290578fc 100644
--- a/examples/quick/imageprovider/imageprovider.cpp
+++ b/examples/quick/imageprovider/imageprovider.cpp
@@ -63,7 +63,7 @@ public:
if (size)
*size = QSize(width, height);
QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width,
- requestedSize.height() > 0 ? requestedSize.height() : height);
+ requestedSize.height() > 0 ? requestedSize.height() : height);
pixmap.fill(QColor(id).rgba());
//![0]
diff --git a/examples/quick/keyinteraction/focus/Core/ContextMenu.qml b/examples/quick/keyinteraction/focus/Core/ContextMenu.qml
index 3bbce04b07..ff69f0b81d 100644
--- a/examples/quick/keyinteraction/focus/Core/ContextMenu.qml
+++ b/examples/quick/keyinteraction/focus/Core/ContextMenu.qml
@@ -54,7 +54,7 @@ FocusScope {
focus: true
Keys.onRightPressed: mainView.focus = true
- Text {
+ Text {
anchors { top: parent.top; horizontalCenter: parent.horizontalCenter; margins: 30 }
color: "black"
font.pixelSize: 14
diff --git a/examples/quick/keyinteraction/focus/Core/GridMenu.qml b/examples/quick/keyinteraction/focus/Core/GridMenu.qml
index 0fba859466..22016c37d2 100644
--- a/examples/quick/keyinteraction/focus/Core/GridMenu.qml
+++ b/examples/quick/keyinteraction/focus/Core/GridMenu.qml
@@ -44,7 +44,7 @@ FocusScope {
property alias interactive: gridView.interactive
onActiveFocusChanged: {
- if (activeFocus)
+ if (activeFocus)
mainView.state = "showGridViews"
}
diff --git a/examples/quick/keyinteraction/focus/Core/ListMenu.qml b/examples/quick/keyinteraction/focus/Core/ListMenu.qml
index 27ed804f63..8ca751b7f1 100644
--- a/examples/quick/keyinteraction/focus/Core/ListMenu.qml
+++ b/examples/quick/keyinteraction/focus/Core/ListMenu.qml
@@ -44,7 +44,7 @@ FocusScope {
clip: true
onActiveFocusChanged: {
- if (activeFocus)
+ if (activeFocus)
mainView.state = "showListViews"
}
diff --git a/examples/quick/keyinteraction/focus/Core/TabMenu.qml b/examples/quick/keyinteraction/focus/Core/TabMenu.qml
index a803e5289b..470252f4da 100644
--- a/examples/quick/keyinteraction/focus/Core/TabMenu.qml
+++ b/examples/quick/keyinteraction/focus/Core/TabMenu.qml
@@ -42,7 +42,7 @@ import QtQuick 2.1
FocusScope {
onActiveFocusChanged: {
- if (activeFocus)
+ if (activeFocus)
mainView.state = "showTabViews"
}
diff --git a/examples/quick/keyinteraction/focus/focus.qml b/examples/quick/keyinteraction/focus/focus.qml
index 4e58d4b8cc..11139cd361 100644
--- a/examples/quick/keyinteraction/focus/focus.qml
+++ b/examples/quick/keyinteraction/focus/focus.qml
@@ -43,7 +43,7 @@ import "Core"
Rectangle {
id: window
-
+
width: 800; height: 640
color: "#3E606F"
@@ -73,11 +73,11 @@ Rectangle {
activeFocusOnTab: true
}
- Rectangle {
+ Rectangle {
id: shade
anchors.fill: parent
color: "black"
- opacity: 0
+ opacity: 0
}
states: [
diff --git a/examples/quick/models/abstractitemmodel/model.h b/examples/quick/models/abstractitemmodel/model.h
index be6a6b4933..b90e8ef039 100644
--- a/examples/quick/models/abstractitemmodel/model.h
+++ b/examples/quick/models/abstractitemmodel/model.h
@@ -41,7 +41,7 @@
#include <QStringList>
//![0]
-class Animal
+class Animal
{
public:
Animal(const QString &type, const QString &size);
diff --git a/examples/quick/models/stringlistmodel/stringlistmodel.pro b/examples/quick/models/stringlistmodel/stringlistmodel.pro
index 2d1f99d4ed..fe561083f7 100644
--- a/examples/quick/models/stringlistmodel/stringlistmodel.pro
+++ b/examples/quick/models/stringlistmodel/stringlistmodel.pro
@@ -1,6 +1,6 @@
QT += qml quick
-SOURCES += main.cpp
+SOURCES += main.cpp
RESOURCES += stringlistmodel.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/quick/models/stringlistmodel
diff --git a/examples/quick/particles/affectors/content/spritegoal.qml b/examples/quick/particles/affectors/content/spritegoal.qml
index ab108bb065..f5702fb9a7 100644
--- a/examples/quick/particles/affectors/content/spritegoal.qml
+++ b/examples/quick/particles/affectors/content/spritegoal.qml
@@ -149,7 +149,7 @@ Item {
Item {
id: circle
- x: root.width / 1.2
+ x: root.width / 1.2
y: root.height / 1.7
property real percent: 0
@@ -167,7 +167,7 @@ Item {
}
ImageParticle {
- z:0
+ z:0
system: sys
groups: ["exhaust"]
source: "qrc:///particleresources/fuzzydot.png"
@@ -199,7 +199,7 @@ Item {
lifeSpan: 500
y: holder.y
- x: holder.x
+ x: holder.x
velocity: PointDirection { xVariation: 40; yVariation: 40; }
velocityFromMovement: 16
diff --git a/examples/quick/particles/affectors/content/wander.qml b/examples/quick/particles/affectors/content/wander.qml
index f28aa03459..da0dcf261e 100644
--- a/examples/quick/particles/affectors/content/wander.qml
+++ b/examples/quick/particles/affectors/content/wander.qml
@@ -57,7 +57,7 @@ Rectangle {
}
//! [0]
- Wander {
+ Wander {
id: wanderer
system: particles
anchors.fill: parent
diff --git a/examples/quick/particles/customparticle/content/blurparticles.qml b/examples/quick/particles/customparticle/content/blurparticles.qml
index a5abb07ce6..583d5c251c 100644
--- a/examples/quick/particles/customparticle/content/blurparticles.qml
+++ b/examples/quick/particles/customparticle/content/blurparticles.qml
@@ -67,14 +67,14 @@ Rectangle {
}
CustomParticle {
- system: sys
+ system: sys
//! [vertex]
vertexShader:"
uniform lowp float qt_Opacity;
varying lowp float fFade;
varying lowp float fBlur;
- void main() {
+ void main() {
defaultMain();
highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
highp float fadeIn = min(t * 10., 1.);
diff --git a/examples/quick/particles/customparticle/content/fragmentshader.qml b/examples/quick/particles/customparticle/content/fragmentshader.qml
index ed61720419..04646f811e 100644
--- a/examples/quick/particles/customparticle/content/fragmentshader.qml
+++ b/examples/quick/particles/customparticle/content/fragmentshader.qml
@@ -73,7 +73,7 @@ ParticleSystem {
varying lowp float fFade;
varying highp vec2 fPos;
- void main() {
+ void main() {
qt_TexCoord0 = qt_ParticleTex;
highp float size = qt_ParticleData.z;
highp float endSize = qt_ParticleData.w;
diff --git a/examples/quick/particles/customparticle/content/imagecolors.qml b/examples/quick/particles/customparticle/content/imagecolors.qml
index 3fb4c9f378..0702e33a2d 100644
--- a/examples/quick/particles/customparticle/content/imagecolors.qml
+++ b/examples/quick/particles/customparticle/content/imagecolors.qml
@@ -81,7 +81,7 @@ Rectangle {
varying lowp float fFade;
uniform lowp float qt_Opacity;
- void main() {
+ void main() {
fTex2 = vec2(qt_ParticlePos.x, qt_ParticlePos.y);
//Uncomment this next line for each particle to use full texture, instead of the solid color at the center of the particle.
diff --git a/examples/quick/particles/imageparticle/content/allatonce.qml b/examples/quick/particles/imageparticle/content/allatonce.qml
index 737b6955e2..068093cc19 100644
--- a/examples/quick/particles/imageparticle/content/allatonce.qml
+++ b/examples/quick/particles/imageparticle/content/allatonce.qml
@@ -46,7 +46,7 @@ Rectangle {
width: 640
height: 480
ParticleSystem {
- id: sys
+ id: sys
}
ImageParticle {
diff --git a/examples/quick/particles/itemparticle/content/Delegate2.qml b/examples/quick/particles/itemparticle/content/Delegate2.qml
index ba6d725a45..d4cb81261d 100644
--- a/examples/quick/particles/itemparticle/content/Delegate2.qml
+++ b/examples/quick/particles/itemparticle/content/Delegate2.qml
@@ -43,7 +43,7 @@ import QtQuick 2.0
//![0]
Package {
Item { id: gridDelegate; width: w; height: h; Package.name: 'grid' }
- Item { id: particleDelegate; width: w; height: h; Package.name: 'particles'
+ Item { id: particleDelegate; width: w; height: h; Package.name: 'particles'
Rectangle {
id: wrapper
diff --git a/examples/quick/particles/itemparticle/content/ExpandingDelegate.qml b/examples/quick/particles/itemparticle/content/ExpandingDelegate.qml
index c2a679b4ef..28e490787c 100644
--- a/examples/quick/particles/itemparticle/content/ExpandingDelegate.qml
+++ b/examples/quick/particles/itemparticle/content/ExpandingDelegate.qml
@@ -103,7 +103,7 @@ import "../../../modelviews/listview/content"
width: background.width - recipeImage.width - 20; height: recipeImage.height
spacing: 5
- Text {
+ Text {
text: title
font.bold: true; font.pointSize: 16
}
@@ -185,7 +185,7 @@ import "../../../modelviews/listview/content"
}
transitions: Transition {
- //The only strictly necessary particle specific lines
+ //The only strictly necessary particle specific lines
to: "Details"
reversible: true
ScriptAction {script: {
diff --git a/examples/quick/particles/itemparticle/particleview.qml b/examples/quick/particles/itemparticle/particleview.qml
index 2637e13107..89dcf61a05 100644
--- a/examples/quick/particles/itemparticle/particleview.qml
+++ b/examples/quick/particles/itemparticle/particleview.qml
@@ -224,7 +224,7 @@ Item {
anchors.centerIn: parent
antialiasing: true;
source: "http://" + Script.getImagePath(content); cache: true
- fillMode: Image.PreserveAspectFit;
+ fillMode: Image.PreserveAspectFit;
width: parent.width-4; height: parent.height-4
onStatusChanged: if (img.status == Image.Ready) {
loading.opacity = 0;
diff --git a/examples/quick/positioners/positioners-transitions.qml b/examples/quick/positioners/positioners-transitions.qml
index 64ee15af32..8341d6c442 100644
--- a/examples/quick/positioners/positioners-transitions.qml
+++ b/examples/quick/positioners/positioners-transitions.qml
@@ -73,7 +73,7 @@ Rectangle {
width: 100; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -86,7 +86,7 @@ Rectangle {
width: 100; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -129,7 +129,7 @@ Rectangle {
width: 50; height: 100
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -161,7 +161,7 @@ Rectangle {
width: 50; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -174,7 +174,7 @@ Rectangle {
width: 50; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -187,7 +187,7 @@ Rectangle {
width: 50; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -226,7 +226,7 @@ Rectangle {
width: 60; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
@@ -239,20 +239,20 @@ Rectangle {
width: 60; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 }
- Rectangle {
+ Rectangle {
id: blueF3
visible: opacity != 0
width: 40; height: 50
color: "lightsteelblue"
border.color: "black"
- radius: 15
+ radius: 15
Behavior on opacity { NumberAnimation {} }
opacity: effectiveOpacity
}
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index 027faaa4c9..1f96111b04 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -21,7 +21,6 @@ SUBDIRS = quick-accessibility \
customitems \
imageprovider \
window \
- dialogs \
particles \
demos
diff --git a/examples/quick/text/textselection/textselection.qml b/examples/quick/text/textselection/textselection.qml
index 80ce532369..047a3e7b79 100644
--- a/examples/quick/text/textselection/textselection.qml
+++ b/examples/quick/text/textselection/textselection.qml
@@ -137,9 +137,9 @@ Rectangle {
Text { anchors.centerIn: parent; text: "Cut" }
- MouseArea {
+ MouseArea {
anchors.fill: parent
- onClicked: { edit.cut(); editor.state = "" }
+ onClicked: { edit.cut(); editor.state = "" }
}
}
@@ -152,9 +152,9 @@ Rectangle {
Text { anchors.centerIn: parent; text: "Copy" }
- MouseArea {
+ MouseArea {
anchors.fill: parent
- onClicked: { edit.copy(); editor.state = "selection" }
+ onClicked: { edit.copy(); editor.state = "selection" }
}
}
@@ -167,9 +167,9 @@ Rectangle {
Text { anchors.centerIn: parent; text: "Paste" }
- MouseArea {
+ MouseArea {
anchors.fill: parent
- onClicked: { edit.paste(); edit.cursorPosition = edit.selectionEnd; editor.state = "" }
+ onClicked: { edit.paste(); edit.cursorPosition = edit.selectionEnd; editor.state = "" }
}
}
@@ -182,13 +182,13 @@ Rectangle {
Text { anchors.centerIn: parent; text: "Deselect" }
- MouseArea {
+ MouseArea {
anchors.fill: parent
- onClicked: {
+ onClicked: {
edit.cursorPosition = edit.selectionEnd;
edit.deselect();
- editor.state = ""
- }
+ editor.state = ""
+ }
}
}
}
diff --git a/examples/quick/touchinteraction/flickable/corkboards.qml b/examples/quick/touchinteraction/flickable/corkboards.qml
index 34b0e3108a..3f04c49073 100644
--- a/examples/quick/touchinteraction/flickable/corkboards.qml
+++ b/examples/quick/touchinteraction/flickable/corkboards.qml
@@ -50,13 +50,13 @@ Rectangle {
ListElement {
name: "Panel One"
- notes: [
+ notes: [
ListElement { noteText: "Tap to edit" },
ListElement { noteText: "Drag to move" },
ListElement { noteText: "Flick to scroll" }
]
}
-
+
ListElement {
name: "Panel Two"
notes: [
diff --git a/examples/quick/tutorials/samegame/samegame1/samegame.qml b/examples/quick/tutorials/samegame/samegame1/samegame.qml
index 83ab84a4cf..fa87d85f97 100644
--- a/examples/quick/tutorials/samegame/samegame1/samegame.qml
+++ b/examples/quick/tutorials/samegame/samegame1/samegame.qml
@@ -68,7 +68,7 @@ Rectangle {
Button {
anchors { left: parent.left; verticalCenter: parent.verticalCenter }
- text: "New Game"
+ text: "New Game"
onClicked: console.log("This doesn't do anything yet...")
}
diff --git a/examples/quick/tutorials/samegame/samegame3/Block.qml b/examples/quick/tutorials/samegame/samegame3/Block.qml
index cd382f85b8..ff62bb5ec4 100644
--- a/examples/quick/tutorials/samegame/samegame3/Block.qml
+++ b/examples/quick/tutorials/samegame/samegame3/Block.qml
@@ -53,7 +53,7 @@ Item {
source: {
if (type == 0)
return "../shared/pics/redStone.png";
- else if (type == 1)
+ else if (type == 1)
return "../shared/pics/blueStone.png";
else
return "../shared/pics/greenStone.png";
diff --git a/examples/quick/tutorials/samegame/samegame3/samegame.js b/examples/quick/tutorials/samegame/samegame3/samegame.js
index df5bdfb049..01edc5bd41 100644
--- a/examples/quick/tutorials/samegame/samegame3/samegame.js
+++ b/examples/quick/tutorials/samegame/samegame3/samegame.js
@@ -160,7 +160,7 @@ function victoryCheck() {
}
//![2]
-//only floods up and right, to see if it can find adjacent same-typed blocks
+//only floods up and right, to see if it can find adjacent same-typed blocks
function floodMoveCheck(column, row, type) {
if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return false;
diff --git a/examples/quick/tutorials/samegame/samegame4/content/samegame.js b/examples/quick/tutorials/samegame/samegame4/content/samegame.js
index 7f1c976480..80b175d450 100755
--- a/examples/quick/tutorials/samegame/samegame4/content/samegame.js
+++ b/examples/quick/tutorials/samegame/samegame4/content/samegame.js
@@ -177,7 +177,7 @@ function victoryCheck() {
}
//![4]
-//only floods up and right, to see if it can find adjacent same-typed blocks
+//only floods up and right, to see if it can find adjacent same-typed blocks
function floodMoveCheck(column, row, type) {
if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return false;
diff --git a/examples/quick/tutorials/samegame/samegame4/highscores/scores.php b/examples/quick/tutorials/samegame/samegame4/highscores/scores.php
index daf480e21b..86e4187acd 100755
--- a/examples/quick/tutorials/samegame/samegame4/highscores/scores.php
+++ b/examples/quick/tutorials/samegame/samegame4/highscores/scores.php
@@ -8,8 +8,8 @@
$time = $_POST["time"];
if($name == "")
$name = "Anonymous";
- $file = fopen("score_data.xml", "a");
- $ret = fwrite($file, "<record><score>". $score . "</score><name>"
+ $file = fopen("score_data.xml", "a");
+ $ret = fwrite($file, "<record><score>". $score . "</score><name>"
. $name . "</name><gridSize>" . $grid . "</gridSize><seconds>"
. $time . "</seconds></record>\n");
echo "Your score has been recorded. Thanks for playing!";
@@ -18,7 +18,7 @@
}else{#Read high score list
#Now uses XSLT to display. So just print the file. With XML cruft added.
#Note that firefox at least won't apply the XSLT on a php file. So redirecting
- $file = fopen("scores.xml", "w");
+ $file = fopen("scores.xml", "w");
$ret = fwrite($file, '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n"
. '<?xml-stylesheet type="text/xsl" href="score_style.xsl"?>' . "\n"
. "<records>\n" . file_get_contents("score_data.xml") . "</records>\n");
diff --git a/examples/quick/views/listview/content/RecipesModel.qml b/examples/quick/views/listview/content/RecipesModel.qml
index 0cdb8919b6..9830aa60d0 100644
--- a/examples/quick/views/listview/content/RecipesModel.qml
+++ b/examples/quick/views/listview/content/RecipesModel.qml
@@ -44,20 +44,20 @@ ListModel {
ListElement {
title: "Pancakes"
picture: "content/pics/pancakes.jpg"
- ingredients: "<html>
- <ul>
- <li> 1 cup (150g) self-raising flour
- <li> 1 tbs caster sugar
- <li> 3/4 cup (185ml) milk
- <li> 1 egg
- </ul>
+ ingredients: "<html>
+ <ul>
+ <li> 1 cup (150g) self-raising flour
+ <li> 1 tbs caster sugar
+ <li> 3/4 cup (185ml) milk
+ <li> 1 egg
+ </ul>
</html>"
- method: "<html>
- <ol>
- <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
- <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
- <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
- <li> Turn over and cook other side until golden.
+ method: "<html>
+ <ol>
+ <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
+ <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
+ <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
+ <li> Turn over and cook other side until golden.
</ol>
</html>"
}
@@ -70,60 +70,60 @@ ListModel {
ListElement {
title: "Vegetable Soup"
picture: "content/pics/vegetable-soup.jpg"
- ingredients: "<html>
- <ul>
- <li> 1 onion
- <li> 1 turnip
- <li> 1 potato
- <li> 1 carrot
- <li> 1 head of celery
- <li> 1 1/2 litres of water
- </ul>
+ ingredients: "<html>
+ <ul>
+ <li> 1 onion
+ <li> 1 turnip
+ <li> 1 potato
+ <li> 1 carrot
+ <li> 1 head of celery
+ <li> 1 1/2 litres of water
+ </ul>
</html>"
- method: "<html>
- <ol>
- <li> Chop vegetables.
- <li> Boil in water until vegetables soften.
- <li> Season with salt and pepper to taste.
- </ol>
+ method: "<html>
+ <ol>
+ <li> Chop vegetables.
+ <li> Boil in water until vegetables soften.
+ <li> Season with salt and pepper to taste.
+ </ol>
</html>"
}
ListElement {
title: "Hamburger"
picture: "content/pics/hamburger.jpg"
- ingredients: "<html>
- <ul>
- <li> 500g minced beef
- <li> Seasoning
- <li> lettuce, tomato, onion, cheese
- <li> 1 hamburger bun for each burger
- </ul>
+ ingredients: "<html>
+ <ul>
+ <li> 500g minced beef
+ <li> Seasoning
+ <li> lettuce, tomato, onion, cheese
+ <li> 1 hamburger bun for each burger
+ </ul>
</html>"
- method: "<html>
- <ol>
- <li> Mix the beef, together with seasoning, in a food processor.
- <li> Shape the beef into burgers.
- <li> Grill the burgers for about 5 mins on each side (until cooked through)
- <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
- </ol>
+ method: "<html>
+ <ol>
+ <li> Mix the beef, together with seasoning, in a food processor.
+ <li> Shape the beef into burgers.
+ <li> Grill the burgers for about 5 mins on each side (until cooked through)
+ <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
+ </ol>
</html>"
}
ListElement {
title: "Lemonade"
picture: "content/pics/lemonade.jpg"
- ingredients: "<html>
- <ul>
- <li> 1 cup Lemon Juice
- <li> 1 cup Sugar
- <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
- </ul>
+ ingredients: "<html>
+ <ul>
+ <li> 1 cup Lemon Juice
+ <li> 1 cup Sugar
+ <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
+ </ul>
</html>"
- method: "<html>
- <ol>
- <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
- <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
- <li> Chill or serve over ice cubes.
- </ol>
+ method: "<html>
+ <ol>
+ <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
+ <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
+ <li> Chill or serve over ice cubes.
+ </ol>
</html>"
}
}
diff --git a/src/imports/dialogs/qml/DefaultWindowDecoration.qml b/examples/quick/views/listview/displaymargin.qml
index ec930101d2..c3402f6baa 100644
--- a/src/imports/dialogs/qml/DefaultWindowDecoration.qml
+++ b/examples/quick/views/listview/displaymargin.qml
@@ -1,9 +1,9 @@
-/*****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
@@ -36,36 +36,58 @@
**
** $QT_END_LICENSE$
**
-*****************************************************************************/
+****************************************************************************/
+import QtQuick 2.3
-import QtQuick 2.1
+Item {
+ width: 480; height: 320
-Rectangle {
- color: "#80000000"
- anchors.fill: parent
- z: 1000000
- property alias content: borderImage.content
- property bool dismissOnOuterClick: true
- signal dismissed
- MouseArea {
- anchors.fill: parent
- enabled: dismissOnOuterClick
- onClicked: dismissed()
- BorderImage {
- id: borderImage
- property Item content
+ ListView {
+ id: view
+ anchors.top: header.bottom
+ anchors.bottom: footer.top
+ width: parent.width
- MouseArea { anchors.fill: parent }
+ cacheBuffer: 0
+ displayMarginBeginning: 40
+ displayMarginEnd: 40
- width: content ? content.width + 15 : 0
- height: content ? content.height + 15 : 0
- onWidthChanged: content.x = 5
- onHeightChanged: content.y = 5
- border { left: 10; top: 10; right: 10; bottom: 10 }
- clip: true
- source: "../images/window_border.png"
+ model: 100
+ delegate: Rectangle {
+ objectName: "delegate"
+ width: parent.width
+ height: 25
+ color: index % 2 ? "steelblue" : "lightsteelblue"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "Item " + (index + 1)
+ }
+ }
+ }
+
+ Rectangle {
+ id: header
+ width: parent.width; height: 40
+ color: "#AAFF0000"
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 24
+ text: "Header"
+ }
+ }
+
+ Rectangle {
+ id: footer
+ anchors.bottom: parent.bottom
+ width: parent.width; height: 40
+ color: "#AAFF0000"
+
+ Text {
anchors.centerIn: parent
- onContentChanged: if (content) content.parent = borderImage
+ font.pixelSize: 24
+ text: "Footer"
}
}
}
diff --git a/examples/quick/views/listview/dynamiclist.qml b/examples/quick/views/listview/dynamiclist.qml
index a3e6026d16..fc09372602 100644
--- a/examples/quick/views/listview/dynamiclist.qml
+++ b/examples/quick/views/listview/dynamiclist.qml
@@ -204,7 +204,7 @@ Rectangle {
anchors { left: parent.left; bottom: parent.bottom; margins: 20 }
spacing: 10
- TextButton {
+ TextButton {
text: "Add an item"
onClicked: {
fruitModel.append({
@@ -215,8 +215,8 @@ Rectangle {
}
}
- TextButton {
- text: "Remove all items"
+ TextButton {
+ text: "Remove all items"
onClicked: fruitModel.clear()
}
}
diff --git a/examples/quick/views/listview/expandingdelegates.qml b/examples/quick/views/listview/expandingdelegates.qml
index c19e75f7bd..139ce6bd0d 100644
--- a/examples/quick/views/listview/expandingdelegates.qml
+++ b/examples/quick/views/listview/expandingdelegates.qml
@@ -103,7 +103,7 @@ Rectangle {
width: background.width - recipeImage.width - 20; height: recipeImage.height
spacing: 5
- Text {
+ Text {
text: title
font.bold: true; font.pointSize: 16
}
diff --git a/examples/quick/views/listview/highlight.qml b/examples/quick/views/listview/highlight.qml
index 9564ea11b3..d4c57277b1 100644
--- a/examples/quick/views/listview/highlight.qml
+++ b/examples/quick/views/listview/highlight.qml
@@ -67,7 +67,7 @@ Rectangle {
PropertyChanges { target: wrapper; x: 20 }
}
transitions: Transition {
- NumberAnimation { properties: "x"; duration: 200 }
+ NumberAnimation { properties: "x"; duration: 200 }
}
MouseArea {
anchors.fill: parent
diff --git a/examples/quick/views/listview/highlightranges.qml b/examples/quick/views/listview/highlightranges.qml
index 8b4eed7400..eaa4470ef0 100644
--- a/examples/quick/views/listview/highlightranges.qml
+++ b/examples/quick/views/listview/highlightranges.qml
@@ -79,8 +79,8 @@ Rectangle {
width: 320; height: 480
- // This example shows the same model in three different ListView items,
- // with different highlight ranges. The highlight ranges are set by the
+ // This example shows the same model in three different ListView items,
+ // with different highlight ranges. The highlight ranges are set by the
// preferredHighlightBegin and preferredHighlightEnd properties in ListView.
//
// The first ListView does not set a highlight range, so its currentItem
diff --git a/examples/quick/views/listview/sections.qml b/examples/quick/views/listview/sections.qml
index 636f78fdbd..64d3dc8d71 100644
--- a/examples/quick/views/listview/sections.qml
+++ b/examples/quick/views/listview/sections.qml
@@ -70,7 +70,7 @@ Rectangle {
//! [0]
// The delegate for each section header
- Component {
+ Component {
id: sectionHeading
Rectangle {
width: container.width
diff --git a/examples/quick/views/parallax/parallax.qml b/examples/quick/views/parallax/parallax.qml
index ddcafc1ee1..fad5bee36c 100644
--- a/examples/quick/views/parallax/parallax.qml
+++ b/examples/quick/views/parallax/parallax.qml
@@ -68,7 +68,7 @@ Rectangle {
Loader {
anchors { top: parent.top; topMargin: 10; horizontalCenter: parent.horizontalCenter }
width: 300; height: 400
- clip: true;
+ clip: true;
source: "../../demos/samegame/samegame.qml"
}
}
diff --git a/examples/quick/views/views.qml b/examples/quick/views/views.qml
index 1bc6f6a3d8..2fbf9c5470 100644
--- a/examples/quick/views/views.qml
+++ b/examples/quick/views/views.qml
@@ -58,6 +58,7 @@ Item {
addExample("Packages", "Transitions between a ListView and GridView", Qt.resolvedUrl("package/view.qml"))
addExample("PathView", "A simple PathView", Qt.resolvedUrl("pathview/pathview-example.qml"))
addExample("ObjectModel", "Using a ObjectModel", Qt.resolvedUrl("objectmodel/objectmodel.qml"))
+ addExample("Display Margins", "A ListView with display margins", Qt.resolvedUrl("listview/displaymargin.qml"))
}
}
}
diff --git a/examples/quick/views/views.qrc b/examples/quick/views/views.qrc
index 434fa788bf..52abb68659 100644
--- a/examples/quick/views/views.qrc
+++ b/examples/quick/views/views.qrc
@@ -65,5 +65,6 @@
<file>visualdatamodel/dragselection.qml</file>
<file>objectmodel/objectmodel.qml</file>
<file>views.qml</file>
+ <file>listview/displaymargin.qml</file>
</qresource>
</RCC>
diff --git a/src/imports/dialogs/WidgetColorDialog.qml b/examples/quickwidgets/quickwidget/main.cpp
index ed7c7ab77a..7251760f4f 100644
--- a/src/imports/dialogs/WidgetColorDialog.qml
+++ b/examples/quickwidgets/quickwidget/main.cpp
@@ -1,9 +1,9 @@
-/*****************************************************************************
+/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
@@ -36,9 +36,36 @@
**
** $QT_END_LICENSE$
**
-*****************************************************************************/
+****************************************************************************/
+
+#include <QQuickWidget>
+#include <QtWidgets>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QMdiArea *toplevel = new QMdiArea;
+
+ QLCDNumber *lcd = new QLCDNumber;
+ lcd->display(1337);
+ lcd->setMinimumSize(250,100);
+ toplevel->addSubWindow(lcd);
+
+ QUrl source("qrc:quickwidget/rotatingsquare.qml");
+
+ QQuickWidget *w = new QQuickWidget;
+ w->resize(300,300);
+ w->setResizeMode(QQuickWidget::SizeRootObjectToView );
+ w->setSource(source);
+
+ toplevel->addSubWindow(w);
+
+ toplevel->show();
+
+ return app.exec();
+}
+
+
-import QtQuick 2.1
-import QtQuick.PrivateWidgets 1.0
-QtColorDialog { }
diff --git a/examples/quickwidgets/quickwidget/quickwidget.pro b/examples/quickwidgets/quickwidget/quickwidget.pro
new file mode 100644
index 0000000000..1aca22082e
--- /dev/null
+++ b/examples/quickwidgets/quickwidget/quickwidget.pro
@@ -0,0 +1,8 @@
+QT += core gui quick widgets quickwidgets
+
+TARGET = quickwidget
+TEMPLATE = app
+
+SOURCES += main.cpp
+
+RESOURCES += quickwidget.qrc
diff --git a/examples/quickwidgets/quickwidget/quickwidget.qrc b/examples/quickwidgets/quickwidget/quickwidget.qrc
new file mode 100644
index 0000000000..c073b7b80d
--- /dev/null
+++ b/examples/quickwidgets/quickwidget/quickwidget.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/quickwidget">
+ <file>rotatingsquare.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/dialogs/systemdialogs/main.cpp b/examples/quickwidgets/quickwidget/rotatingsquare.qml
index f6723bb35b..a5becfba38 100644
--- a/examples/quick/dialogs/systemdialogs/main.cpp
+++ b/examples/quickwidgets/quickwidget/rotatingsquare.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@@ -37,5 +37,24 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(dialogs/systemdialogs/systemdialogs)
+
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+
+ Rectangle {
+ property int d: 100
+ id: square
+ width: d
+ height: d
+ anchors.centerIn: parent
+ color: "red"
+ NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; }
+ }
+
+ Text {
+ anchors.centerIn: parent
+ text: "Qt Quick running in a widget"
+ }
+}
diff --git a/examples/quickwidgets/quickwidgets.pro b/examples/quickwidgets/quickwidgets.pro
new file mode 100644
index 0000000000..07192b6696
--- /dev/null
+++ b/examples/quickwidgets/quickwidgets.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = quickwidget
diff --git a/qtdeclarative.pro b/qtdeclarative.pro
index cab16ad610..9ecfad6f75 100644
--- a/qtdeclarative.pro
+++ b/qtdeclarative.pro
@@ -1,3 +1,3 @@
-CONFIG += tests_need_tools
+CONFIG += tests_need_tools examples_need_tools
load(qt_parts)
diff --git a/src/3rdparty/double-conversion/README b/src/3rdparty/double-conversion/README
index 40ed4a7efd..3a9733d795 100644
--- a/src/3rdparty/double-conversion/README
+++ b/src/3rdparty/double-conversion/README
@@ -3,4 +3,4 @@ from
http://code.google.com/p/double-conversion/
-commit e5b34421b763f7bf7e4f9081403db417d5a55a36
+commit 2fb03de56faa32bbba5e02222528e7b760f71d77
diff --git a/src/3rdparty/double-conversion/bignum-dtoa.cc b/src/3rdparty/double-conversion/bignum-dtoa.cc
index b6c2e85d17..f1ad7a5ae8 100644
--- a/src/3rdparty/double-conversion/bignum-dtoa.cc
+++ b/src/3rdparty/double-conversion/bignum-dtoa.cc
@@ -192,13 +192,13 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
delta_plus = delta_minus;
}
*length = 0;
- while (true) {
+ for (;;) {
uint16_t digit;
digit = numerator->DivideModuloIntBignum(*denominator);
ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
// digit = numerator / denominator (integer division).
// numerator = numerator % denominator.
- buffer[(*length)++] = digit + '0';
+ buffer[(*length)++] = static_cast<char>(digit + '0');
// Can we stop already?
// If the remainder of the division is less than the distance to the lower
@@ -282,7 +282,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
// exponent (decimal_point), when rounding upwards.
static void GenerateCountedDigits(int count, int* decimal_point,
Bignum* numerator, Bignum* denominator,
- Vector<char>(buffer), int* length) {
+ Vector<char> buffer, int* length) {
ASSERT(count >= 0);
for (int i = 0; i < count - 1; ++i) {
uint16_t digit;
@@ -290,7 +290,7 @@ static void GenerateCountedDigits(int count, int* decimal_point,
ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
// digit = numerator / denominator (integer division).
// numerator = numerator % denominator.
- buffer[i] = digit + '0';
+ buffer[i] = static_cast<char>(digit + '0');
// Prepare for next iteration.
numerator->Times10();
}
@@ -300,7 +300,8 @@ static void GenerateCountedDigits(int count, int* decimal_point,
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
digit++;
}
- buffer[count - 1] = digit + '0';
+ ASSERT(digit <= 10);
+ buffer[count - 1] = static_cast<char>(digit + '0');
// Correct bad digits (in case we had a sequence of '9's). Propagate the
// carry until we hat a non-'9' or til we reach the first digit.
for (int i = count - 1; i > 0; --i) {
diff --git a/src/3rdparty/double-conversion/bignum.cc b/src/3rdparty/double-conversion/bignum.cc
index 747491a089..2743d67e8d 100644
--- a/src/3rdparty/double-conversion/bignum.cc
+++ b/src/3rdparty/double-conversion/bignum.cc
@@ -40,6 +40,7 @@ Bignum::Bignum()
template<typename S>
static int BitSize(S value) {
+ (void) value; // Mark variable as used.
return 8 * sizeof(value);
}
@@ -122,9 +123,8 @@ void Bignum::AssignDecimalString(Vector<const char> value) {
static int HexCharValue(char c) {
if ('0' <= c && c <= '9') return c - '0';
if ('a' <= c && c <= 'f') return 10 + c - 'a';
- if ('A' <= c && c <= 'F') return 10 + c - 'A';
- UNREACHABLE();
- return 0; // To make compiler happy.
+ ASSERT('A' <= c && c <= 'F');
+ return 10 + c - 'A';
}
@@ -501,13 +501,14 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
// Start by removing multiples of 'other' until both numbers have the same
// number of digits.
while (BigitLength() > other.BigitLength()) {
- // This naive approach is extremely inefficient if the this divided other
- // might be big. This function is implemented for doubleToString where
+ // This naive approach is extremely inefficient if `this` divided by other
+ // is big. This function is implemented for doubleToString where
// the result should be small (less than 10).
ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));
+ ASSERT(bigits_[used_digits_ - 1] < 0x10000);
// Remove the multiples of the first digit.
// Example this = 23 and other equals 9. -> Remove 2 multiples.
- result += bigits_[used_digits_ - 1];
+ result += static_cast<uint16_t>(bigits_[used_digits_ - 1]);
SubtractTimes(other, bigits_[used_digits_ - 1]);
}
@@ -523,13 +524,15 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
// Shortcut for easy (and common) case.
int quotient = this_bigit / other_bigit;
bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
- result += quotient;
+ ASSERT(quotient < 0x10000);
+ result += static_cast<uint16_t>(quotient);
Clamp();
return result;
}
int division_estimate = this_bigit / (other_bigit + 1);
- result += division_estimate;
+ ASSERT(division_estimate < 0x10000);
+ result += static_cast<uint16_t>(division_estimate);
SubtractTimes(other, division_estimate);
if (other_bigit * (division_estimate + 1) > this_bigit) {
@@ -560,8 +563,8 @@ static int SizeInHexChars(S number) {
static char HexCharOfValue(int value) {
ASSERT(0 <= value && value <= 16);
- if (value < 10) return value + '0';
- return value - 10 + 'A';
+ if (value < 10) return static_cast<char>(value + '0');
+ return static_cast<char>(value - 10 + 'A');
}
@@ -755,7 +758,6 @@ void Bignum::SubtractTimes(const Bignum& other, int factor) {
Chunk difference = bigits_[i] - borrow;
bigits_[i] = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
- ++i;
}
Clamp();
}
diff --git a/src/3rdparty/double-conversion/cached-powers.cc b/src/3rdparty/double-conversion/cached-powers.cc
index 7067fca4a9..f2d53de52b 100644
--- a/src/3rdparty/double-conversion/cached-powers.cc
+++ b/src/3rdparty/double-conversion/cached-powers.cc
@@ -153,6 +153,7 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
ASSERT(0 <= index && index < kCachedPowersLength);
CachedPower cached_power = kCachedPowers[index];
ASSERT(min_exponent <= cached_power.binary_exponent);
+ (void) max_exponent; // Mark variable as used.
ASSERT(cached_power.binary_exponent <= max_exponent);
*decimal_exponent = cached_power.decimal_exponent;
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
diff --git a/src/3rdparty/double-conversion/double-conversion.cc b/src/3rdparty/double-conversion/double-conversion.cc
index a79fe92d22..909985be82 100644
--- a/src/3rdparty/double-conversion/double-conversion.cc
+++ b/src/3rdparty/double-conversion/double-conversion.cc
@@ -348,7 +348,6 @@ static BignumDtoaMode DtoaToBignumDtoaMode(
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
default:
UNREACHABLE();
- return BIGNUM_DTOA_SHORTEST; // To silence compiler.
}
}
@@ -403,8 +402,8 @@ void DoubleToStringConverter::DoubleToAscii(double v,
vector, length, point);
break;
default:
- UNREACHABLE();
fast_worked = false;
+ UNREACHABLE();
}
if (fast_worked) return;
@@ -417,8 +416,9 @@ void DoubleToStringConverter::DoubleToAscii(double v,
// Consumes the given substring from the iterator.
// Returns false, if the substring does not match.
-static bool ConsumeSubString(const char** current,
- const char* end,
+template <class Iterator>
+static bool ConsumeSubString(Iterator* current,
+ Iterator end,
const char* substring) {
ASSERT(**current == *substring);
for (substring++; *substring != '\0'; substring++) {
@@ -440,10 +440,36 @@ static bool ConsumeSubString(const char** current,
const int kMaxSignificantDigits = 772;
+static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
+static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
+
+
+static const uc16 kWhitespaceTable16[] = {
+ 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
+ 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
+};
+static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
+
+
+static bool isWhitespace(int x) {
+ if (x < 128) {
+ for (int i = 0; i < kWhitespaceTable7Length; i++) {
+ if (kWhitespaceTable7[i] == x) return true;
+ }
+ } else {
+ for (int i = 0; i < kWhitespaceTable16Length; i++) {
+ if (kWhitespaceTable16[i] == x) return true;
+ }
+ }
+ return false;
+}
+
+
// Returns true if a nonspace found and false if the end has reached.
-static inline bool AdvanceToNonspace(const char** current, const char* end) {
+template <class Iterator>
+static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
while (*current != end) {
- if (**current != ' ') return true;
+ if (!isWhitespace(**current)) return true;
++*current;
}
return false;
@@ -462,26 +488,50 @@ static double SignedZero(bool sign) {
}
+// Returns true if 'c' is a decimal digit that is valid for the given radix.
+//
+// The function is small and could be inlined, but VS2012 emitted a warning
+// because it constant-propagated the radix and concluded that the last
+// condition was always true. By moving it into a separate function the
+// compiler wouldn't warn anymore.
+static bool IsDecimalDigitForRadix(int c, int radix) {
+ return '0' <= c && c <= '9' && (c - '0') < radix;
+}
+
+// Returns true if 'c' is a character digit that is valid for the given radix.
+// The 'a_character' should be 'a' or 'A'.
+//
+// The function is small and could be inlined, but VS2012 emitted a warning
+// because it constant-propagated the radix and concluded that the first
+// condition was always false. By moving it into a separate function the
+// compiler wouldn't warn anymore.
+static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
+ return radix > 10 && c >= a_character && c < a_character + radix - 10;
+}
+
+
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
-template <int radix_log_2>
-static double RadixStringToIeee(const char* current,
- const char* end,
+template <int radix_log_2, class Iterator>
+static double RadixStringToIeee(Iterator* current,
+ Iterator end,
bool sign,
bool allow_trailing_junk,
double junk_string_value,
bool read_as_double,
- const char** trailing_pointer) {
- ASSERT(current != end);
+ bool* result_is_junk) {
+ ASSERT(*current != end);
const int kDoubleSize = Double::kSignificandSize;
const int kSingleSize = Single::kSignificandSize;
const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
+ *result_is_junk = true;
+
// Skip leading 0s.
- while (*current == '0') {
- ++current;
- if (current == end) {
- *trailing_pointer = end;
+ while (**current == '0') {
+ ++(*current);
+ if (*current == end) {
+ *result_is_junk = false;
return SignedZero(sign);
}
}
@@ -492,14 +542,14 @@ static double RadixStringToIeee(const char* current,
do {
int digit;
- if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
- digit = static_cast<char>(*current) - '0';
- } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
- digit = static_cast<char>(*current) - 'a' + 10;
- } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
- digit = static_cast<char>(*current) - 'A' + 10;
+ if (IsDecimalDigitForRadix(**current, radix)) {
+ digit = static_cast<char>(**current) - '0';
+ } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
+ digit = static_cast<char>(**current) - 'a' + 10;
+ } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
+ digit = static_cast<char>(**current) - 'A' + 10;
} else {
- if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
+ if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
break;
} else {
return junk_string_value;
@@ -523,14 +573,14 @@ static double RadixStringToIeee(const char* current,
exponent = overflow_bits_count;
bool zero_tail = true;
- while (true) {
- ++current;
- if (current == end || !isDigit(*current, radix)) break;
- zero_tail = zero_tail && *current == '0';
+ for (;;) {
+ ++(*current);
+ if (*current == end || !isDigit(**current, radix)) break;
+ zero_tail = zero_tail && **current == '0';
exponent += radix_log_2;
}
- if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+ if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
return junk_string_value;
}
@@ -552,13 +602,13 @@ static double RadixStringToIeee(const char* current,
}
break;
}
- ++current;
- } while (current != end);
+ ++(*current);
+ } while (*current != end);
ASSERT(number < ((int64_t)1 << kSignificandSize));
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
- *trailing_pointer = current;
+ *result_is_junk = false;
if (exponent == 0) {
if (sign) {
@@ -573,13 +623,14 @@ static double RadixStringToIeee(const char* current,
}
+template <class Iterator>
double StringToDoubleConverter::StringToIeee(
- const char* input,
+ Iterator input,
int length,
- int* processed_characters_count,
- bool read_as_double) {
- const char* current = input;
- const char* end = input + length;
+ bool read_as_double,
+ int* processed_characters_count) const {
+ Iterator current = input;
+ Iterator end = input + length;
*processed_characters_count = 0;
@@ -600,7 +651,7 @@ double StringToDoubleConverter::StringToIeee(
if (allow_leading_spaces || allow_trailing_spaces) {
if (!AdvanceToNonspace(&current, end)) {
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return empty_string_value_;
}
if (!allow_leading_spaces && (input != current)) {
@@ -626,7 +677,7 @@ double StringToDoubleConverter::StringToIeee(
if (*current == '+' || *current == '-') {
sign = (*current == '-');
++current;
- const char* next_non_space = current;
+ Iterator next_non_space = current;
// Skip following spaces (if allowed).
if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
if (!allow_spaces_after_sign && (current != next_non_space)) {
@@ -649,7 +700,7 @@ double StringToDoubleConverter::StringToIeee(
}
ASSERT(buffer_pos == 0);
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return sign ? -Double::Infinity() : Double::Infinity();
}
}
@@ -668,7 +719,7 @@ double StringToDoubleConverter::StringToIeee(
}
ASSERT(buffer_pos == 0);
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return sign ? -Double::NaN() : Double::NaN();
}
}
@@ -677,7 +728,7 @@ double StringToDoubleConverter::StringToIeee(
if (*current == '0') {
++current;
if (current == end) {
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -690,17 +741,17 @@ double StringToDoubleConverter::StringToIeee(
return junk_string_value_; // "0x".
}
- const char* tail_pointer = NULL;
- double result = RadixStringToIeee<4>(current,
+ bool result_is_junk;
+ double result = RadixStringToIeee<4>(&current,
end,
sign,
allow_trailing_junk,
junk_string_value_,
read_as_double,
- &tail_pointer);
- if (tail_pointer != NULL) {
- if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
- *processed_characters_count = tail_pointer - input;
+ &result_is_junk);
+ if (!result_is_junk) {
+ if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
+ *processed_characters_count = static_cast<int>(current - input);
}
return result;
}
@@ -709,7 +760,7 @@ double StringToDoubleConverter::StringToIeee(
while (*current == '0') {
++current;
if (current == end) {
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
}
@@ -757,7 +808,7 @@ double StringToDoubleConverter::StringToIeee(
while (*current == '0') {
++current;
if (current == end) {
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
exponent--; // Move this 0 into the exponent.
@@ -855,16 +906,17 @@ double StringToDoubleConverter::StringToIeee(
if (octal) {
double result;
- const char* tail_pointer = NULL;
- result = RadixStringToIeee<3>(buffer,
+ bool result_is_junk;
+ char* start = buffer;
+ result = RadixStringToIeee<3>(&start,
buffer + buffer_pos,
sign,
allow_trailing_junk,
junk_string_value_,
read_as_double,
- &tail_pointer);
- ASSERT(tail_pointer != NULL);
- *processed_characters_count = current - input;
+ &result_is_junk);
+ ASSERT(!result_is_junk);
+ *processed_characters_count = static_cast<int>(current - input);
return result;
}
@@ -882,8 +934,42 @@ double StringToDoubleConverter::StringToIeee(
} else {
converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
}
- *processed_characters_count = current - input;
+ *processed_characters_count = static_cast<int>(current - input);
return sign? -converted: converted;
}
+
+double StringToDoubleConverter::StringToDouble(
+ const char* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return StringToIeee(buffer, length, true, processed_characters_count);
+}
+
+
+double StringToDoubleConverter::StringToDouble(
+ const uc16* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return StringToIeee(buffer, length, true, processed_characters_count);
+}
+
+
+float StringToDoubleConverter::StringToFloat(
+ const char* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return static_cast<float>(StringToIeee(buffer, length, false,
+ processed_characters_count));
+}
+
+
+float StringToDoubleConverter::StringToFloat(
+ const uc16* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return static_cast<float>(StringToIeee(buffer, length, false,
+ processed_characters_count));
+}
+
} // namespace double_conversion
diff --git a/src/3rdparty/double-conversion/double-conversion.h b/src/3rdparty/double-conversion/double-conversion.h
index f98edae75a..6bdfa8d25d 100644
--- a/src/3rdparty/double-conversion/double-conversion.h
+++ b/src/3rdparty/double-conversion/double-conversion.h
@@ -415,9 +415,10 @@ class StringToDoubleConverter {
// junk, too.
// - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
// a double literal.
- // - ALLOW_LEADING_SPACES: skip over leading spaces.
- // - ALLOW_TRAILING_SPACES: ignore trailing spaces.
- // - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.
+ // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
+ // new-lines, and tabs.
+ // - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
+ // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
// Ex: StringToDouble("- 123.2") -> -123.2.
// StringToDouble("+ 123.2") -> 123.2
//
@@ -502,19 +503,24 @@ class StringToDoubleConverter {
// in the 'processed_characters_count'. Trailing junk is never included.
double StringToDouble(const char* buffer,
int length,
- int* processed_characters_count) {
- return StringToIeee(buffer, length, processed_characters_count, true);
- }
+ int* processed_characters_count) const;
+
+ // Same as StringToDouble above but for 16 bit characters.
+ double StringToDouble(const uc16* buffer,
+ int length,
+ int* processed_characters_count) const;
// Same as StringToDouble but reads a float.
// Note that this is not equivalent to static_cast<float>(StringToDouble(...))
// due to potential double-rounding.
float StringToFloat(const char* buffer,
int length,
- int* processed_characters_count) {
- return static_cast<float>(StringToIeee(buffer, length,
- processed_characters_count, false));
- }
+ int* processed_characters_count) const;
+
+ // Same as StringToFloat above but for 16 bit characters.
+ float StringToFloat(const uc16* buffer,
+ int length,
+ int* processed_characters_count) const;
private:
const int flags_;
@@ -523,10 +529,11 @@ class StringToDoubleConverter {
const char* const infinity_symbol_;
const char* const nan_symbol_;
- double StringToIeee(const char* buffer,
+ template <class Iterator>
+ double StringToIeee(Iterator start_pointer,
int length,
- int* processed_characters_count,
- bool read_as_double);
+ bool read_as_double,
+ int* processed_characters_count) const;
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
};
diff --git a/src/3rdparty/double-conversion/fast-dtoa.cc b/src/3rdparty/double-conversion/fast-dtoa.cc
index 1a0f823509..61350383a9 100644
--- a/src/3rdparty/double-conversion/fast-dtoa.cc
+++ b/src/3rdparty/double-conversion/fast-dtoa.cc
@@ -248,10 +248,7 @@ static void BiggestPowerTen(uint32_t number,
// Note: kPowersOf10[i] == 10^(i-1).
exponent_plus_one_guess++;
// We don't have any guarantees that 2^number_bits <= number.
- // TODO(floitsch): can we change the 'while' into an 'if'? We definitely see
- // number < (2^number_bits - 1), but I haven't encountered
- // number < (2^number_bits - 2) yet.
- while (number < kSmallPowersOfTen[exponent_plus_one_guess]) {
+ if (number < kSmallPowersOfTen[exponent_plus_one_guess]) {
exponent_plus_one_guess--;
}
*power = kSmallPowersOfTen[exponent_plus_one_guess];
@@ -350,7 +347,8 @@ static bool DigitGen(DiyFp low,
// that is smaller than integrals.
while (*kappa > 0) {
int digit = integrals / divisor;
- buffer[*length] = '0' + digit;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
(*length)++;
integrals %= divisor;
(*kappa)--;
@@ -379,13 +377,14 @@ static bool DigitGen(DiyFp low,
ASSERT(one.e() >= -60);
ASSERT(fractionals < one.f());
ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
- while (true) {
+ for (;;) {
fractionals *= 10;
unit *= 10;
unsafe_interval.set_f(unsafe_interval.f() * 10);
// Integer division by one.
int digit = static_cast<int>(fractionals >> -one.e());
- buffer[*length] = '0' + digit;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
(*length)++;
fractionals &= one.f() - 1; // Modulo by one.
(*kappa)--;
@@ -459,7 +458,8 @@ static bool DigitGenCounted(DiyFp w,
// that is smaller than 'integrals'.
while (*kappa > 0) {
int digit = integrals / divisor;
- buffer[*length] = '0' + digit;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
(*length)++;
requested_digits--;
integrals %= divisor;
@@ -492,7 +492,8 @@ static bool DigitGenCounted(DiyFp w,
w_error *= 10;
// Integer division by one.
int digit = static_cast<int>(fractionals >> -one.e());
- buffer[*length] = '0' + digit;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
(*length)++;
requested_digits--;
fractionals &= one.f() - 1; // Modulo by one.
diff --git a/src/3rdparty/double-conversion/fixed-dtoa.cc b/src/3rdparty/double-conversion/fixed-dtoa.cc
index 6d63c71858..aef65fdc21 100644
--- a/src/3rdparty/double-conversion/fixed-dtoa.cc
+++ b/src/3rdparty/double-conversion/fixed-dtoa.cc
@@ -133,7 +133,7 @@ static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
while (number != 0) {
int digit = number % 10;
number /= 10;
- buffer[(*length) + number_length] = '0' + digit;
+ buffer[(*length) + number_length] = static_cast<char>('0' + digit);
number_length++;
}
// Exchange the digits.
@@ -150,10 +150,8 @@ static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
}
-static void FillDigits64FixedLength(uint64_t number, int requested_length,
+static void FillDigits64FixedLength(uint64_t number,
Vector<char> buffer, int* length) {
- (void) requested_length;
-
const uint32_t kTen7 = 10000000;
// For efficiency cut the number into 3 uint32_t parts, and print those.
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
@@ -255,7 +253,8 @@ static void FillFractionals(uint64_t fractionals, int exponent,
fractionals *= 5;
point--;
int digit = static_cast<int>(fractionals >> point);
- buffer[*length] = '0' + digit;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
(*length)++;
fractionals -= static_cast<uint64_t>(digit) << point;
}
@@ -276,7 +275,8 @@ static void FillFractionals(uint64_t fractionals, int exponent,
fractionals128.Multiply(5);
point--;
int digit = fractionals128.DivModPowerOf2(point);
- buffer[*length] = '0' + digit;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
(*length)++;
}
if (fractionals128.BitAt(point - 1) == 1) {
@@ -360,7 +360,7 @@ bool FastFixedDtoa(double v,
remainder = (dividend % divisor) << exponent;
}
FillDigits32(quotient, buffer, length);
- FillDigits64FixedLength(remainder, divisor_power, buffer, length);
+ FillDigits64FixedLength(remainder, buffer, length);
*decimal_point = *length;
} else if (exponent >= 0) {
// 0 <= exponent <= 11
diff --git a/src/3rdparty/double-conversion/ieee.h b/src/3rdparty/double-conversion/ieee.h
index 839dc47d45..661141d1a8 100644
--- a/src/3rdparty/double-conversion/ieee.h
+++ b/src/3rdparty/double-conversion/ieee.h
@@ -256,6 +256,8 @@ class Double {
return (significand & kSignificandMask) |
(biased_exponent << kPhysicalSignificandSize);
}
+
+ DISALLOW_COPY_AND_ASSIGN(Double);
};
class Single {
@@ -391,6 +393,8 @@ class Single {
static const uint32_t kNaN = 0x7FC00000;
const uint32_t d32_;
+
+ DISALLOW_COPY_AND_ASSIGN(Single);
};
} // namespace double_conversion
diff --git a/src/3rdparty/double-conversion/strtod.cc b/src/3rdparty/double-conversion/strtod.cc
index 2620fbbf0f..34717562bd 100644
--- a/src/3rdparty/double-conversion/strtod.cc
+++ b/src/3rdparty/double-conversion/strtod.cc
@@ -137,7 +137,7 @@ static void TrimAndCut(Vector<const char> buffer, int exponent,
Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed);
exponent += left_trimmed.length() - right_trimmed.length();
if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
- (void)space_size; // Silence unused parameter warning in release build
+ (void) space_size; // Mark variable as used.
ASSERT(space_size >= kMaxSignificantDecimalDigits);
CutToMaxSignificantDigits(right_trimmed, exponent,
buffer_copy_space, updated_exponent);
@@ -264,7 +264,6 @@ static DiyFp AdjustmentPowerOfTen(int exponent) {
case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
default:
UNREACHABLE();
- return DiyFp(0, 0);
}
}
@@ -516,7 +515,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_next2 = Double(double_next).NextDouble();
f4 = static_cast<float>(double_next2);
}
- (void)f2; // Silence unused parameter warning in release builds
+ (void) f2; // Mark variable as used.
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
// If the guess doesn't lie near a single-precision boundary we can simply
diff --git a/src/3rdparty/double-conversion/utils.h b/src/3rdparty/double-conversion/utils.h
index 1eca476913..53eec64282 100644
--- a/src/3rdparty/double-conversion/utils.h
+++ b/src/3rdparty/double-conversion/utils.h
@@ -36,7 +36,8 @@
# if defined(WINCE) || defined(_WIN32_WCE)
# define ASSERT(condition)
# else
-# define ASSERT(condition) (assert(condition))
+# define ASSERT(condition) \
+ assert(condition);
# endif
#endif
#ifndef UNIMPLEMENTED
@@ -59,10 +60,12 @@
#if defined(_M_X64) || defined(__x86_64__) || \
defined(__ARMEL__) || defined(__avr32__) || _M_ARM_FP || \
defined(__hppa__) || defined(__ia64__) || \
- defined(__mips__) || defined(__powerpc__) || \
+ defined(__mips__) || \
+ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
- defined(_MIPS_ARCH_MIPS32R2)
+ defined(_MIPS_ARCH_MIPS32R2) || \
+ defined(__AARCH64EL__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
@@ -77,6 +80,11 @@
#error Target architecture was not detected as supported by Double-Conversion.
#endif
+#if defined(__GNUC__)
+#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
+#else
+#define DOUBLE_CONVERSION_UNUSED
+#endif
#if defined(_WIN32) && !defined(__MINGW32__)
@@ -96,6 +104,8 @@ typedef unsigned __int64 uint64_t;
#endif
+typedef uint16_t uc16;
+
// The following macro works on both 32 and 64-bit platforms.
// Usage: instead of writing 0x1234567890123456
// write UINT64_2PART_C(0x12345678,90123456);
@@ -302,8 +312,8 @@ template <class Dest, class Source>
inline Dest BitCast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
- char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
- (void) VerifySizesAreEqual;
+ DOUBLE_CONVERSION_UNUSED
+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
Dest dest;
memmove(&dest, &source, sizeof(dest));
diff --git a/src/3rdparty/masm/masm-defs.pri b/src/3rdparty/masm/masm-defs.pri
index 95f1f60031..66506dccf5 100644
--- a/src/3rdparty/masm/masm-defs.pri
+++ b/src/3rdparty/masm/masm-defs.pri
@@ -25,7 +25,7 @@ INCLUDEPATH += $$PWD
disassembler {
if(isEqual(QT_ARCH, "i386")|isEqual(QT_ARCH, "x86_64")):!win*: DEFINES += WTF_USE_UDIS86=1
- if(isEqual(QT_ARCH, "arm")):contains(DEFINES, V4_ENABLE_JIT): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1
+ if(isEqual(QT_ARCH, "arm")): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1
} else {
DEFINES += WTF_USE_UDIS86=0
}
diff --git a/src/imports/dialogs-private/dialogs-private.pro b/src/imports/dialogs-private/dialogs-private.pro
deleted file mode 100644
index 7f04617ef5..0000000000
--- a/src/imports/dialogs-private/dialogs-private.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-CXX_MODULE = qml
-TARGET = dialogsprivateplugin
-TARGETPATH = QtQuick/Dialogs/Private
-IMPORT_VERSION = 1.1
-
-SOURCES += \
- qquickfontlistmodel.cpp \
- qquickwritingsystemlistmodel.cpp \
- dialogsprivateplugin.cpp
-
-HEADERS += \
- qquickfontlistmodel_p.h \
- qquickwritingsystemlistmodel_p.h
-
-QT += gui-private core-private qml-private
-
-load(qml_plugin)
diff --git a/src/imports/dialogs-private/qmldir b/src/imports/dialogs-private/qmldir
deleted file mode 100644
index c371f8bb8c..0000000000
--- a/src/imports/dialogs-private/qmldir
+++ /dev/null
@@ -1,4 +0,0 @@
-module QtQuick.Dialogs.Private
-plugin dialogsprivateplugin
-typeinfo plugins.qmltypes
-classname QtQuick2DialogsPrivatePlugin
diff --git a/src/imports/dialogs-private/qquickfontlistmodel.cpp b/src/imports/dialogs-private/qquickfontlistmodel.cpp
deleted file mode 100644
index 96d1824ef6..0000000000
--- a/src/imports/dialogs-private/qquickfontlistmodel.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickfontlistmodel_p.h"
-#include <QtGui/qfontdatabase.h>
-#include <QtQml/qqmlcontext.h>
-#include <private/qqmlengine_p.h>
-#include <private/qv8engine_p.h>
-#include <private/qv4value_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4object_p.h>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QV4;
-
-class QQuickFontListModelPrivate
-{
- Q_DECLARE_PUBLIC(QQuickFontListModel)
-
-public:
- QQuickFontListModelPrivate(QQuickFontListModel *q)
- : q_ptr(q), ws(QFontDatabase::Any)
- , options(QSharedPointer<QFontDialogOptions>(new QFontDialogOptions()))
- {}
-
- QQuickFontListModel *q_ptr;
- QFontDatabase db;
- QFontDatabase::WritingSystem ws;
- QSharedPointer<QFontDialogOptions> options;
- QStringList families;
- QHash<int, QByteArray> roleNames;
- ~QQuickFontListModelPrivate() {}
- void init();
-};
-
-
-void QQuickFontListModelPrivate::init()
-{
- Q_Q(QQuickFontListModel);
-
- families = db.families();
-
- emit q->rowCountChanged();
- emit q->writingSystemChanged();
-}
-
-QQuickFontListModel::QQuickFontListModel(QObject *parent)
- : QAbstractListModel(parent), d_ptr(new QQuickFontListModelPrivate(this))
-{
- Q_D(QQuickFontListModel);
- d->roleNames[FontFamilyRole] = "family";
- d->init();
-}
-
-QQuickFontListModel::~QQuickFontListModel()
-{
-}
-
-QVariant QQuickFontListModel::data(const QModelIndex &index, int role) const
-{
- Q_D(const QQuickFontListModel);
- QVariant rv;
-
- if (index.row() >= d->families.size())
- return rv;
-
- switch (role)
- {
- case FontFamilyRole:
- rv = d->families.at(index.row());
- break;
- default:
- break;
- }
- return rv;
-}
-
-QHash<int, QByteArray> QQuickFontListModel::roleNames() const
-{
- Q_D(const QQuickFontListModel);
- return d->roleNames;
-}
-
-int QQuickFontListModel::rowCount(const QModelIndex &parent) const
-{
- Q_D(const QQuickFontListModel);
- Q_UNUSED(parent);
- return d->families.size();
-}
-
-QModelIndex QQuickFontListModel::index(int row, int , const QModelIndex &) const
-{
- return createIndex(row, 0);
-}
-
-QString QQuickFontListModel::writingSystem() const
-{
- Q_D(const QQuickFontListModel);
- return QFontDatabase::writingSystemName(d->ws);
-}
-
-void QQuickFontListModel::setWritingSystem(const QString &wSystem)
-{
- Q_D(QQuickFontListModel);
-
- if (wSystem == writingSystem())
- return;
-
- QList<QFontDatabase::WritingSystem> wss;
- wss << QFontDatabase::Any;
- wss << d->db.writingSystems();
- QFontDatabase::WritingSystem ws;
- foreach (ws, wss) {
- if (wSystem == QFontDatabase::writingSystemName(ws)) {
- d->ws = ws;
- updateFamilies();
- return;
- }
- }
-}
-
-void QQuickFontListModel::updateFamilies()
-{
- Q_D(QQuickFontListModel);
-
- beginResetModel();
- const QFontDialogOptions::FontDialogOptions scalableMask = (QFontDialogOptions::FontDialogOptions)(QFontDialogOptions::ScalableFonts | QFontDialogOptions::NonScalableFonts);
- const QFontDialogOptions::FontDialogOptions spacingMask = (QFontDialogOptions::FontDialogOptions)(QFontDialogOptions::ProportionalFonts | QFontDialogOptions::MonospacedFonts);
- const QFontDialogOptions::FontDialogOptions options = d->options->options();
-
- d->families.clear();
- foreach (const QString &family, d->db.families(d->ws)) {
- if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
- if (bool(options & QFontDialogOptions::ScalableFonts) != d->db.isSmoothlyScalable(family))
- continue;
- }
- if ((options & spacingMask) && (options & spacingMask) != spacingMask) {
- if (bool(options & QFontDialogOptions::MonospacedFonts) != d->db.isFixedPitch(family))
- continue;
- }
- d->families << family;
- }
- endResetModel();
-}
-
-bool QQuickFontListModel::scalableFonts() const
-{
- Q_D(const QQuickFontListModel);
- return d->options->testOption(QFontDialogOptions::ScalableFonts);
-}
-
-bool QQuickFontListModel::nonScalableFonts() const
-{
- Q_D(const QQuickFontListModel);
- return d->options->testOption(QFontDialogOptions::NonScalableFonts);
-}
-
-bool QQuickFontListModel::monospacedFonts() const
-{
- Q_D(const QQuickFontListModel);
- return d->options->testOption(QFontDialogOptions::MonospacedFonts);
-}
-
-bool QQuickFontListModel::proportionalFonts() const
-{
- Q_D(const QQuickFontListModel);
- return d->options->testOption(QFontDialogOptions::ProportionalFonts);
-}
-
-QQmlV4Handle QQuickFontListModel::get(int idx) const
-{
- Q_D(const QQuickFontListModel);
-
- if (idx < 0 || idx >= count())
- return QQmlV4Handle(Encode::undefined());
-
- QQmlEngine *engine = qmlContext(this)->engine();
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
- ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
- Scope scope(v4engine);
- ScopedObject o(scope, v4engine->newObject());
- ScopedString s(scope);
- for (int ii = 0; ii < d->roleNames.keys().count(); ++ii) {
- Property *p = o->insertMember((s = v4engine->newIdentifier(d->roleNames[Qt::UserRole + ii + 1])), PropertyAttributes());
- p->value = v8engine->fromVariant(data(index(idx, 0), Qt::UserRole + ii + 1));
- }
-
- return QQmlV4Handle(o);
-}
-
-QQmlV4Handle QQuickFontListModel::pointSizes()
-{
- QQmlEngine *engine = qmlContext(this)->engine();
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
- ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
- Scope scope(v4engine);
-
- QList<int> pss = QFontDatabase::standardSizes();
- int size = pss.size();
-
- Scoped<QV4::ArrayObject> a(scope, v4engine->newArrayObject());
- a->arrayReserve(size);
- a->arrayDataLen = size;
- for (int i = 0; i < size; ++i)
- a->arrayData[i].value = Primitive::fromInt32(pss.at(i));
- a->setArrayLengthUnchecked(size);
-
- return QQmlV4Handle(ScopedValue(scope, a.asReturnedValue()));
-}
-
-void QQuickFontListModel::classBegin()
-{
-}
-
-void QQuickFontListModel::componentComplete()
-{
-}
-
-void QQuickFontListModel::setScalableFonts(bool arg)
-{
- Q_D(QQuickFontListModel);
- d->options->setOption(QFontDialogOptions::ScalableFonts, arg);
- updateFamilies();
- emit scalableFontsChanged();
-}
-
-void QQuickFontListModel::setNonScalableFonts(bool arg)
-{
- Q_D(QQuickFontListModel);
- d->options->setOption(QFontDialogOptions::NonScalableFonts, arg);
- updateFamilies();
- emit nonScalableFontsChanged();
-}
-
-void QQuickFontListModel::setMonospacedFonts(bool arg)
-{
- Q_D(QQuickFontListModel);
- d->options->setOption(QFontDialogOptions::MonospacedFonts, arg);
- updateFamilies();
- emit monospacedFontsChanged();
-}
-
-void QQuickFontListModel::setProportionalFonts(bool arg)
-{
- Q_D(QQuickFontListModel);
- d->options->setOption(QFontDialogOptions::ProportionalFonts, arg);
- updateFamilies();
- emit proportionalFontsChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs-private/qquickfontlistmodel_p.h b/src/imports/dialogs-private/qquickfontlistmodel_p.h
deleted file mode 100644
index 3e2e7f7132..0000000000
--- a/src/imports/dialogs-private/qquickfontlistmodel_p.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKFONTLISTMODEL_P_H
-#define QQUICKFONTLISTMODEL_P_H
-
-#include <QtCore/qstringlist.h>
-#include <QtCore/qabstractitemmodel.h>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include <QtQml/qqmlparserstatus.h>
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QModelIndex;
-
-class QQuickFontListModelPrivate;
-
-class QQuickFontListModel : public QAbstractListModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
- Q_PROPERTY(QString writingSystem READ writingSystem WRITE setWritingSystem NOTIFY writingSystemChanged)
-
- Q_PROPERTY(bool scalableFonts READ scalableFonts WRITE setScalableFonts NOTIFY scalableFontsChanged)
- Q_PROPERTY(bool nonScalableFonts READ nonScalableFonts WRITE setNonScalableFonts NOTIFY nonScalableFontsChanged)
- Q_PROPERTY(bool monospacedFonts READ monospacedFonts WRITE setMonospacedFonts NOTIFY monospacedFontsChanged)
- Q_PROPERTY(bool proportionalFonts READ proportionalFonts WRITE setProportionalFonts NOTIFY proportionalFontsChanged)
-
- Q_PROPERTY(int count READ count NOTIFY rowCountChanged)
-
-public:
- QQuickFontListModel(QObject *parent = 0);
- ~QQuickFontListModel();
-
- enum Roles {
- FontFamilyRole = Qt::UserRole + 1
- };
-
- virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
- virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
- virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- virtual QHash<int, QByteArray> roleNames() const;
-
- int count() const { return rowCount(QModelIndex()); }
-
- QString writingSystem() const;
- void setWritingSystem(const QString& writingSystem);
-
- bool scalableFonts() const;
- bool nonScalableFonts() const;
- bool monospacedFonts() const;
- bool proportionalFonts() const;
-
- Q_INVOKABLE QQmlV4Handle get(int index) const;
- Q_INVOKABLE QQmlV4Handle pointSizes();
-
- virtual void classBegin();
- virtual void componentComplete();
-
-public Q_SLOTS:
- void setScalableFonts(bool arg);
- void setNonScalableFonts(bool arg);
- void setMonospacedFonts(bool arg);
- void setProportionalFonts(bool arg);
-
-Q_SIGNALS:
- void scalableFontsChanged();
- void nonScalableFontsChanged();
- void monospacedFontsChanged();
- void proportionalFontsChanged();
- void writingSystemChanged();
- void rowCountChanged() const;
-
-protected:
- void updateFamilies();
-
-private:
- Q_DISABLE_COPY(QQuickFontListModel)
- Q_DECLARE_PRIVATE(QQuickFontListModel)
- QScopedPointer<QQuickFontListModelPrivate> d_ptr;
-
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKFONTLISTMODEL_P_H
diff --git a/src/imports/dialogs-private/qquickwritingsystemlistmodel.cpp b/src/imports/dialogs-private/qquickwritingsystemlistmodel.cpp
deleted file mode 100644
index f2b4ff8b8f..0000000000
--- a/src/imports/dialogs-private/qquickwritingsystemlistmodel.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickwritingsystemlistmodel_p.h"
-#include <QtGui/qfontdatabase.h>
-#include <QtQml/qqmlcontext.h>
-#include <private/qqmlengine_p.h>
-#include <private/qv8engine_p.h>
-#include <private/qv4value_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4object_p.h>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QV4;
-
-class QQuickWritingSystemListModelPrivate
-{
- Q_DECLARE_PUBLIC(QQuickWritingSystemListModel)
-
-public:
- QQuickWritingSystemListModelPrivate(QQuickWritingSystemListModel *q)
- : q_ptr(q)
- {}
-
- QQuickWritingSystemListModel *q_ptr;
- QList<QFontDatabase::WritingSystem> wss;
- QHash<int, QByteArray> roleNames;
- ~QQuickWritingSystemListModelPrivate() {}
- void init();
-};
-
-
-void QQuickWritingSystemListModelPrivate::init()
-{
- Q_Q(QQuickWritingSystemListModel);
- wss << QFontDatabase::Any;
- QFontDatabase db;
- wss << db.writingSystems();
-
- emit q->rowCountChanged();
- emit q->writingSystemsChanged();
-}
-
-QQuickWritingSystemListModel::QQuickWritingSystemListModel(QObject *parent)
- : QAbstractListModel(parent), d_ptr(new QQuickWritingSystemListModelPrivate(this))
-{
- Q_D(QQuickWritingSystemListModel);
- d->roleNames[WritingSystemNameRole] = "name";
- d->roleNames[WritingSystemSampleRole] = "sample";
- d->init();
-}
-
-QQuickWritingSystemListModel::~QQuickWritingSystemListModel()
-{
-}
-
-QVariant QQuickWritingSystemListModel::data(const QModelIndex &index, int role) const
-{
- Q_D(const QQuickWritingSystemListModel);
- QVariant rv;
-
- if (index.row() >= d->wss.size())
- return rv;
-
- switch (role)
- {
- case WritingSystemNameRole:
- rv = QFontDatabase::writingSystemName(d->wss.at(index.row()));
- break;
- case WritingSystemSampleRole:
- rv = QFontDatabase::writingSystemSample(d->wss.at(index.row()));
- break;
- default:
- break;
- }
- return rv;
-}
-
-QHash<int, QByteArray> QQuickWritingSystemListModel::roleNames() const
-{
- Q_D(const QQuickWritingSystemListModel);
- return d->roleNames;
-}
-
-int QQuickWritingSystemListModel::rowCount(const QModelIndex &parent) const
-{
- Q_D(const QQuickWritingSystemListModel);
- Q_UNUSED(parent);
- return d->wss.size();
-}
-
-QModelIndex QQuickWritingSystemListModel::index(int row, int , const QModelIndex &) const
-{
- return createIndex(row, 0);
-}
-
-QStringList QQuickWritingSystemListModel::writingSystems() const
-{
- Q_D(const QQuickWritingSystemListModel);
- QStringList result;
- QFontDatabase::WritingSystem ws;
- foreach (ws, d->wss)
- result.append(QFontDatabase::writingSystemName(ws));
-
- return result;
-}
-
-QQmlV4Handle QQuickWritingSystemListModel::get(int idx) const
-{
- Q_D(const QQuickWritingSystemListModel);
-
- if (idx < 0 || idx >= count())
- return QQmlV4Handle(Encode::undefined());
-
- QQmlEngine *engine = qmlContext(this)->engine();
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
- ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
- Scope scope(v4engine);
- ScopedObject o(scope, v4engine->newObject());
- ScopedString s(scope);
- for (int ii = 0; ii < d->roleNames.keys().count(); ++ii) {
- Property *p = o->insertMember((s = v4engine->newIdentifier(d->roleNames[Qt::UserRole + ii + 1])), PropertyAttributes());
- p->value = v8engine->fromVariant(data(index(idx, 0), Qt::UserRole + ii + 1));
- }
-
- return QQmlV4Handle(o);
-}
-
-void QQuickWritingSystemListModel::classBegin()
-{
-}
-
-void QQuickWritingSystemListModel::componentComplete()
-{
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/DefaultColorDialog.qml b/src/imports/dialogs/DefaultColorDialog.qml
deleted file mode 100644
index 4913e332d7..0000000000
--- a/src/imports/dialogs/DefaultColorDialog.qml
+++ /dev/null
@@ -1,362 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Window 2.1
-import QtQuick.Dialogs 1.0
-import "qml"
-
-AbstractColorDialog {
- id: root
- property bool __valueSet: true // guard to prevent binding loops
- function __setControlsFromColor() {
- __valueSet = false
- hueSlider.value = root.currentHue
- saturationSlider.value = root.currentSaturation
- lightnessSlider.value = root.currentLightness
- alphaSlider.value = root.currentAlpha
- crosshairs.x = root.currentLightness * paletteMap.width
- crosshairs.y = (1.0 - root.currentSaturation) * paletteMap.height
- __valueSet = true
- }
- onCurrentColorChanged: __setControlsFromColor()
- onSelectionAccepted: root.color = root.currentColor
-
- Rectangle {
- id: content
- property int maxSize: 0.9 * Math.min(Screen.desktopAvailableWidth, Screen.desktopAvailableHeight)
- implicitHeight: Math.min(maxSize, Screen.pixelDensity * (usePaletteMap ? 100 : 50))
- implicitWidth: usePaletteMap ? implicitHeight - bottomMinHeight : implicitHeight * 1.5
- color: palette.window
- focus: root.visible
- property real bottomMinHeight: sliders.height + buttonRow.height + outerSpacing * 3
- property real spacing: 8
- property real outerSpacing: 12
- property bool usePaletteMap: true
-
- Keys.onPressed: {
- event.accepted = true
- switch (event.key) {
- case Qt.Key_Return:
- case Qt.Key_Select:
- accept()
- break
- case Qt.Key_Escape:
- case Qt.Key_Back:
- reject()
- break
- case Qt.Key_C:
- if (event.modifiers & Qt.ControlModifier)
- colorField.copyAll()
- break
- case Qt.Key_V:
- if (event.modifiers & Qt.ControlModifier) {
- colorField.paste()
- root.currentColor = colorField.text
- }
- break
- default:
- // do nothing
- event.accepted = false
- break
- }
- }
-
- // set the preferred width based on height, to avoid "letterboxing" the paletteMap
- onHeightChanged: implicitHeight = Math.max((usePaletteMap ? 480 : bottomMinHeight), height)
-
- SystemPalette { id: palette }
-
- Item {
- id: paletteFrame
- visible: content.usePaletteMap
- anchors {
- top: parent.top
- left: parent.left
- right: parent.right
- margins: content.outerSpacing
- }
- height: Math.min(content.height - content.bottomMinHeight, content.width - content.outerSpacing * 2)
-
- Image {
- id: paletteMap
- x: (parent.width - width) / 2
- width: height
- onWidthChanged: root.__setControlsFromColor()
- height: parent.height
- source: "images/checkers.png"
- fillMode: Image.Tile
-
- // note we smoothscale the shader from a smaller version to improve performance
- ShaderEffect {
- id: map
- width: 64
- height: 64
- opacity: alphaSlider.value
- scale: paletteMap.width / width;
- layer.enabled: true
- layer.smooth: true
- anchors.centerIn: parent
- property real hue: hueSlider.value
-
- fragmentShader: "
- varying mediump vec2 qt_TexCoord0;
- uniform highp float qt_Opacity;
- uniform highp float hue;
-
- highp float hueToIntensity(highp float v1, highp float v2, highp float h) {
- h = fract(h);
- if (h < 1.0 / 6.0)
- return v1 + (v2 - v1) * 6.0 * h;
- else if (h < 1.0 / 2.0)
- return v2;
- else if (h < 2.0 / 3.0)
- return v1 + (v2 - v1) * 6.0 * (2.0 / 3.0 - h);
-
- return v1;
- }
-
- highp vec3 HSLtoRGB(highp vec3 color) {
- highp float h = color.x;
- highp float l = color.z;
- highp float s = color.y;
-
- if (s < 1.0 / 256.0)
- return vec3(l, l, l);
-
- highp float v1;
- highp float v2;
- if (l < 0.5)
- v2 = l * (1.0 + s);
- else
- v2 = (l + s) - (s * l);
-
- v1 = 2.0 * l - v2;
-
- highp float d = 1.0 / 3.0;
- highp float r = hueToIntensity(v1, v2, h + d);
- highp float g = hueToIntensity(v1, v2, h);
- highp float b = hueToIntensity(v1, v2, h - d);
- return vec3(r, g, b);
- }
-
- void main() {
- lowp vec4 c = vec4(1.0);
- c.rgb = HSLtoRGB(vec3(hue, 1.0 - qt_TexCoord0.t, qt_TexCoord0.s));
- gl_FragColor = c * qt_Opacity;
- }
- "
- }
-
- MouseArea {
- id: mapMouseArea
- anchors.fill: parent
- onPositionChanged: {
- if (pressed && containsMouse) {
- var xx = Math.max(0, Math.min(mouse.x, parent.width))
- var yy = Math.max(0, Math.min(mouse.y, parent.height))
- saturationSlider.value = 1.0 - yy / parent.height
- lightnessSlider.value = xx / parent.width
- // TODO if we constrain the movement here, can avoid the containsMouse test
- crosshairs.x = mouse.x - crosshairs.radius
- crosshairs.y = mouse.y - crosshairs.radius
- }
- }
- onPressed: positionChanged(mouse)
- }
-
- Image {
- id: crosshairs
- property int radius: width / 2 // truncated to int
- source: "images/crosshairs.png"
- }
-
- BorderImage {
- anchors.fill: parent
- anchors.margins: -1
- anchors.leftMargin: -2
- source: "images/sunken_frame.png"
- border.left: 8
- border.right: 8
- border.top: 8
- border.bottom: 8
- }
- }
- }
-
- Column {
- id: sliders
- anchors {
- top: paletteFrame.bottom
- left: parent.left
- right: parent.right
- margins: content.outerSpacing
- }
- spacing: content.spacing
-
- ColorSlider {
- id: hueSlider
- value: 0.5
- onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
- text: qsTr("Hue")
- trackDelegate: Rectangle {
- rotation: -90
- transformOrigin: Item.TopLeft
- gradient: Gradient {
- GradientStop {position: 0.000; color: Qt.rgba(1, 0, 0, 1)}
- GradientStop {position: 0.167; color: Qt.rgba(1, 1, 0, 1)}
- GradientStop {position: 0.333; color: Qt.rgba(0, 1, 0, 1)}
- GradientStop {position: 0.500; color: Qt.rgba(0, 1, 1, 1)}
- GradientStop {position: 0.667; color: Qt.rgba(0, 0, 1, 1)}
- GradientStop {position: 0.833; color: Qt.rgba(1, 0, 1, 1)}
- GradientStop {position: 1.000; color: Qt.rgba(1, 0, 0, 1)}
- }
- }
- }
-
- ColorSlider {
- id: saturationSlider
- visible: !content.usePaletteMap
- value: 0.5
- onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
- text: qsTr("Saturation")
- trackDelegate: Rectangle {
- rotation: -90
- transformOrigin: Item.TopLeft
- gradient: Gradient {
- GradientStop { position: 0; color: Qt.hsla(hueSlider.value, 0.0, lightnessSlider.value, 1.0) }
- GradientStop { position: 1; color: Qt.hsla(hueSlider.value, 1.0, lightnessSlider.value, 1.0) }
- }
- }
- }
-
- ColorSlider {
- id: lightnessSlider
- visible: !content.usePaletteMap
- value: 0.5
- onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
- text: qsTr("Luminosity")
- trackDelegate: Rectangle {
- rotation: -90
- transformOrigin: Item.TopLeft
- gradient: Gradient {
- GradientStop { position: 0; color: "black" }
- GradientStop { position: 0.5; color: Qt.hsla(hueSlider.value, saturationSlider.value, 0.5, 1.0) }
- GradientStop { position: 1; color: "white" }
- }
- }
- }
-
- ColorSlider {
- id: alphaSlider
- minimum: 0.0
- maximum: 1.0
- value: 1.0
- onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
- text: qsTr("Alpha")
- visible: root.showAlphaChannel
- trackDelegate: Item {
- rotation: -90
- transformOrigin: Item.TopLeft
- Image {
- anchors {fill: parent}
- source: "images/checkers.png"
- fillMode: Image.TileVertically
- }
- Rectangle {
- anchors.fill: parent
- gradient: Gradient {
- GradientStop { position: 0; color: "transparent" }
- GradientStop { position: 1; color: Qt.hsla(hueSlider.value,
- saturationSlider.value,
- lightnessSlider.value, 1.0) }
- } }
- }
- }
- }
-
- Item {
- id: buttonRow
- height: Math.max(buttonsOnly.height, copyIcon.height)
- width: parent.width
- anchors {
- left: parent.left
- right: parent.right
- bottom: content.bottom
- margins: content.outerSpacing
- }
- Row {
- spacing: content.spacing
- height: parent.height
- TextField {
- id: colorField
- text: root.currentColor.toString()
- anchors.verticalCenter: parent.verticalCenter
- onAccepted: root.currentColor = text
- Component.onCompleted: width = implicitWidth + 10
- }
- Image {
- id: copyIcon
- anchors.verticalCenter: parent.verticalCenter
- source: "images/copy.png"
- MouseArea {
- anchors.fill: parent
- onClicked: colorField.copyAll()
- }
- }
- }
- Row {
- id: buttonsOnly
- spacing: content.spacing
- anchors.right: parent.right
- Button {
- id: cancelButton
- text: "Cancel"
- onClicked: root.reject()
- }
- Button {
- id: okButton
- text: "OK"
- onClicked: root.accept()
- }
- }
- }
- }
-}
diff --git a/src/imports/dialogs/DefaultFileDialog.qml b/src/imports/dialogs/DefaultFileDialog.qml
deleted file mode 100644
index 627a719f60..0000000000
--- a/src/imports/dialogs/DefaultFileDialog.qml
+++ /dev/null
@@ -1,394 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Dialogs 1.0
-import QtQuick.Window 2.1
-import Qt.labs.folderlistmodel 2.0
-import "qml"
-
-AbstractFileDialog {
- id: root
- onVisibleChanged: {
- if (visible) {
- __selectedIndices = []
- __lastClickedIdx = -1
- currentPathField.visible = false
- }
- }
- onFolderChanged: {
- var str = new String(folder)
- if (str.indexOf("qrc:") === 0)
- folder = "file:" + str.slice(4)
- if (view.model.folder != folder)
- view.model.folder = folder
- }
-
- property real __textX: titleBar.height
- property SystemPalette __palette
- property var __selectedIndices: []
- property int __lastClickedIdx: -1
-
- function __dirDown(path) {
- view.model.folder = "file://" + path
- __lastClickedIdx = -1
- __selectedIndices = []
- }
- function __dirUp() {
- if (view.model.parentFolder == "")
- view.model.folder = "file:///"
- else
- view.model.folder = view.model.parentFolder
- __lastClickedIdx = -1
- __selectedIndices = []
- }
- function __up(extend) {
- if (view.currentIndex > 0)
- --view.currentIndex
- else
- view.currentIndex = 0
- if (extend) {
- if (__selectedIndices.indexOf(view.currentIndex) < 0) {
- var selCopy = __selectedIndices
- selCopy.push(view.currentIndex)
- __selectedIndices = selCopy
- }
- } else
- __selectedIndices = [view.currentIndex]
- }
- function __down(extend) {
- if (view.currentIndex < view.model.count - 1)
- ++view.currentIndex
- else
- view.currentIndex = view.model.count - 1
- if (extend) {
- if (__selectedIndices.indexOf(view.currentIndex) < 0) {
- var selCopy = __selectedIndices
- selCopy.push(view.currentIndex)
- __selectedIndices = selCopy
- }
- } else
- __selectedIndices = [view.currentIndex]
- }
- function __acceptSelection() {
- clearSelection()
- if (selectFolder && __selectedIndices.length == 0)
- addSelection(folder)
- else if (__selectedIndices.length > 0) {
- __selectedIndices.map(function(idx) {
- if (view.model.isFolder(idx)) {
- if (selectFolder)
- addSelection(view.model.get(idx, "fileURL"))
- } else {
- if (!selectFolder)
- addSelection(view.model.get(idx, "fileURL"))
- }
- })
- } else {
- addSelection(pathToUrl(currentPathField.text))
- }
- accept()
- }
-
- Rectangle {
- id: content
- property int maxSize: Math.min(Screen.desktopAvailableWidth, Screen.desktopAvailableHeight)
- // TODO: QTBUG-29817 geometry from AbstractFileDialog
- implicitWidth: Math.min(maxSize, Screen.pixelDensity * 100)
- implicitHeight: Math.min(maxSize, Screen.pixelDensity * 80)
- color: __palette.window
- focus: root.visible && !currentPathField.visible
- property real spacing: 6
- property real outerSpacing: 12
- SystemPalette { id: __palette }
-
- Component {
- id: folderDelegate
- Rectangle {
- id: wrapper
- function launch() {
- if (view.model.isFolder(index)) {
- __dirDown(filePath)
- } else {
- root.__acceptSelection()
- }
- }
- width: content.width
- height: nameText.implicitHeight * 1.5
- color: "transparent"
- Rectangle {
- id: itemHighlight
- visible: root.__selectedIndices.indexOf(index) >= 0
- anchors.fill: parent
- color: __palette.highlight
- }
- Image {
- id: icon
- source: "images/folder.png"
- height: wrapper.height - y * 2; width: height
- x: (root.__textX - width) / 2
- y: 2
- visible: view.model.isFolder(index)
- }
- Text {
- id: nameText
- anchors.fill: parent; verticalAlignment: Text.AlignVCenter
- text: fileName
- anchors.leftMargin: root.__textX
- color: itemHighlight.visible ? __palette.highlightedText : __palette.windowText
- elide: Text.ElideRight
- }
- MouseArea {
- id: mouseRegion
- anchors.fill: parent
- onDoubleClicked: {
- __selectedIndices = [index]
- root.__lastClickedIdx = index
- launch()
- }
- onClicked: {
- view.currentIndex = index
- if (mouse.modifiers & Qt.ControlModifier && root.selectMultiple) {
- // modifying the contents of __selectedIndices doesn't notify,
- // so we have to re-assign the variable
- var selCopy = __selectedIndices
- var existingIdx = selCopy.indexOf(index)
- if (existingIdx >= 0)
- selCopy.splice(existingIdx, 1)
- else
- selCopy.push(index)
- __selectedIndices = selCopy
- } else if (mouse.modifiers & Qt.ShiftModifier && root.selectMultiple) {
- if (root.__lastClickedIdx >= 0) {
- var sel = []
- if (index > __lastClickedIdx) {
- for (var i = root.__lastClickedIdx; i <= index; i++)
- sel.push(i)
- } else {
- for (var i = root.__lastClickedIdx; i >= index; i--)
- sel.push(i)
- }
- __selectedIndices = sel
- }
- } else {
- __selectedIndices = [index]
- root.__lastClickedIdx = index
- }
- }
- }
- }
- }
-
- Keys.onPressed: {
- event.accepted = true
- switch (event.key) {
- case Qt.Key_Up:
- root.__up(event.modifiers & Qt.ShiftModifier && root.selectMultiple)
- break
- case Qt.Key_Down:
- root.__down(event.modifiers & Qt.ShiftModifier && root.selectMultiple)
- break
- case Qt.Key_Left:
- root.__dirUp()
- break
- case Qt.Key_Return:
- case Qt.Key_Select:
- case Qt.Key_Right:
- if (view.currentItem)
- view.currentItem.launch()
- else
- root.__acceptSelection()
- break
- case Qt.Key_Back:
- case Qt.Key_Escape:
- reject()
- break
- case Qt.Key_C:
- if (event.modifiers & Qt.ControlModifier)
- currentPathField.copyAll()
- break
- case Qt.Key_V:
- if (event.modifiers & Qt.ControlModifier) {
- currentPathField.visible = true
- currentPathField.paste()
- }
- break
- default:
- // do nothing
- event.accepted = false
- break
- }
- }
-
- ListView {
- id: view
- anchors.top: titleBar.bottom
- anchors.bottom: bottomBar.top
- clip: true
- x: 0
- width: parent.width
- model: FolderListModel {
- onFolderChanged: {
- root.folder = folder
- currentPathField.text = root.urlToPath(view.model.folder)
- }
- }
- delegate: folderDelegate
- highlight: Rectangle {
- color: "transparent"
- border.color: Qt.darker(__palette.window, 1.3)
- }
- highlightMoveDuration: 0
- highlightMoveVelocity: -1
- }
-
- MouseArea {
- anchors.fill: view
- enabled: currentPathField.visible
- onClicked: currentPathField.visible = false
- }
-
-
- Item {
- id: titleBar
- width: parent.width
- height: currentPathField.height * 1.5
- Rectangle {
- anchors.fill: parent
- color: Qt.darker(__palette.window, 1.1)
- border.color: Qt.darker(__palette.window, 1.3)
- }
- Rectangle {
- id: upButton
- width: root.__textX
- height: titleBar.height
- color: "transparent"
-
- Image {
- id: upButtonImage
- anchors.centerIn: parent; source: "images/up.png"
- }
- MouseArea { id: upRegion; anchors.centerIn: parent
- width: 56
- height: parent.height
- onClicked: if (view.model.parentFolder !== "") __dirUp()
- }
- states: [
- State {
- name: "pressed"
- when: upRegion.pressed
- PropertyChanges { target: upButton; color: __palette.highlight }
- }
- ]
- }
- Text {
- id: currentPathText
- anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: __textX; anchors.rightMargin: content.spacing
- text: root.urlToPath(view.model.folder)
- color: __palette.text
- elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
- MouseArea {
- anchors.fill: parent
- onClicked: currentPathField.visible = true
- }
- }
- TextField {
- id: currentPathField
- anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: __textX; anchors.rightMargin: content.spacing
- visible: false
- focus: visible
- onAccepted: {
- root.clearSelection()
- if (root.addSelection(root.pathToUrl(text)))
- root.accept()
- else
- view.model.folder = root.pathFolder(text)
- }
- onDownPressed: currentPathField.visible = false
- onBackPressed: reject()
- onEscapePressed: reject()
- }
- }
- Rectangle {
- id: bottomBar
- width: parent.width
- height: buttonRow.height + buttonRow.spacing * 2
- anchors.bottom: parent.bottom
- color: Qt.darker(__palette.window, 1.1)
- border.color: Qt.darker(__palette.window, 1.3)
-
- Row {
- id: buttonRow
- anchors.right: parent.right
- anchors.rightMargin: spacing
- anchors.verticalCenter: parent.verticalCenter
- spacing: content.spacing
- TextField {
- id: filterField
- text: root.selectedNameFilter
- visible: !selectFolder
- width: bottomBar.width - cancelButton.width - okButton.width - parent.spacing * 5
- anchors.verticalCenter: parent.verticalCenter
- onAccepted: {
- root.selectNameFilter(text)
- view.model.nameFilters = text
- }
- }
- Button {
- id: cancelButton
- text: "Cancel"
- onClicked: root.reject()
- }
- Button {
- id: okButton
- text: "OK"
- onClicked: {
- if (view.model.isFolder(view.currentIndex) && !selectFolder)
- __dirDown(view.model.get(view.currentIndex, "filePath"))
- else
- root.__acceptSelection()
- }
- }
- }
- }
- }
-}
diff --git a/src/imports/dialogs/DefaultFontDialog.qml b/src/imports/dialogs/DefaultFontDialog.qml
deleted file mode 100644
index 29feed342f..0000000000
--- a/src/imports/dialogs/DefaultFontDialog.qml
+++ /dev/null
@@ -1,483 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Window 2.1
-import QtQuick.Dialogs 1.1
-import QtQuick.Dialogs.Private 1.1
-import "qml"
-
-AbstractFontDialog {
- id: root
-
- property alias font: content.externalFont
-
- Rectangle {
- id: content
- implicitWidth: Math.min(Screen.desktopAvailableWidth, implicitHeight * 1.2)
- implicitHeight: Math.min(Screen.desktopAvailableHeight, settingsBottom.implicitHeight * 3)
- color: palette.window
- focus: root.visible
- property real spacing: 6
- property real outerSpacing: 12
- property real listMargins: 4
- property real delegateHeightMultiplier: 1.5
- property real extraWidth: width > 400 ? width - 400 : 0
- property real extraHeight: height > initialHeight ? height - initialHeight : 0
- property real initialHeight: -1
- onHeightChanged: if (visible && initialHeight < 0) initialHeight = height
-
- property color borderColor: Qt.darker(palette.button, 1.5)
-
- property font font: Qt.font({ family: "Helvetica", pointSize: 24, weight: Font.Normal })
- property font externalFont
- property string writingSystem
- property string writingSystemSample
- property var pointSizes
-
- onFontChanged: externalFont = font
-
- onExternalFontChanged: {
- if (content.font != content.externalFont) {
- font = externalFont
- wsListView.reset()
- fontListView.reset()
- weightListView.reset()
- }
- }
-
- Keys.onPressed: {
- event.accepted = true
- switch (event.key) {
- case Qt.Key_Return:
- case Qt.Key_Select:
- root.font = content.font
- root.accept()
- break
- case Qt.Key_Escape:
- case Qt.Key_Back:
- reject()
- break
- default:
- // do nothing
- event.accepted = false
- break
- }
- }
-
- SystemPalette { id: palette }
-
- Column {
- id: contentColumn
- anchors.fill: parent
- anchors.margins: content.outerSpacing
- spacing: content.outerSpacing
-
- Grid {
- id: settingsTop
- columns: 3
- spacing: content.spacing
- width: parent.width
- height: parent.height - buttonRow.height - settingsBottom.height - parent.spacing * 2
- property real columnHeight: height - writingSystemLabel.height - spacing
-
- Text { id: writingSystemLabel; text: qsTr("Writing System"); font.bold: true }
- Text { id: fontNameLabel; text: qsTr("Font"); font.bold: true }
- Text { id: sizeLabel; text: qsTr("Size"); font.bold: true }
- Rectangle {
- id: wsColumn
- radius: 3
- color: palette.window
- border.color: content.borderColor
- implicitWidth: Math.max(writingSystemLabel.implicitWidth, 100) + content.extraWidth / 5
- height: parent.columnHeight
- clip: true
- ListView {
- id: wsListView
- anchors.fill: parent
- anchors.margins: content.listMargins
- anchors.topMargin: 2
- highlightMoveDuration: 0
- onHeightChanged: positionViewAtIndex(currentIndex, ListView.Contain)
- function reset() {
- if (wsModel.count > 0) {
- content.writingSystem = wsModel.get(0).name;
- fontModel.writingSystem = content.writingSystem;
- content.writingSystemSample = wsModel.get(0).sample;
- }
- }
-
- model: WritingSystemListModel {
- id: wsModel
- Component.onCompleted: wsListView.reset()
- }
- highlight: Rectangle {
- color: palette.highlight
- x: 2 - wsListView.anchors.margins
- width: wsListView.parent.width - 4
- }
- delegate: Item {
- width: parent.width
- height: wsText.height * content.delegateHeightMultiplier
- Text {
- id: wsText
- text: name
- width: parent.width
- elide: Text.ElideRight
- color: index === wsListView.currentIndex ? palette.highlightedText : palette.windowText
- anchors.verticalCenter: parent.verticalCenter
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- wsListView.currentIndex = index;
- content.writingSystem = wsModel.get(wsListView.currentIndex).name;
- fontModel.writingSystem = content.writingSystem;
- content.writingSystemSample = wsModel.get(wsListView.currentIndex).sample;
- }
- }
- }
- }
- }
- Rectangle {
- radius: 3
- color: palette.window
- border.color: content.borderColor
- implicitWidth: Math.max(fontNameLabel.implicitWidth, parent.width - wsColumn.implicitWidth - pointSizesColumn.implicitWidth - parent.spacing * 2)
- height: parent.columnHeight
- clip: true
- ListView {
- id: fontListView
- anchors.fill: parent
- anchors.margins: content.listMargins
- anchors.topMargin: 2
- highlightMoveDuration: 0
- onHeightChanged: positionViewAtIndex(currentIndex, ListView.Contain)
- function reset() {
- fontModel.findIndex()
- content.pointSizes = fontModel.pointSizes()
- fontModel.findPointSizesIndex()
- }
-
- model: FontListModel {
- id: fontModel
- scalableFonts: root.scalableFonts
- nonScalableFonts: root.nonScalableFonts
- monospacedFonts: root.monospacedFonts
- proportionalFonts: root.proportionalFonts
- Component.onCompleted: fontListView.reset()
- onModelReset: { findIndex(); }
- function findIndex() {
- if (fontModel.count <= 0)
- return
-
- if (content.font.family == "") {
- content.font.family = fontModel.get(0).family
- fontListView.currentIndex = 0
- } else {
- var find = false
- for (var i = 0; i < fontModel.count; ++i) {
- if (content.font.family == fontModel.get(i).family) {
- find = true
- fontListView.currentIndex = i
- break
- }
- }
- if (find == false) {
- content.font.family = fontModel.get(0).family
- fontListView.currentIndex = 0
- }
- }
- }
- function findPointSizesIndex() {
- if (content.pointSizes.length <= 0)
- return
-
- var find = false
- for (var i = 0; i < content.pointSizes.length; ++i) {
- if (content.font.pointSize == content.pointSizes[i]) {
- find = true
- pointSizesListView.currentIndex = i
- break
- }
- }
- if (find == false) {
- content.font.pointSize = content.pointSizes[0]
- pointSizesListView.currentIndex = 0
- }
- }
- }
- highlight: Rectangle {
- color: palette.highlight
- x: 2 - fontListView.anchors.margins
- width: fontListView.parent.width - 4
- }
- delegate: Item {
- width: parent.width
- height: fontText.height * content.delegateHeightMultiplier
- Text {
- id: fontText
- text: family
- width: parent.width
- elide: Text.ElideRight
- color: index === fontListView.currentIndex ? palette.highlightedText : palette.windowText
- anchors.verticalCenter: parent.verticalCenter
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- fontListView.currentIndex = index
- content.font.family = fontModel.get(fontListView.currentIndex).family
- }
- }
- }
- }
- }
- Rectangle {
- id: pointSizesColumn
- radius: 3
- color: palette.window
- border.color: content.borderColor
- implicitWidth:sizeLabel.implicitWidth * 2
- height: parent.columnHeight
- clip: true
- ListView {
- id: pointSizesListView
- anchors.fill: parent
- anchors.margins: content.listMargins
- anchors.topMargin: 2
- highlightMoveDuration: 0
- onHeightChanged: positionViewAtIndex(currentIndex, ListView.Contain)
- model: content.pointSizes
- highlight: Rectangle {
- color: palette.highlight
- x: 2 - pointSizesListView.anchors.margins
- width: pointSizesListView.parent.width - 4
- }
- delegate: Item {
- width: parent.width
- height: pointSizesText.height * content.delegateHeightMultiplier
- Text {
- id: pointSizesText
- text: content.pointSizes[index]
- width: parent.width
- elide: Text.ElideRight
- color: index === pointSizesListView.currentIndex ? palette.highlightedText : palette.windowText
- anchors.verticalCenter: parent.verticalCenter
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- pointSizesListView.currentIndex = index
- content.font.pointSize = content.pointSizes[pointSizesListView.currentIndex]
- }
- }
- }
- }
- }
- }
-
- Grid {
- id: settingsBottom
- columns: 3
- spacing: content.spacing
- width: parent.width
- height: initialHeight + content.extraHeight / 4
- property real initialHeight
- property real secondRowHeight: height - weightLabel.height - spacing
- Component.onCompleted: initialHeight = implicitHeight
-
- Text { id: weightLabel; text: qsTr("Weight"); font.bold: true }
- Text { id: optionsLabel; text: qsTr("Style"); font.bold: true }
- Text { id: sampleLabel; text: qsTr("Sample"); font.bold: true }
- Rectangle {
- id: weightColumn
- radius: 3
- color: palette.window
- border.color: content.borderColor
- implicitWidth: optionsColumn.implicitWidth
- implicitHeight: optionsColumn.implicitHeight
- height: parent.secondRowHeight
- clip: true
- ListView {
- id: weightListView
- anchors.fill: parent
- anchors.margins: content.listMargins
- anchors.topMargin: 2
- highlightMoveDuration: 0
- onHeightChanged: positionViewAtIndex(currentIndex, ListView.Contain)
- function reset() {
- weightModel.findIndex()
- }
-
- model: ListModel {
- id: weightModel
- ListElement {
- name: "Light"
- weight: Font.Light
- }
- ListElement {
- name: "Normal"
- weight: Font.Normal
- }
- ListElement {
- name: "DemiBold"
- weight: Font.DemiBold
- }
- ListElement {
- name: "Bold"
- weight: Font.Bold
- }
- ListElement {
- name: "Black"
- weight: Font.Black
- }
- Component.onCompleted: weightListView.reset()
- function findIndex() {
- var find = false
- for (var i = 0; i < weightModel.count; ++i) {
- if (content.font.weight == weightModel.get(i).weight) {
- find = true
- weightListView.currentIndex = i
- break
- }
- }
- if (find == false) {
- content.font.weight = weightModel.get(1).family
- fontListView.currentIndex = 1
- }
- }
- }
- highlight: Rectangle {
- color: palette.highlight
- x: 2 - weightListView.anchors.margins
- width: weightListView.parent.width - 4
- }
- delegate: Item {
- width: parent.width
- height: weightText.height * content.delegateHeightMultiplier
- Text {
- id: weightText
- text: name
- width: parent.width
- elide: Text.ElideRight
- color: index === weightListView.currentIndex ? palette.highlightedText : palette.windowText
- anchors.verticalCenter: parent.verticalCenter
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- weightListView.currentIndex = index
- content.font.weight = weightModel.get(weightListView.currentIndex).weight
- }
- }
- }
- }
- }
- Column {
- id: optionsColumn
- spacing: 4
- CheckBox {
- id: italicCheckBox
- text: qsTr("Italic")
- checked: content.font.italic
- onClicked: { content.font.italic = italicCheckBox.checked }
- }
- CheckBox {
- id: underlineCheckBox
- text: qsTr("Underline")
- checked: content.font.underline
- onClicked: { content.font.underline = underlineCheckBox.checked }
- }
- CheckBox {
- id: overlineCheckBox
- text: qsTr("Overline")
- checked: content.font.overline
- onClicked: { content.font.overline = overlineCheckBox.checked }
- }
- CheckBox {
- id: strikeoutCheckBox
- text: qsTr("Strikeout")
- checked: content.font.strikeout
- onClicked: { content.font.strikeout = strikeoutCheckBox.checked }
- }
- }
- Rectangle {
- clip: true
- implicitWidth: sample.implicitWidth + parent.spacing
- implicitHeight: optionsColumn.implicitHeight
- width: parent.width - weightColumn.width - optionsColumn.width - parent.spacing * 2
- height: parent.secondRowHeight
- color: palette.window
- border.color: content.borderColor
- Text {
- id: sample
- anchors.centerIn: parent
- font: content.font
- text: content.writingSystemSample
- }
- }
- }
-
- Item {
- id: buttonRow
- height: buttonsOnly.height
- width: parent.width
- Row {
- id: buttonsOnly
- spacing: content.spacing
- anchors.right: parent.right
- Button {
- text: qsTr("Cancel")
- onClicked: root.reject()
- }
- Button {
- text: qsTr("OK")
- onClicked: {
- root.font = content.font
- root.accept()
- }
- }
- }
- }
- }
- }
-}
-
diff --git a/src/imports/dialogs/DefaultMessageDialog.qml b/src/imports/dialogs/DefaultMessageDialog.qml
deleted file mode 100644
index ba29469b5e..0000000000
--- a/src/imports/dialogs/DefaultMessageDialog.qml
+++ /dev/null
@@ -1,330 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Window 2.1
-import QtQuick.Dialogs 1.1
-import "qml"
-
-AbstractMessageDialog {
- id: root
-
- Rectangle {
- id: content
- property real spacing: 6
- property real outerSpacing: 12
- property real buttonsRowImplicitWidth: Screen.pixelDensity * 50
- implicitHeight: contentColumn.implicitHeight + outerSpacing * 2
- onImplicitHeightChanged: root.height = implicitHeight
- implicitWidth: Math.min(Screen.desktopAvailableWidth * 0.9, Math.max(
- mainText.implicitWidth, buttonsRowImplicitWidth) + outerSpacing * 2);
- onImplicitWidthChanged: root.width = implicitWidth
- color: palette.window
- focus: root.visible
- Keys.onPressed: {
- event.accepted = true
- if (event.modifiers === Qt.ControlModifier)
- switch (event.key) {
- case Qt.Key_A:
- detailedText.selectAll()
- break
- case Qt.Key_C:
- detailedText.copy()
- break
- } else switch (event.key) {
- case Qt.Key_Escape:
- case Qt.Key_Back:
- reject()
- break
- case Qt.Key_Enter:
- case Qt.Key_Return:
- accept()
- break
- }
- }
-
- Column {
- id: contentColumn
- spacing: content.spacing
- anchors {
- top: parent.top
- left: parent.left
- right: parent.right
- margins: content.outerSpacing
- }
-
- SystemPalette { id: palette }
-
- Item {
- width: parent.width
- height: Math.max(icon.height, mainText.height + informativeText.height + content.spacing)
- Image {
- id: icon
- source: root.standardIconSource
- }
-
- Text {
- id: mainText
- anchors {
- left: icon.right
- leftMargin: content.spacing
- right: parent.right
- }
- text: root.text
- font.weight: Font.Bold
- wrapMode: Text.WordWrap
- }
-
- Text {
- id: informativeText
- anchors {
- left: icon.right
- right: parent.right
- top: mainText.bottom
- leftMargin: content.spacing
- topMargin: content.spacing
- }
- text: root.informativeText
- wrapMode: Text.WordWrap
- }
- }
-
-
- Flow {
- id: buttons
- spacing: content.spacing
- layoutDirection: Qt.RightToLeft
- width: parent.width + content.outerSpacing
- x: -content.outerSpacing
- Button {
- id: okButton
- text: "OK"
- onClicked: root.click(StandardButton.Ok)
- visible: root.standardButtons & StandardButton.Ok
- }
- Button {
- id: openButton
- text: "Open"
- onClicked: root.click(StandardButton.Open)
- visible: root.standardButtons & StandardButton.Open
- }
- Button {
- id: saveButton
- text: "Save"
- onClicked: root.click(StandardButton.Save)
- visible: root.standardButtons & StandardButton.Save
- }
- Button {
- id: saveAllButton
- text: "Save All"
- onClicked: root.click(StandardButton.SaveAll)
- visible: root.standardButtons & StandardButton.SaveAll
- }
- Button {
- id: retryButton
- text: "Retry"
- onClicked: root.click(StandardButton.Retry)
- visible: root.standardButtons & StandardButton.Retry
- }
- Button {
- id: ignoreButton
- text: "Ignore"
- onClicked: root.click(StandardButton.Ignore)
- visible: root.standardButtons & StandardButton.Ignore
- }
- Button {
- id: applyButton
- text: "Apply"
- onClicked: root.click(StandardButton.Apply)
- visible: root.standardButtons & StandardButton.Apply
- }
- Button {
- id: yesButton
- text: "Yes"
- onClicked: root.click(StandardButton.Yes)
- visible: root.standardButtons & StandardButton.Yes
- }
- Button {
- id: yesAllButton
- text: "Yes to All"
- onClicked: root.click(StandardButton.YesToAll)
- visible: root.standardButtons & StandardButton.YesToAll
- }
- Button {
- id: noButton
- text: "No"
- onClicked: root.click(StandardButton.No)
- visible: root.standardButtons & StandardButton.No
- }
- Button {
- id: noAllButton
- text: "No to All"
- onClicked: root.click(StandardButton.NoToAll)
- visible: root.standardButtons & StandardButton.NoToAll
- }
- Button {
- id: discardButton
- text: "Discard"
- onClicked: root.click(StandardButton.Discard)
- visible: root.standardButtons & StandardButton.Discard
- }
- Button {
- id: resetButton
- text: "Reset"
- onClicked: root.click(StandardButton.Reset)
- visible: root.standardButtons & StandardButton.Reset
- }
- Button {
- id: restoreDefaultsButton
- text: "Restore Defaults"
- onClicked: root.click(StandardButton.RestoreDefaults)
- visible: root.standardButtons & StandardButton.RestoreDefaults
- }
- Button {
- id: cancelButton
- text: "Cancel"
- onClicked: root.click(StandardButton.Cancel)
- visible: root.standardButtons & StandardButton.Cancel
- }
- Button {
- id: abortButton
- text: "Abort"
- onClicked: root.click(StandardButton.Abort)
- visible: root.standardButtons & StandardButton.Abort
- }
- Button {
- id: closeButton
- text: "Close"
- onClicked: root.click(StandardButton.Close)
- visible: root.standardButtons & StandardButton.Close
- }
- Button {
- id: moreButton
- text: "Show Details..."
- onClicked: content.state = (content.state === "" ? "expanded" : "")
- visible: root.detailedText.length > 0
- }
- Button {
- id: helpButton
- text: "Help"
- onClicked: root.click(StandardButton.Help)
- visible: root.standardButtons & StandardButton.Help
- }
- onVisibleChildrenChanged: calculateImplicitWidth()
- }
- }
-
- Item {
- id: details
- width: parent.width
- implicitHeight: detailedText.implicitHeight + content.spacing
- height: 0
- clip: true
-
- anchors {
- left: parent.left
- right: parent.right
- top: contentColumn.bottom
- topMargin: content.spacing
- leftMargin: content.outerSpacing
- rightMargin: content.outerSpacing
- }
-
- Flickable {
- id: flickable
- contentHeight: detailedText.height
- anchors.fill: parent
- anchors.topMargin: content.spacing
- anchors.bottomMargin: content.outerSpacing
- TextEdit {
- id: detailedText
- text: root.detailedText
- width: details.width
- wrapMode: Text.WordWrap
- readOnly: true
- selectByMouse: true
- }
- }
-
- Component {
- id: edgeFade
- EdgeFade {
- fadeColor: palette.window
- topThreshold: flickable.atYBeginning ? 0 : content.spacing * 3
- bottomThreshold: flickable.atYEnd ? 0 : content.spacing * 3
- }
- }
-
- Loader {
- sourceComponent: flickable.height < flickable.contentHeight ? edgeFade : undefined
- anchors.fill: parent
- }
-
- }
-
- states: [
- State {
- name: "expanded"
- PropertyChanges {
- target: details
- height: content.height - contentColumn.height - content.spacing - content.outerSpacing
- }
- PropertyChanges {
- target: content
- implicitHeight: contentColumn.implicitHeight + content.spacing * 2 +
- detailedText.implicitHeight + content.outerSpacing * 2
- }
- PropertyChanges {
- target: moreButton
- text: "Hide Details"
- }
- }
- ]
- }
- function calculateImplicitWidth() {
- if (buttons.visibleChildren.length < 2)
- return;
- var calcWidth = 0;
- for (var i = 0; i < buttons.visibleChildren.length; ++i)
- calcWidth += Math.max(100, buttons.visibleChildren[i].implicitWidth) + content.spacing
- content.buttonsRowImplicitWidth = content.outerSpacing + calcWidth
- }
- Component.onCompleted: calculateImplicitWidth()
-}
diff --git a/src/imports/dialogs/WidgetFileDialog.qml b/src/imports/dialogs/WidgetFileDialog.qml
deleted file mode 100644
index c8f59d20a7..0000000000
--- a/src/imports/dialogs/WidgetFileDialog.qml
+++ /dev/null
@@ -1,44 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.PrivateWidgets 1.0
-
-QtFileDialog { }
diff --git a/src/imports/dialogs/WidgetFontDialog.qml b/src/imports/dialogs/WidgetFontDialog.qml
deleted file mode 100644
index 69f98b28a2..0000000000
--- a/src/imports/dialogs/WidgetFontDialog.qml
+++ /dev/null
@@ -1,44 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.2
-import QtQuick.PrivateWidgets 1.1
-
-QtFontDialog { }
diff --git a/src/imports/dialogs/WidgetMessageDialog.qml b/src/imports/dialogs/WidgetMessageDialog.qml
deleted file mode 100644
index 8bc3eccfd7..0000000000
--- a/src/imports/dialogs/WidgetMessageDialog.qml
+++ /dev/null
@@ -1,44 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.PrivateWidgets 1.1
-
-QtMessageDialog { }
diff --git a/src/imports/dialogs/dialogs.pro b/src/imports/dialogs/dialogs.pro
deleted file mode 100644
index 1abad55883..0000000000
--- a/src/imports/dialogs/dialogs.pro
+++ /dev/null
@@ -1,97 +0,0 @@
-CXX_MODULE = qml
-TARGET = dialogplugin
-TARGETPATH = QtQuick/Dialogs
-IMPORT_VERSION = 1.1
-
-QMAKE_DOCS = $$PWD/doc/qtquickdialogs.qdocconf
-
-SOURCES += \
- qquickabstractmessagedialog.cpp \
- qquickplatformmessagedialog.cpp \
- qquickmessagedialog.cpp \
- qquickabstractfiledialog.cpp \
- qquickplatformfiledialog.cpp \
- qquickfiledialog.cpp \
- qquickabstractcolordialog.cpp \
- qquickplatformcolordialog.cpp \
- qquickcolordialog.cpp \
- qquickabstractfontdialog.cpp \
- qquickplatformfontdialog.cpp \
- qquickfontdialog.cpp \
- qquickabstractdialog.cpp \
- plugin.cpp
-
-HEADERS += \
- qquickabstractmessagedialog_p.h \
- qquickplatformmessagedialog_p.h \
- qquickmessagedialog_p.h \
- qquickdialogassets_p.h \
- qquickabstractfiledialog_p.h \
- qquickplatformfiledialog_p.h \
- qquickfiledialog_p.h \
- qquickabstractcolordialog_p.h \
- qquickplatformcolordialog_p.h \
- qquickcolordialog_p.h \
- qquickabstractfontdialog_p.h \
- qquickplatformfontdialog_p.h \
- qquickfontdialog_p.h \
- qquickabstractdialog_p.h
-
-DIALOGS_QML_FILES += \
- DefaultMessageDialog.qml \
- WidgetMessageDialog.qml \
- DefaultFileDialog.qml \
- WidgetFileDialog.qml \
- DefaultColorDialog.qml \
- WidgetColorDialog.qml \
- DefaultFontDialog.qml \
- WidgetFontDialog.qml \
- qml/Button.qml \
- qml/CheckBox.qml \
- qml/ColorSlider.qml \
- qml/EdgeFade.qml \
- qml/DefaultWindowDecoration.qml \
- qml/TextField.qml \
- qml/qmldir \
- images/critical.png \
- images/information.png \
- images/question.png \
- images/warning.png \
- images/checkers.png \
- images/checkmark.png \
- images/copy.png \
- images/crosshairs.png \
- images/slider_handle.png \
- images/sunken_frame.png \
- images/window_border.png \
- images/folder.png \
- images/up.png
-
-QT += quick-private gui gui-private core core-private qml
-
-# Create the resource file
-GENERATED_RESOURCE_FILE = $$OUT_PWD/dialogs.qrc
-
-RESOURCE_CONTENT = \
- "<RCC>" \
- "<qresource prefix=\"/QtQuick/Dialogs\">"
-
-for(resourcefile, DIALOGS_QML_FILES) {
- resourcefileabsolutepath = $$absolute_path($$resourcefile)
- relativepath_in = $$relative_path($$resourcefileabsolutepath, $$_PRO_FILE_PWD_)
- relativepath_out = $$relative_path($$resourcefileabsolutepath, $$OUT_PWD)
- RESOURCE_CONTENT += "<file alias=\"$$relativepath_in\">$$relativepath_out</file>"
-}
-
-RESOURCE_CONTENT += \
- "</qresource>" \
- "</RCC>"
-
-write_file($$GENERATED_RESOURCE_FILE, RESOURCE_CONTENT)|error("Aborting.")
-
-RESOURCES += $$GENERATED_RESOURCE_FILE
-
-# In case of a debug build, deploy the QML files too
-CONFIG(debug, debug|release): QML_FILES += $$DIALOGS_QML_FILES
-
-load(qml_plugin)
diff --git a/src/imports/dialogs/doc/images/critical.png b/src/imports/dialogs/doc/images/critical.png
deleted file mode 100644
index dc9c5aebf4..0000000000
--- a/src/imports/dialogs/doc/images/critical.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/doc/images/information.png b/src/imports/dialogs/doc/images/information.png
deleted file mode 100644
index 0a2eb87d10..0000000000
--- a/src/imports/dialogs/doc/images/information.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/doc/images/question.png b/src/imports/dialogs/doc/images/question.png
deleted file mode 100644
index 2dd92fd791..0000000000
--- a/src/imports/dialogs/doc/images/question.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/doc/images/replacefile.png b/src/imports/dialogs/doc/images/replacefile.png
deleted file mode 100644
index d1479fa944..0000000000
--- a/src/imports/dialogs/doc/images/replacefile.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/doc/images/warning.png b/src/imports/dialogs/doc/images/warning.png
deleted file mode 100644
index cba78f6bea..0000000000
--- a/src/imports/dialogs/doc/images/warning.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/doc/qtquickdialogs.qdocconf b/src/imports/dialogs/doc/qtquickdialogs.qdocconf
deleted file mode 100644
index 1bad67790f..0000000000
--- a/src/imports/dialogs/doc/qtquickdialogs.qdocconf
+++ /dev/null
@@ -1,41 +0,0 @@
-include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
-
-project = QtQuickDialogs
-description = Qt Quick Dialogs Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
-version = $QT_VERSION
-
-qhp.projects = QtQuickDialogs
-
-qhp.QtQuickDialogs.file = qtquickdialogs.qhp
-qhp.QtQuickDialogs.namespace = org.qt-project.qtquickdialogs.$QT_VERSION_TAG
-qhp.QtQuickDialogs.virtualFolder = qtquickdialogs
-qhp.QtQuickDialogs.indexTitle = Qt Quick Dialogs
-qhp.QtQuickDialogs.indexRoot =
-
-qhp.QtQuickDialogs.filterAttributes = qtquickdialogs $QT_VERSION qtrefdoc
-qhp.QtQuickDialogs.customFilters.Qt.name = QtQuickDialogs $QT_VERSION
-qhp.QtQuickDialogs.customFilters.Qt.filterAttributes = qtquickdialogs $QT_VERSION
-
-qhp.QtQuickDialogs.subprojects = qtquickdialogsqmltypes
-qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.title = QML Types
-qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.indexTitle = Qt Quick Dialogs QML Types
-qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.selectors = fake:qmlclass
-qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.sortPages = true
-
-depends = qtqml qtquick qtgui qtwidgets qtdoc
-
-exampledirs += ../../../../examples/quick/dialogs
-
-examplesinstallpath = quick/dialogs
-
-headerdirs += ..
-
-sourcedirs += ..
-
-imagedirs += images
-
-excludedirs += ../qml
-
-navigation.landingpage = "Qt Quick Dialogs"
-navigation.qmltypespage = "Qt Quick Dialogs QML Types"
diff --git a/src/imports/dialogs/doc/src/qtquickdialogs-examples.qdoc b/src/imports/dialogs/doc/src/qtquickdialogs-examples.qdoc
deleted file mode 100644
index ee277f48dc..0000000000
--- a/src/imports/dialogs/doc/src/qtquickdialogs-examples.qdoc
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \group qtquickdialog_examples
- \ingroup qtquickexamples
- \title Qt Quick Examples - Dialogs
- \brief A Collection of examples for \l{Qt Quick Dialogs}, written in QML.
-
- These examples show how to use the \l{Qt Quick Dialogs}.
-*/
-
diff --git a/src/imports/dialogs/doc/src/qtquickdialogs-index.qdoc b/src/imports/dialogs/doc/src/qtquickdialogs-index.qdoc
deleted file mode 100644
index 5a1223b04d..0000000000
--- a/src/imports/dialogs/doc/src/qtquickdialogs-index.qdoc
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \group dialogs
- \title Dialogs
-*/
-
-/*!
- \page qtquickdialogs-index.html
- \title Qt Quick Dialogs
-
- \brief Qt Quick Dialogs submodule
-
- The module is new in Qt 5.1.
-
- \section1 Dialogs
-
- \annotatedlist dialogs
-
- \section1 Related information
-
- \section2 Examples
- \list
- \li \l{Qt Quick Examples - Dialogs}{Dialogs Examples}
- \endlist
-
- \section2 Reference
- \list
- \li \l{Qt Quick Dialogs QML Types}{QML Types}
- \endlist
-
-*/
-
diff --git a/src/imports/dialogs/images/checkers.png b/src/imports/dialogs/images/checkers.png
deleted file mode 100644
index 458d33de9d..0000000000
--- a/src/imports/dialogs/images/checkers.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/checkmark.png b/src/imports/dialogs/images/checkmark.png
deleted file mode 100644
index 821aafccdd..0000000000
--- a/src/imports/dialogs/images/checkmark.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/copy.png b/src/imports/dialogs/images/copy.png
deleted file mode 100644
index 2aeb28288f..0000000000
--- a/src/imports/dialogs/images/copy.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/critical.png b/src/imports/dialogs/images/critical.png
deleted file mode 100644
index dc9c5aebf4..0000000000
--- a/src/imports/dialogs/images/critical.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/crosshairs.png b/src/imports/dialogs/images/crosshairs.png
deleted file mode 100644
index 9a61946eca..0000000000
--- a/src/imports/dialogs/images/crosshairs.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/folder.png b/src/imports/dialogs/images/folder.png
deleted file mode 100644
index e53e2ad464..0000000000
--- a/src/imports/dialogs/images/folder.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/information.png b/src/imports/dialogs/images/information.png
deleted file mode 100644
index 0a2eb87d10..0000000000
--- a/src/imports/dialogs/images/information.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/question.png b/src/imports/dialogs/images/question.png
deleted file mode 100644
index 2dd92fd791..0000000000
--- a/src/imports/dialogs/images/question.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/slider_handle.png b/src/imports/dialogs/images/slider_handle.png
deleted file mode 100644
index e3b9654392..0000000000
--- a/src/imports/dialogs/images/slider_handle.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/sunken_frame.png b/src/imports/dialogs/images/sunken_frame.png
deleted file mode 100644
index 178c3092d2..0000000000
--- a/src/imports/dialogs/images/sunken_frame.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/up.png b/src/imports/dialogs/images/up.png
deleted file mode 100644
index b05f8025d0..0000000000
--- a/src/imports/dialogs/images/up.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/warning.png b/src/imports/dialogs/images/warning.png
deleted file mode 100644
index cba78f6bea..0000000000
--- a/src/imports/dialogs/images/warning.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/images/window_border.png b/src/imports/dialogs/images/window_border.png
deleted file mode 100644
index 431af8545d..0000000000
--- a/src/imports/dialogs/images/window_border.png
+++ /dev/null
Binary files differ
diff --git a/src/imports/dialogs/plugin.cpp b/src/imports/dialogs/plugin.cpp
deleted file mode 100644
index 70e12093b6..0000000000
--- a/src/imports/dialogs/plugin.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtQml/qqml.h>
-#include <QtQml/qqmlextensionplugin.h>
-#include "qquickmessagedialog_p.h"
-#include "qquickabstractmessagedialog_p.h"
-#include "qquickdialogassets_p.h"
-#include "qquickplatformmessagedialog_p.h"
-#include "qquickfiledialog_p.h"
-#include "qquickabstractfiledialog_p.h"
-#include "qquickplatformfiledialog_p.h"
-#include "qquickcolordialog_p.h"
-#include "qquickabstractcolordialog_p.h"
-#include "qquickplatformcolordialog_p.h"
-#include "qquickfontdialog_p.h"
-#include "qquickabstractfontdialog_p.h"
-#include "qquickplatformfontdialog_p.h"
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-
-//#define PURE_QML_ONLY
-//#define DEBUG_REGISTRATION
-
-static void initResources()
-{
- Q_INIT_RESOURCE(dialogs);
-}
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlmodule QtQuick.Dialogs 1.1
- \title Qt Quick Dialogs QML Types
- \ingroup qmlmodules
- \brief Provides QML types for standard file, color picker and message dialogs
-
- This QML module contains types for creating and interacting with system dialogs.
-
- To use the types in this module, import the module with the following line:
-
- \code
- import QtQuick.Dialogs 1.1
- \endcode
-*/
-
-class QtQuick2DialogsPlugin : public QQmlExtensionPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
-
-public:
- QtQuick2DialogsPlugin() : QQmlExtensionPlugin(), m_useResources(true) { }
-
- virtual void initializeEngine(QQmlEngine *engine, const char * uri) {
-#ifdef DEBUG_REGISTRATION
- qDebug() << Q_FUNC_INFO << uri << m_decorationComponentUrl;
-#else
- Q_UNUSED(uri)
-#endif
- QQuickAbstractDialog::m_decorationComponent =
- new QQmlComponent(engine, m_decorationComponentUrl, QQmlComponent::Asynchronous);
- }
-
- virtual void registerTypes(const char *uri) {
- initResources();
-
-#ifdef DEBUG_REGISTRATION
- qDebug() << Q_FUNC_INFO << uri;
-#endif
- Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Dialogs"));
- bool hasTopLevelWindows = QGuiApplicationPrivate::platformIntegration()->
- hasCapability(QPlatformIntegration::MultipleWindows);
- QDir qmlDir(baseUrl().toLocalFile());
- QDir widgetsDir(baseUrl().toLocalFile());
- // TODO: find the directory by searching rather than assuming a relative path
- widgetsDir.cd("../PrivateWidgets");
-
- // If at least one file was actually installed, then use installed qml files instead of resources.
- // This makes debugging and incremental development easier, whereas the "normal" installation
- // uses resources to save space and cut down on the number of files to deploy.
- if (qmlDir.exists(QString("DefaultFileDialog.qml")))
- m_useResources = false;
- m_decorationComponentUrl = m_useResources ?
- QUrl("qrc:/QtQuick/Dialogs/qml/DefaultWindowDecoration.qml") :
- QUrl::fromLocalFile(qmlDir.filePath(QString("qml/DefaultWindowDecoration.qml")));
-
- // Prefer the QPA dialog helpers if the platform supports them.
- // Else if there is a QWidget-based implementation, check whether it's
- // possible to instantiate it from Qt Quick.
- // Otherwise fall back to a pure-QML implementation.
-
- // MessageDialog
- qmlRegisterUncreatableType<QQuickStandardButton>(uri, 1, 1, "StandardButton",
- QLatin1String("Do not create objects of type StandardButton"));
- qmlRegisterUncreatableType<QQuickStandardIcon>(uri, 1, 1, "StandardIcon",
- QLatin1String("Do not create objects of type StandardIcon"));
-#ifndef PURE_QML_ONLY
- if (QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::MessageDialog))
- qmlRegisterType<QQuickPlatformMessageDialog>(uri, 1, 0, "MessageDialog");
- else
-#endif
- registerWidgetOrQmlImplementation<QQuickMessageDialog>(widgetsDir, qmlDir, "MessageDialog", uri, hasTopLevelWindows, 1, 1);
-
- // FileDialog
-#ifndef PURE_QML_ONLY
- if (QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FileDialog))
- qmlRegisterType<QQuickPlatformFileDialog>(uri, 1, 0, "FileDialog");
- else
-#endif
- registerWidgetOrQmlImplementation<QQuickFileDialog>(widgetsDir, qmlDir, "FileDialog", uri, hasTopLevelWindows, 1, 0);
-
- // ColorDialog
-#ifndef PURE_QML_ONLY
- if (QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::ColorDialog))
- qmlRegisterType<QQuickPlatformColorDialog>(uri, 1, 0, "ColorDialog");
- else
-#endif
- registerWidgetOrQmlImplementation<QQuickColorDialog>(widgetsDir, qmlDir, "ColorDialog", uri, hasTopLevelWindows, 1, 0);
-
- // FontDialog
-#ifndef PURE_QML_ONLY
- if (QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FontDialog))
- qmlRegisterType<QQuickPlatformFontDialog>(uri, 1, 1, "FontDialog");
- else
-#endif
- registerWidgetOrQmlImplementation<QQuickFontDialog>(widgetsDir, qmlDir, "FontDialog", uri, hasTopLevelWindows, 1, 1);
- }
-
-protected:
- template <class WrapperType>
- void registerWidgetOrQmlImplementation(QDir widgetsDir, QDir qmlDir,
- const char *qmlName, const char *uri, bool hasTopLevelWindows, int versionMajor, int versionMinor) {
- // qDebug() << "QtQuick2DialogsPlugin::registerWidgetOrQmlImplementation" << uri << qmlName << ": QML in" << qmlDir.absolutePath()
- // << "using resources?" << m_useResources << "; widgets in" << widgetsDir.absolutePath();
- bool needQmlImplementation = true;
-
-#ifdef PURE_QML_ONLY
- Q_UNUSED(widgetsDir)
- Q_UNUSED(hasTopLevelWindows)
-#else
- // If there is a qmldir and we have a QApplication instance (as opposed to a
- // widget-free QGuiApplication), assume that the widget-based dialog will work.
- if (hasTopLevelWindows && widgetsDir.exists("qmldir") &&
- QCoreApplication::instance()->inherits("QApplication")) {
- QUrl dialogQmlPath = m_useResources ?
- QUrl(QString("qrc:/QtQuick/Dialogs/Widget%1.qml").arg(qmlName)) :
- QUrl::fromLocalFile(qmlDir.filePath(QString("Widget%1.qml").arg(qmlName)));
- if (qmlRegisterType(dialogQmlPath, uri, versionMajor, versionMinor, qmlName) >= 0) {
- needQmlImplementation = false;
-#ifdef DEBUG_REGISTRATION
- qDebug() << " registering" << qmlName << " as " << dialogQmlPath << "success?" << !needQmlImplementation;
-#endif
- }
- }
-#endif
- if (needQmlImplementation) {
- QByteArray abstractTypeName = QByteArray("Abstract") + qmlName;
- qmlRegisterType<WrapperType>(uri, versionMajor, versionMinor, abstractTypeName); // implementation wrapper
- QUrl dialogQmlPath = m_useResources ?
- QUrl(QString("qrc:/QtQuick/Dialogs/Default%1.qml").arg(qmlName)) :
- QUrl::fromLocalFile(qmlDir.filePath(QString("Default%1.qml").arg(qmlName)));
-#ifdef DEBUG_REGISTRATION
- qDebug() << " registering" << qmlName << " as " << dialogQmlPath << "success?" <<
-#endif
- qmlRegisterType(dialogQmlPath, uri, versionMajor, versionMinor, qmlName);
- }
- }
-
- QUrl m_decorationComponentUrl;
- bool m_useResources;
-};
-
-QT_END_NAMESPACE
-
-#include "plugin.moc"
diff --git a/src/imports/dialogs/plugins.qmltypes b/src/imports/dialogs/plugins.qmltypes
deleted file mode 100644
index d5db4b93bd..0000000000
--- a/src/imports/dialogs/plugins.qmltypes
+++ /dev/null
@@ -1,654 +0,0 @@
-import QtQuick.tooling 1.1
-
-// This file describes the plugin-supplied types contained in the library.
-// It is used for QML tooling purposes only.
-//
-// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -omit-prefix=__ QtQuick.Dialogs 1.1'
-
-Module {
- Component {
- name: "QQuickAbstractColorDialog"
- prototype: "QQuickAbstractDialog"
- Property { name: "showAlphaChannel"; type: "bool" }
- Property { name: "color"; type: "QColor" }
- Property { name: "currentColor"; type: "QColor" }
- Property { name: "currentHue"; type: "double"; isReadonly: true }
- Property { name: "currentSaturation"; type: "double"; isReadonly: true }
- Property { name: "currentLightness"; type: "double"; isReadonly: true }
- Property { name: "currentAlpha"; type: "double"; isReadonly: true }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setModality"
- Parameter { name: "m"; type: "Qt::WindowModality" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setColor"
- Parameter { name: "arg"; type: "QColor" }
- }
- Method {
- name: "setCurrentColor"
- Parameter { name: "currentColor"; type: "QColor" }
- }
- Method {
- name: "setShowAlphaChannel"
- Parameter { name: "arg"; type: "bool" }
- }
- }
- Component {
- name: "QQuickAbstractDialog"
- prototype: "QObject"
- Property { name: "visible"; type: "bool" }
- Property { name: "modality"; type: "Qt::WindowModality" }
- Property { name: "title"; type: "string" }
- Property { name: "isWindow"; type: "bool"; isReadonly: true }
- Property { name: "x"; type: "int" }
- Property { name: "y"; type: "int" }
- Property { name: "width"; type: "int" }
- Property { name: "height"; type: "int" }
- Signal { name: "visibilityChanged" }
- Signal { name: "geometryChanged" }
- Signal { name: "accepted" }
- Signal { name: "rejected" }
- Method { name: "open" }
- Method { name: "close" }
- Method {
- name: "setX"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setY"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setWidth"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "arg"; type: "int" }
- }
- }
- Component {
- name: "QQuickAbstractFileDialog"
- prototype: "QQuickAbstractDialog"
- Property { name: "selectExisting"; type: "bool" }
- Property { name: "selectMultiple"; type: "bool" }
- Property { name: "selectFolder"; type: "bool" }
- Property { name: "folder"; type: "QUrl" }
- Property { name: "nameFilters"; type: "QStringList" }
- Property { name: "selectedNameFilter"; type: "string" }
- Property { name: "fileUrl"; type: "QUrl"; isReadonly: true }
- Property { name: "fileUrls"; type: "QList<QUrl>"; isReadonly: true }
- Signal { name: "filterSelected" }
- Signal { name: "fileModeChanged" }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setSelectExisting"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setSelectMultiple"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setSelectFolder"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setFolder"
- Parameter { name: "f"; type: "QUrl" }
- }
- Method {
- name: "setNameFilters"
- Parameter { name: "f"; type: "QStringList" }
- }
- Method {
- name: "selectNameFilter"
- Parameter { name: "f"; type: "string" }
- }
- }
- Component {
- name: "QQuickAbstractFontDialog"
- prototype: "QQuickAbstractDialog"
- Property { name: "scalableFonts"; type: "bool" }
- Property { name: "nonScalableFonts"; type: "bool" }
- Property { name: "monospacedFonts"; type: "bool" }
- Property { name: "proportionalFonts"; type: "bool" }
- Property { name: "font"; type: "QFont" }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setModality"
- Parameter { name: "m"; type: "Qt::WindowModality" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setFont"
- Parameter { name: "arg"; type: "QFont" }
- }
- Method {
- name: "setScalableFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setNonScalableFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setMonospacedFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setProportionalFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- }
- Component {
- name: "QQuickAbstractMessageDialog"
- prototype: "QQuickAbstractDialog"
- Enum {
- name: "Icon"
- values: {
- "NoIcon": 0,
- "Information": 1,
- "Warning": 2,
- "Critical": 3,
- "Question": 4
- }
- }
- Enum {
- name: "StandardButton"
- values: {
- "NoButton": 0,
- "Ok": 1024,
- "Save": 2048,
- "SaveAll": 4096,
- "Open": 8192,
- "Yes": 16384,
- "YesToAll": 32768,
- "No": 65536,
- "NoToAll": 131072,
- "Abort": 262144,
- "Retry": 524288,
- "Ignore": 1048576,
- "Close": 2097152,
- "Cancel": 4194304,
- "Discard": 8388608,
- "Help": 16777216,
- "Apply": 33554432,
- "Reset": 67108864,
- "RestoreDefaults": 134217728
- }
- }
- Enum {
- name: "StandardButtons"
- values: {
- "NoButton": 0,
- "Ok": 1024,
- "Save": 2048,
- "SaveAll": 4096,
- "Open": 8192,
- "Yes": 16384,
- "YesToAll": 32768,
- "No": 65536,
- "NoToAll": 131072,
- "Abort": 262144,
- "Retry": 524288,
- "Ignore": 1048576,
- "Close": 2097152,
- "Cancel": 4194304,
- "Discard": 8388608,
- "Help": 16777216,
- "Apply": 33554432,
- "Reset": 67108864,
- "RestoreDefaults": 134217728
- }
- }
- Property { name: "text"; type: "string" }
- Property { name: "informativeText"; type: "string" }
- Property { name: "detailedText"; type: "string" }
- Property { name: "icon"; type: "Icon" }
- Property { name: "standardIconSource"; type: "QUrl"; isReadonly: true }
- Property { name: "standardButtons"; type: "StandardButtons" }
- Property { name: "clickedButton"; type: "StandardButton"; isReadonly: true }
- Signal { name: "buttonClicked" }
- Signal { name: "discard" }
- Signal { name: "help" }
- Signal { name: "yes" }
- Signal { name: "no" }
- Signal { name: "apply" }
- Signal { name: "reset" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setInformativeText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setDetailedText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setIcon"
- Parameter { name: "icon"; type: "Icon" }
- }
- Method {
- name: "setStandardButtons"
- Parameter { name: "buttons"; type: "StandardButtons" }
- }
- Method {
- name: "click"
- Parameter { name: "button"; type: "QMessageDialogOptions::StandardButton" }
- Parameter { type: "QMessageDialogOptions::ButtonRole" }
- }
- Method {
- name: "click"
- Parameter { name: "button"; type: "QQuickAbstractMessageDialog::StandardButton" }
- }
- }
- Component {
- name: "QQuickColorDialog"
- defaultProperty: "implementation"
- prototype: "QQuickAbstractColorDialog"
- exports: ["QtQuick.Dialogs/AbstractColorDialog 1.0"]
- exportMetaObjectRevisions: [0]
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- }
- Component {
- name: "QQuickFileDialog"
- defaultProperty: "implementation"
- prototype: "QQuickAbstractFileDialog"
- exports: ["QtQuick.Dialogs/AbstractFileDialog 1.0"]
- exportMetaObjectRevisions: [0]
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- Method { name: "clearSelection" }
- Method {
- name: "addSelection"
- type: "bool"
- Parameter { name: "path"; type: "QUrl" }
- }
- }
- Component {
- name: "QQuickFontDialog"
- defaultProperty: "implementation"
- prototype: "QQuickAbstractFontDialog"
- exports: ["QtQuick.Dialogs/AbstractFontDialog 1.1"]
- exportMetaObjectRevisions: [0]
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- }
- Component {
- name: "QQuickMessageDialog"
- defaultProperty: "implementation"
- prototype: "QQuickAbstractMessageDialog"
- exports: ["QtQuick.Dialogs/AbstractMessageDialog 1.1"]
- exportMetaObjectRevisions: [0]
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- }
- Component {
- name: "QQuickStandardButton"
- exports: ["QtQuick.Dialogs/StandardButton 1.1"]
- exportMetaObjectRevisions: [0]
- }
- Component {
- name: "QQuickStandardIcon"
- exports: ["QtQuick.Dialogs/StandardIcon 1.1"]
- exportMetaObjectRevisions: [0]
- }
- Component {
- prototype: "QObject"
- name: "QtQuick.Dialogs/ColorDialog"
- exports: ["QtQuick.Dialogs/ColorDialog 1.0"]
- exportMetaObjectRevisions: [0]
- defaultProperty: "implementation"
- Property { name: "showAlphaChannel"; type: "bool" }
- Property { name: "color"; type: "QColor" }
- Property { name: "currentColor"; type: "QColor" }
- Property { name: "currentHue"; type: "double"; isReadonly: true }
- Property { name: "currentSaturation"; type: "double"; isReadonly: true }
- Property { name: "currentLightness"; type: "double"; isReadonly: true }
- Property { name: "currentAlpha"; type: "double"; isReadonly: true }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setModality"
- Parameter { name: "m"; type: "Qt::WindowModality" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setColor"
- Parameter { name: "arg"; type: "QColor" }
- }
- Method {
- name: "setCurrentColor"
- Parameter { name: "currentColor"; type: "QColor" }
- }
- Method {
- name: "setShowAlphaChannel"
- Parameter { name: "arg"; type: "bool" }
- }
- Property { name: "visible"; type: "bool" }
- Property { name: "modality"; type: "Qt::WindowModality" }
- Property { name: "title"; type: "string" }
- Property { name: "isWindow"; type: "bool"; isReadonly: true }
- Property { name: "x"; type: "int" }
- Property { name: "y"; type: "int" }
- Property { name: "width"; type: "int" }
- Property { name: "height"; type: "int" }
- Signal { name: "visibilityChanged" }
- Signal { name: "geometryChanged" }
- Signal { name: "accepted" }
- Signal { name: "rejected" }
- Method { name: "open" }
- Method { name: "close" }
- Method {
- name: "setX"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setY"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setWidth"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "arg"; type: "int" }
- }
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- }
- Component {
- prototype: "QObject"
- name: "QtQuick.Dialogs/FileDialog"
- exports: ["QtQuick.Dialogs/FileDialog 1.0"]
- exportMetaObjectRevisions: [0]
- defaultProperty: "implementation"
- Property { name: "visible"; type: "bool" }
- Property { name: "modality"; type: "Qt::WindowModality" }
- Property { name: "title"; type: "string" }
- Property { name: "isWindow"; type: "bool"; isReadonly: true }
- Property { name: "x"; type: "int" }
- Property { name: "y"; type: "int" }
- Property { name: "width"; type: "int" }
- Property { name: "height"; type: "int" }
- Signal { name: "visibilityChanged" }
- Signal { name: "geometryChanged" }
- Signal { name: "accepted" }
- Signal { name: "rejected" }
- Method { name: "open" }
- Method { name: "close" }
- Method {
- name: "setX"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setY"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setWidth"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "arg"; type: "int" }
- }
- Property { name: "selectExisting"; type: "bool" }
- Property { name: "selectMultiple"; type: "bool" }
- Property { name: "selectFolder"; type: "bool" }
- Property { name: "folder"; type: "QUrl" }
- Property { name: "nameFilters"; type: "QStringList" }
- Property { name: "selectedNameFilter"; type: "string" }
- Property { name: "fileUrl"; type: "QUrl"; isReadonly: true }
- Property { name: "fileUrls"; type: "QList<QUrl>"; isReadonly: true }
- Signal { name: "filterSelected" }
- Signal { name: "fileModeChanged" }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setSelectExisting"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setSelectMultiple"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setSelectFolder"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setFolder"
- Parameter { name: "f"; type: "QUrl" }
- }
- Method {
- name: "setNameFilters"
- Parameter { name: "f"; type: "QStringList" }
- }
- Method {
- name: "selectNameFilter"
- Parameter { name: "f"; type: "string" }
- }
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- Method { name: "clearSelection" }
- Method {
- name: "addSelection"
- type: "bool"
- Parameter { name: "path"; type: "QUrl" }
- }
- }
- Component {
- prototype: "QObject"
- name: "QtQuick.Dialogs/FontDialog"
- exports: ["QtQuick.Dialogs/FontDialog 1.1"]
- exportMetaObjectRevisions: [1]
- defaultProperty: "implementation"
- Property { name: "font"; type: "QFont" }
- Property { name: "visible"; type: "bool" }
- Property { name: "modality"; type: "Qt::WindowModality" }
- Property { name: "title"; type: "string" }
- Property { name: "isWindow"; type: "bool"; isReadonly: true }
- Property { name: "x"; type: "int" }
- Property { name: "y"; type: "int" }
- Property { name: "width"; type: "int" }
- Property { name: "height"; type: "int" }
- Signal { name: "visibilityChanged" }
- Signal { name: "geometryChanged" }
- Signal { name: "accepted" }
- Signal { name: "rejected" }
- Method { name: "open" }
- Method { name: "close" }
- Method {
- name: "setX"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setY"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setWidth"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "arg"; type: "int" }
- }
- Property { name: "scalableFonts"; type: "bool" }
- Property { name: "nonScalableFonts"; type: "bool" }
- Property { name: "monospacedFonts"; type: "bool" }
- Property { name: "proportionalFonts"; type: "bool" }
- Property { name: "font"; type: "QFont" }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setModality"
- Parameter { name: "m"; type: "Qt::WindowModality" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setFont"
- Parameter { name: "arg"; type: "QFont" }
- }
- Method {
- name: "setScalableFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setNonScalableFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setMonospacedFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setProportionalFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- }
- Component {
- prototype: "QObject"
- name: "QtQuick.Dialogs/MessageDialog"
- exports: ["QtQuick.Dialogs/MessageDialog 1.1"]
- exportMetaObjectRevisions: [1]
- defaultProperty: "implementation"
- Method { name: "calculateImplicitWidth"; type: "QVariant" }
- Property { name: "visible"; type: "bool" }
- Property { name: "modality"; type: "Qt::WindowModality" }
- Property { name: "title"; type: "string" }
- Property { name: "isWindow"; type: "bool"; isReadonly: true }
- Property { name: "x"; type: "int" }
- Property { name: "y"; type: "int" }
- Property { name: "width"; type: "int" }
- Property { name: "height"; type: "int" }
- Signal { name: "visibilityChanged" }
- Signal { name: "geometryChanged" }
- Signal { name: "accepted" }
- Signal { name: "rejected" }
- Method { name: "open" }
- Method { name: "close" }
- Method {
- name: "setX"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setY"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setWidth"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "arg"; type: "int" }
- }
- Property { name: "text"; type: "string" }
- Property { name: "informativeText"; type: "string" }
- Property { name: "detailedText"; type: "string" }
- Property { name: "icon"; type: "Icon" }
- Property { name: "standardIconSource"; type: "QUrl"; isReadonly: true }
- Property { name: "standardButtons"; type: "StandardButtons" }
- Property { name: "clickedButton"; type: "StandardButton"; isReadonly: true }
- Signal { name: "buttonClicked" }
- Signal { name: "discard" }
- Signal { name: "help" }
- Signal { name: "yes" }
- Signal { name: "no" }
- Signal { name: "apply" }
- Signal { name: "reset" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setInformativeText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setDetailedText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setIcon"
- Parameter { name: "icon"; type: "Icon" }
- }
- Method {
- name: "setStandardButtons"
- Parameter { name: "buttons"; type: "StandardButtons" }
- }
- Method {
- name: "click"
- Parameter { name: "button"; type: "QMessageDialogOptions::StandardButton" }
- Parameter { type: "QMessageDialogOptions::ButtonRole" }
- }
- Method {
- name: "click"
- Parameter { name: "button"; type: "QQuickAbstractMessageDialog::StandardButton" }
- }
- Property { name: "implementation"; type: "QObject"; isPointer: true }
- }
-}
diff --git a/src/imports/dialogs/qml/Button.qml b/src/imports/dialogs/qml/Button.qml
deleted file mode 100644
index f48264d5ff..0000000000
--- a/src/imports/dialogs/qml/Button.qml
+++ /dev/null
@@ -1,86 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Window 2.1
-
-Item {
- id: container
-
- property alias text: buttonLabel.text
- property alias label: buttonLabel
- signal clicked
- property alias containsMouse: mouseArea.containsMouse
- property alias pressed: mouseArea.pressed
- implicitHeight: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2)
- implicitWidth: visible ? Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3) : 0
- height: implicitHeight
- width: implicitWidth
-
- SystemPalette { id: palette }
-
- Rectangle {
- id: frame
- anchors.fill: parent
- color: palette.button
- gradient: Gradient {
- GradientStop { position: 0.0; color: mouseArea.pressed ? Qt.darker(palette.button, 1.3) : palette.button }
- GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) }
- }
- antialiasing: true
- radius: height / 6
- border.color: Qt.darker(palette.button, 1.5)
- border.width: 1
- }
-
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked: container.clicked()
- hoverEnabled: true
- }
-
- Text {
- id: buttonLabel
- text: container.text
- color: palette.buttonText
- anchors.centerIn: parent
- }
-}
diff --git a/src/imports/dialogs/qml/CheckBox.qml b/src/imports/dialogs/qml/CheckBox.qml
deleted file mode 100644
index 32b0e6ff70..0000000000
--- a/src/imports/dialogs/qml/CheckBox.qml
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-****************************************************************************/
-
-import QtQuick 2.1
-
-Item {
- id: root
- implicitHeight: frame.height
- implicitWidth: row.implicitWidth
- width: implicitWidth
- height: implicitHeight
- property alias text: label.text
- property bool checked
- property alias pressed: mouseArea.pressed
- signal clicked
-
- SystemPalette { id: palette }
-
- Row {
- id: row
- anchors.verticalCenter: parent.verticalCenter
- spacing: 6
- Rectangle {
- id: frame
- gradient: Gradient {
- GradientStop { position: 0.0; color: mouseArea.pressed ? Qt.darker(palette.button, 1.3) : palette.button }
- GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) }
- }
- height: label.implicitHeight * 1.5
- width: height
- anchors.margins: 1
- radius: 3
- antialiasing: true
- border.color: Qt.darker(palette.button, 1.5)
- Image {
- id: theX
- source: "../images/checkmark.png"
- anchors.fill: frame
- anchors.margins: frame.width / 5
- fillMode: Image.PreserveAspectFit
- smooth: true
- visible: checked
- }
- }
- Text {
- id: label
- color: palette.text
- anchors.verticalCenter: frame.verticalCenter
- }
- }
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked: {
- parent.checked = !parent.checked
- parent.clicked()
- }
- }
-}
diff --git a/src/imports/dialogs/qml/ColorSlider.qml b/src/imports/dialogs/qml/ColorSlider.qml
deleted file mode 100755
index 8fc9717380..0000000000
--- a/src/imports/dialogs/qml/ColorSlider.qml
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Graphical Effects module.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-****************************************************************************/
-
-import QtQuick 2.1
-
-Item {
- id: colorSlider
-
- property real value: 1
- property real maximum: 1
- property real minimum: 0
- property string text: ""
- property bool pressed: mouseArea.pressed
- property bool integer: false
- property Component trackDelegate
- property string handleSource: "../images/slider_handle.png"
-
- width: parent.width
- height: handle.height + textText.implicitHeight
-
- function updatePos() {
- if (maximum > minimum) {
- var pos = (track.width - 10) * (value - minimum) / (maximum - minimum) + 5;
- return Math.min(Math.max(pos, 5), track.width - 5) - 10;
- } else {
- return 5;
- }
- }
-
- SystemPalette { id: palette }
-
- Column {
- id: column
- width: parent.width
- spacing: 12
- Text {
- id: textText
- anchors.horizontalCenter: parent.horizontalCenter
- text: colorSlider.text
- anchors.left: parent.left
- color: palette.windowText
- }
-
- Item {
- id: track
- height: 8
- anchors.left: parent.left
- anchors.right: parent.right
-
- Loader {
- sourceComponent: trackDelegate
- width: parent.height
- height: parent.width
- y: width
- }
-
- BorderImage {
- source: "../images/sunken_frame.png"
- border.left: 8
- border.right: 8
- border.top:8
- border.bottom: 8
- anchors.fill: track
- anchors.margins: -1
- anchors.topMargin: -2
- anchors.leftMargin: -2
- }
-
- Image {
- id: handle
- anchors.verticalCenter: parent.verticalCenter
- smooth: true
- source: "../images/slider_handle.png"
- x: updatePos() - 8
- z: 1
- }
-
- MouseArea {
- id: mouseArea
- anchors {left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter}
- height: handle.height
- width: handle.width
- preventStealing: true
-
- onPressed: {
- var handleX = Math.max(0, Math.min(mouseX, mouseArea.width))
- var realValue = (maximum - minimum) * handleX / mouseArea.width + minimum;
- value = colorSlider.integer ? Math.round(realValue) : realValue;
- }
-
- onPositionChanged: {
- if (pressed) {
- var handleX = Math.max(0, Math.min(mouseX, mouseArea.width))
- var realValue = (maximum - minimum) * handleX / mouseArea.width + minimum;
- value = colorSlider.integer ? Math.round(realValue) : realValue;
- }
- }
- }
- }
- }
-}
diff --git a/src/imports/dialogs/qml/EdgeFade.qml b/src/imports/dialogs/qml/EdgeFade.qml
deleted file mode 100644
index 376aa151e6..0000000000
--- a/src/imports/dialogs/qml/EdgeFade.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-
-ShaderEffect {
- property color fadeColor
- property real topThreshold: 10
- property real bottomThreshold: 10
- property real _topRatio: topThreshold / height
- property real _bottomRatio: bottomThreshold / height
- z: 1
- fragmentShader: "
- varying lowp vec2 qt_TexCoord0;
- uniform lowp vec4 fadeColor;
- uniform highp float _topRatio;
- uniform highp float _bottomRatio;
-
- void main() {
- highp float bottomEnd = 1. - _bottomRatio;
- gl_FragColor = fadeColor *
- (qt_TexCoord0.y < _topRatio ? 1. - qt_TexCoord0.y / _topRatio :
- (qt_TexCoord0.y > bottomEnd ? (qt_TexCoord0.y - bottomEnd) / _bottomRatio : 0.));
- }
- "
-}
diff --git a/src/imports/dialogs/qml/TextField.qml b/src/imports/dialogs/qml/TextField.qml
deleted file mode 100644
index e67155086c..0000000000
--- a/src/imports/dialogs/qml/TextField.qml
+++ /dev/null
@@ -1,89 +0,0 @@
-/*****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 Digia Plc and its Subsidiary(-ies) 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$
-**
-*****************************************************************************/
-
-import QtQuick 2.1
-
-Item {
- id: root
-
- property alias textInput: textInput
- property alias text: textInput.text
- signal accepted
- signal downPressed
- signal backPressed
- signal escapePressed
- implicitWidth: textInput.implicitWidth + rect.radius * 2
- implicitHeight: textInput.implicitHeight
-
- function copyAll() {
- textInput.selectAll()
- textInput.copy()
- }
-
- function paste() {
- textInput.selectAll()
- textInput.paste()
- }
-
- SystemPalette { id: palette }
- height: textInput.implicitHeight + 8
- clip: true
-
- Rectangle {
- id: rect
- anchors.fill: parent
- radius: height / 4
- color: palette.button
- border.color: Qt.darker(palette.button, 1.5)
- }
-
- TextInput {
- id: textInput
- color: palette.text
- anchors.fill: parent
- anchors.leftMargin: rect.radius
- anchors.rightMargin: rect.radius
- verticalAlignment: Text.AlignVCenter
- onAccepted: root.accepted()
- Keys.onDownPressed: root.downPressed()
- Keys.onBackPressed: root.backPressed()
- Keys.onEscapePressed: root.escapePressed()
- }
-}
diff --git a/src/imports/dialogs/qml/qmldir b/src/imports/dialogs/qml/qmldir
deleted file mode 100644
index 9d273b1c4b..0000000000
--- a/src/imports/dialogs/qml/qmldir
+++ /dev/null
@@ -1,5 +0,0 @@
-Button 1.0 Button.qml
-CheckBox 1.1 CheckBox.qml
-ColorSlider 1.0 ColorSlider.qml
-EdgeFade 1.0 EdgeFade.qml
-TextField 1.0 TextField.qml
diff --git a/src/imports/dialogs/qmldir b/src/imports/dialogs/qmldir
deleted file mode 100644
index b4ae1a059c..0000000000
--- a/src/imports/dialogs/qmldir
+++ /dev/null
@@ -1,4 +0,0 @@
-module QtQuick.Dialogs
-plugin dialogplugin
-classname QtQuick2DialogsPlugin
-typeinfo plugins.qmltypes
diff --git a/src/imports/dialogs/qquickabstractcolordialog.cpp b/src/imports/dialogs/qquickabstractcolordialog.cpp
deleted file mode 100644
index 1931bde905..0000000000
--- a/src/imports/dialogs/qquickabstractcolordialog.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickabstractcolordialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-QQuickAbstractColorDialog::QQuickAbstractColorDialog(QObject *parent)
- : QQuickAbstractDialog(parent)
- , m_dlgHelper(0)
- , m_options(QSharedPointer<QColorDialogOptions>(new QColorDialogOptions()))
-{
- // On the Mac, modality doesn't work unless you call exec(). But this is a reasonable default anyway.
- m_modality = Qt::NonModal;
- connect(this, SIGNAL(accepted()), this, SIGNAL(selectionAccepted()));
-}
-
-QQuickAbstractColorDialog::~QQuickAbstractColorDialog()
-{
-}
-
-void QQuickAbstractColorDialog::setVisible(bool v)
-{
- if (helper() && v) {
- m_dlgHelper->setOptions(m_options);
- // Due to the fact that QColorDialogOptions doesn't have currentColor...
- m_dlgHelper->setCurrentColor(m_color);
- }
- QQuickAbstractDialog::setVisible(v);
- // QTBUG-35206
-#if defined(Q_OS_WIN)
- if (m_dialogWindow)
- m_dialogWindow->setWidth(m_dialogWindow->width() + 1);
-#endif
-}
-
-void QQuickAbstractColorDialog::setModality(Qt::WindowModality m)
-{
-#ifdef Q_OS_MAC
- // On the Mac, modality doesn't work unless you call exec()
- m_modality = Qt::NonModal;
- emit modalityChanged();
- return;
-#endif
- QQuickAbstractDialog::setModality(m);
-}
-
-QString QQuickAbstractColorDialog::title() const
-{
- return m_options->windowTitle();
-}
-
-bool QQuickAbstractColorDialog::showAlphaChannel() const
-{
- return m_options->testOption(QColorDialogOptions::ShowAlphaChannel);
-}
-
-void QQuickAbstractColorDialog::setTitle(const QString &t)
-{
- if (m_options->windowTitle() == t) return;
- m_options->setWindowTitle(t);
- emit titleChanged();
-}
-
-void QQuickAbstractColorDialog::setColor(QColor arg)
-{
- if (m_dlgHelper)
- m_dlgHelper->setCurrentColor(arg);
- // m_options->setCustomColor or setStandardColor don't make sense here
- if (m_color != arg) {
- m_color = arg;
- emit colorChanged();
- }
- setCurrentColor(arg);
-}
-
-void QQuickAbstractColorDialog::setCurrentColor(QColor currentColor)
-{
- if (m_currentColor != currentColor) {
- m_currentColor = currentColor;
- emit currentColorChanged();
- }
-}
-
-void QQuickAbstractColorDialog::setShowAlphaChannel(bool arg)
-{
- m_options->setOption(QColorDialogOptions::ShowAlphaChannel, arg);
- emit showAlphaChannelChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickabstractcolordialog_p.h b/src/imports/dialogs/qquickabstractcolordialog_p.h
deleted file mode 100644
index ad2c7ce1ed..0000000000
--- a/src/imports/dialogs/qquickabstractcolordialog_p.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKABSTRACTCOLORDIALOG_P_H
-#define QQUICKABSTRACTCOLORDIALOG_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>
-#include <QQuickView>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include <qpa/qplatformtheme.h>
-#include "qquickabstractdialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQuickAbstractColorDialog : public QQuickAbstractDialog
-{
- Q_OBJECT
- Q_PROPERTY(bool showAlphaChannel READ showAlphaChannel WRITE setShowAlphaChannel NOTIFY showAlphaChannelChanged)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QColor currentColor READ currentColor WRITE setCurrentColor NOTIFY currentColorChanged)
- Q_PROPERTY(qreal currentHue READ currentHue NOTIFY currentColorChanged)
- Q_PROPERTY(qreal currentSaturation READ currentSaturation NOTIFY currentColorChanged)
- Q_PROPERTY(qreal currentLightness READ currentLightness NOTIFY currentColorChanged)
- Q_PROPERTY(qreal currentAlpha READ currentAlpha NOTIFY currentColorChanged)
-
-public:
- QQuickAbstractColorDialog(QObject *parent = 0);
- virtual ~QQuickAbstractColorDialog();
-
- virtual QString title() const;
- bool showAlphaChannel() const;
- QColor color() const { return m_color; }
- QColor currentColor() const { return m_currentColor; }
- qreal currentHue() const { return m_currentColor.hslHueF(); }
- qreal currentSaturation() const { return m_currentColor.hslSaturationF(); }
- qreal currentLightness() const { return m_currentColor.lightnessF(); }
- qreal currentAlpha() const { return m_currentColor.alphaF(); }
-
-public Q_SLOTS:
- void setVisible(bool v);
- void setModality(Qt::WindowModality m);
- void setTitle(const QString &t);
- void setColor(QColor arg);
- void setCurrentColor(QColor currentColor);
- void setShowAlphaChannel(bool arg);
-
-Q_SIGNALS:
- void showAlphaChannelChanged();
- void colorChanged();
- void currentColorChanged();
- void selectionAccepted();
-
-protected:
- QPlatformColorDialogHelper *m_dlgHelper;
- QSharedPointer<QColorDialogOptions> m_options;
- QColor m_color;
- QColor m_currentColor;
-
- Q_DISABLE_COPY(QQuickAbstractColorDialog)
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKABSTRACTCOLORDIALOG_P_H
diff --git a/src/imports/dialogs/qquickabstractdialog.cpp b/src/imports/dialogs/qquickabstractdialog.cpp
deleted file mode 100644
index 9bb2388741..0000000000
--- a/src/imports/dialogs/qquickabstractdialog.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickabstractdialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQmlComponent>
-#include <QQuickWindow>
-#include <qpa/qplatformintegration.h>
-
-QT_BEGIN_NAMESPACE
-
-QQmlComponent *QQuickAbstractDialog::m_decorationComponent(0);
-
-QQuickAbstractDialog::QQuickAbstractDialog(QObject *parent)
- : QObject(parent)
- , m_parentWindow(0)
- , m_visible(false)
- , m_modality(Qt::WindowModal)
- , m_qmlImplementation(0)
- , m_dialogWindow(0)
- , m_contentItem(0)
- , m_windowDecoration(0)
- , m_hasNativeWindows(QGuiApplicationPrivate::platformIntegration()->
- hasCapability(QPlatformIntegration::MultipleWindows) &&
- QGuiApplicationPrivate::platformIntegration()->
- hasCapability(QPlatformIntegration::WindowManagement))
- , m_hasAspiredPosition(false)
-{
-}
-
-QQuickAbstractDialog::~QQuickAbstractDialog()
-{
-}
-
-void QQuickAbstractDialog::setVisible(bool v)
-{
- if (m_visible == v) return;
- m_visible = v;
- if (helper()) {
- if (v) {
- Qt::WindowFlags flags = Qt::Dialog;
- if (!title().isEmpty())
- flags |= Qt::WindowTitleHint;
- m_visible = helper()->show(flags, m_modality, parentWindow());
- } else {
- helper()->hide();
- }
- } else {
- // For a pure QML implementation, there is no helper.
- // But m_implementation is probably either an Item or a Window at this point.
- if (!m_dialogWindow) {
- m_dialogWindow = qobject_cast<QWindow *>(m_qmlImplementation);
- if (!m_dialogWindow) {
- m_contentItem = qobject_cast<QQuickItem *>(m_qmlImplementation);
- if (m_contentItem) {
- if (m_hasNativeWindows)
- m_dialogWindow = m_contentItem->window();
- // An Item-based dialog implementation doesn't come with a window, so
- // we have to instantiate one iff the platform allows it.
- if (!m_dialogWindow && m_hasNativeWindows) {
- QQuickWindow *win = new QQuickWindow;
- ((QObject *)win)->setParent(this); // memory management only
- m_dialogWindow = win;
- m_contentItem->setParentItem(win->contentItem());
- m_dialogWindow->setMinimumSize(QSize(m_contentItem->implicitWidth(), m_contentItem->implicitHeight()));
- connect(win, SIGNAL(widthChanged(int)), this, SLOT(windowGeometryChanged()));
- connect(win, SIGNAL(heightChanged(int)), this, SLOT(windowGeometryChanged()));
- }
-
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
-
- // If the platform does not support multiple windows, but the dialog is
- // implemented as an Item, then try to decorate it as a fake window and make it visible.
- if (parentItem && !m_dialogWindow && !m_windowDecoration) {
- if (m_decorationComponent) {
- if (m_decorationComponent->isLoading())
- connect(m_decorationComponent, SIGNAL(statusChanged(QQmlComponent::Status)),
- this, SLOT(decorationLoaded()));
- else
- decorationLoaded();
- }
- // Window decoration wasn't possible, so just reparent it into the scene
- else {
- m_contentItem->setParentItem(parentItem);
- m_contentItem->setZ(10000);
- }
- }
- }
- }
- if (m_dialogWindow) {
- // "grow up" to the size and position expected to achieve
- if (!m_sizeAspiration.isNull()) {
- if (m_hasAspiredPosition)
- m_dialogWindow->setGeometry(m_sizeAspiration);
- else {
- if (m_sizeAspiration.width() > 0)
- m_dialogWindow->setWidth(m_sizeAspiration.width());
- if (m_sizeAspiration.height() > 0)
- m_dialogWindow->setHeight(m_sizeAspiration.height());
- }
- }
- connect(m_dialogWindow, SIGNAL(visibleChanged(bool)), this, SLOT(visibleChanged(bool)));
- connect(m_dialogWindow, SIGNAL(xChanged(int)), this, SLOT(setX(int)));
- connect(m_dialogWindow, SIGNAL(yChanged(int)), this, SLOT(setY(int)));
- connect(m_dialogWindow, SIGNAL(widthChanged(int)), this, SLOT(setWidth(int)));
- connect(m_dialogWindow, SIGNAL(heightChanged(int)), this, SLOT(setHeight(int)));
- }
- }
- if (m_windowDecoration) {
- m_windowDecoration->setVisible(v);
- } else if (m_dialogWindow) {
- if (v) {
- m_dialogWindow->setTransientParent(parentWindow());
- m_dialogWindow->setTitle(title());
- m_dialogWindow->setModality(m_modality);
- }
- m_dialogWindow->setVisible(v);
- }
- }
-
- emit visibilityChanged();
-}
-
-void QQuickAbstractDialog::decorationLoaded()
-{
- bool ok = false;
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- while (parentItem->parentItem() && !parentItem->parentItem()->inherits("QQuickRootItem"))
- parentItem = parentItem->parentItem();
- if (m_decorationComponent->isError()) {
- qWarning() << m_decorationComponent->errors();
- } else {
- QObject *decoration = m_decorationComponent->create();
- m_windowDecoration = qobject_cast<QQuickItem *>(decoration);
- if (m_windowDecoration) {
- m_windowDecoration->setParentItem(parentItem);
- // Give the window decoration its content to manage
- QVariant contentVariant;
- contentVariant.setValue<QQuickItem*>(m_contentItem);
- m_windowDecoration->setProperty("content", contentVariant);
- connect(m_windowDecoration, SIGNAL(dismissed()), this, SLOT(reject()));
- ok = true;
- } else {
- qWarning() << m_decorationComponent->url() <<
- "cannot be used as a window decoration because it's not an Item";
- delete m_windowDecoration;
- delete m_decorationComponent;
- m_decorationComponent = 0;
- }
- }
- // Window decoration wasn't possible, so just reparent it into the scene
- if (!ok) {
- m_contentItem->setParentItem(parentItem);
- m_contentItem->setZ(10000);
- }
-}
-
-void QQuickAbstractDialog::setModality(Qt::WindowModality m)
-{
- if (m_modality == m) return;
- m_modality = m;
- emit modalityChanged();
-}
-
-void QQuickAbstractDialog::accept()
-{
- setVisible(false);
- emit accepted();
-}
-
-void QQuickAbstractDialog::reject()
-{
- setVisible(false);
- emit rejected();
-}
-
-void QQuickAbstractDialog::visibleChanged(bool v)
-{
- m_visible = v;
- emit visibilityChanged();
-}
-
-void QQuickAbstractDialog::windowGeometryChanged()
-{
- QQuickItem *content = qobject_cast<QQuickItem*>(m_qmlImplementation);
- if (m_dialogWindow && content) {
- content->setWidth(m_dialogWindow->width());
- content->setHeight(m_dialogWindow->height());
- }
-}
-
-QQuickWindow *QQuickAbstractDialog::parentWindow()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
- return m_parentWindow;
-}
-
-void QQuickAbstractDialog::setQmlImplementation(QObject *obj)
-{
- m_qmlImplementation = obj;
- if (m_dialogWindow) {
- disconnect(this, SLOT(visibleChanged(bool)));
- // Can't necessarily delete because m_dialogWindow might have been provided by the QML.
- m_dialogWindow = 0;
- }
-}
-
-int QQuickAbstractDialog::x() const
-{
- if (m_dialogWindow)
- return m_dialogWindow->x();
- return m_sizeAspiration.x();
-}
-
-int QQuickAbstractDialog::y() const
-{
- if (m_dialogWindow)
- return m_dialogWindow->y();
- return m_sizeAspiration.y();
-}
-
-int QQuickAbstractDialog::width() const
-{
- if (m_dialogWindow)
- return m_dialogWindow->width();
- return m_sizeAspiration.width();
-}
-
-int QQuickAbstractDialog::height() const
-{
- if (m_dialogWindow)
- return m_dialogWindow->height();
- return m_sizeAspiration.height();
-}
-
-void QQuickAbstractDialog::setX(int arg)
-{
- m_hasAspiredPosition = true;
- m_sizeAspiration.setX(arg);
- if (helper()) {
- // TODO
- } else if (m_dialogWindow) {
- if (sender() != m_dialogWindow)
- m_dialogWindow->setX(arg);
- } else if (m_contentItem) {
- m_contentItem->setX(arg);
- }
- emit geometryChanged();
-}
-
-void QQuickAbstractDialog::setY(int arg)
-{
- m_hasAspiredPosition = true;
- m_sizeAspiration.setY(arg);
- if (helper()) {
- // TODO
- } else if (m_dialogWindow) {
- if (sender() != m_dialogWindow)
- m_dialogWindow->setY(arg);
- } else if (m_contentItem) {
- m_contentItem->setY(arg);
- }
- emit geometryChanged();
-}
-
-void QQuickAbstractDialog::setWidth(int arg)
-{
- m_sizeAspiration.setWidth(arg);
- if (helper()) {
- // TODO
- } else if (m_dialogWindow) {
- if (sender() != m_dialogWindow)
- m_dialogWindow->setWidth(arg);
- } else if (m_contentItem) {
- m_contentItem->setWidth(arg);
- }
- emit geometryChanged();
-}
-
-void QQuickAbstractDialog::setHeight(int arg)
-{
- m_sizeAspiration.setHeight(arg);
- if (helper()) {
- // TODO
- } else if (m_dialogWindow) {
- if (sender() != m_dialogWindow)
- m_dialogWindow->setHeight(arg);
- } else if (m_contentItem) {
- m_contentItem->setHeight(arg);
- }
- emit geometryChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickabstractdialog_p.h b/src/imports/dialogs/qquickabstractdialog_p.h
deleted file mode 100644
index 8ffa166c5b..0000000000
--- a/src/imports/dialogs/qquickabstractdialog_p.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKABSTRACTDIALOG_P_H
-#define QQUICKABSTRACTDIALOG_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>
-#include <QQuickView>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include <qpa/qplatformtheme.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickAbstractDialog : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged)
- Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged)
- Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
- Q_PROPERTY(bool isWindow READ isWindow CONSTANT)
- Q_PROPERTY(int x READ x WRITE setX NOTIFY geometryChanged)
- Q_PROPERTY(int y READ y WRITE setY NOTIFY geometryChanged)
- Q_PROPERTY(int width READ width WRITE setWidth NOTIFY geometryChanged)
- Q_PROPERTY(int height READ height WRITE setHeight NOTIFY geometryChanged)
-
-public:
- QQuickAbstractDialog(QObject *parent = 0);
- virtual ~QQuickAbstractDialog();
-
- bool isVisible() const { return m_visible; }
- Qt::WindowModality modality() const { return m_modality; }
- virtual QString title() const = 0;
- QObject* qmlImplementation() { return m_qmlImplementation; }
-
- int x() const;
- int y() const;
- int width() const;
- int height() const;
-
- virtual void setVisible(bool v);
- virtual void setModality(Qt::WindowModality m);
- virtual void setTitle(const QString &t) = 0;
- void setQmlImplementation(QObject* obj);
- bool isWindow() const { return m_hasNativeWindows; }
-
-public Q_SLOTS:
- void open() { setVisible(true); }
- void close() { setVisible(false); }
- void setX(int arg);
- void setY(int arg);
- void setWidth(int arg);
- void setHeight(int arg);
-
-Q_SIGNALS:
- void visibilityChanged();
- void geometryChanged();
- void modalityChanged();
- void titleChanged();
- void accepted();
- void rejected();
-
-protected Q_SLOTS:
- void decorationLoaded();
- virtual void accept();
- virtual void reject();
- void visibleChanged(bool v);
- void windowGeometryChanged();
-
-protected:
- virtual QPlatformDialogHelper *helper() = 0;
- QQuickWindow *parentWindow();
-
-protected:
- QQuickWindow *m_parentWindow;
- bool m_visible;
- Qt::WindowModality m_modality;
-
-protected: // variables for pure-QML implementations only
- QObject *m_qmlImplementation;
- QWindow *m_dialogWindow;
- QQuickItem *m_contentItem;
- QQuickItem *m_windowDecoration;
- bool m_hasNativeWindows;
- QRect m_sizeAspiration;
- bool m_hasAspiredPosition;
-
- static QQmlComponent *m_decorationComponent;
-
- friend class QtQuick2DialogsPlugin;
-
- Q_DISABLE_COPY(QQuickAbstractDialog)
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKABSTRACTDIALOG_P_H
diff --git a/src/imports/dialogs/qquickabstractfiledialog.cpp b/src/imports/dialogs/qquickabstractfiledialog.cpp
deleted file mode 100644
index 0cac801311..0000000000
--- a/src/imports/dialogs/qquickabstractfiledialog.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickabstractfiledialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-QQuickAbstractFileDialog::QQuickAbstractFileDialog(QObject *parent)
- : QQuickAbstractDialog(parent)
- , m_dlgHelper(0)
- , m_options(QSharedPointer<QFileDialogOptions>(new QFileDialogOptions()))
- , m_selectExisting(true)
- , m_selectMultiple(false)
- , m_selectFolder(false)
-{
- updateModes();
- connect(this, SIGNAL(accepted()), this, SIGNAL(selectionAccepted()));
-}
-
-QQuickAbstractFileDialog::~QQuickAbstractFileDialog()
-{
-}
-
-void QQuickAbstractFileDialog::setVisible(bool v)
-{
- if (helper() && v) {
- m_dlgHelper->setOptions(m_options);
- m_dlgHelper->setFilter();
- emit filterSelected();
- }
- QQuickAbstractDialog::setVisible(v);
-}
-
-QString QQuickAbstractFileDialog::title() const
-{
- return m_options->windowTitle();
-}
-
-void QQuickAbstractFileDialog::setTitle(const QString &t)
-{
- if (m_options->windowTitle() == t) return;
- m_options->setWindowTitle(t);
- emit titleChanged();
-}
-
-void QQuickAbstractFileDialog::setSelectExisting(bool selectExisting)
-{
- if (selectExisting == m_selectExisting) return;
- m_selectExisting = selectExisting;
- updateModes();
-}
-
-void QQuickAbstractFileDialog::setSelectMultiple(bool selectMultiple)
-{
- if (selectMultiple == m_selectMultiple) return;
- m_selectMultiple = selectMultiple;
- updateModes();
-}
-
-void QQuickAbstractFileDialog::setSelectFolder(bool selectFolder)
-{
- if (selectFolder == m_selectFolder) return;
- m_selectFolder = selectFolder;
- updateModes();
-}
-
-QUrl QQuickAbstractFileDialog::folder()
-{
- if (m_dlgHelper && !m_dlgHelper->directory().isEmpty())
- return m_dlgHelper->directory();
- return m_options->initialDirectory();
-}
-
-void QQuickAbstractFileDialog::setFolder(const QUrl &f)
-{
- if (m_dlgHelper)
- m_dlgHelper->setDirectory(f);
- m_options->setInitialDirectory(f);
- emit folderChanged();
-}
-
-void QQuickAbstractFileDialog::setNameFilters(const QStringList &f)
-{
- m_options->setNameFilters(f);
- if (f.isEmpty())
- selectNameFilter(QString());
- else if (!f.contains(selectedNameFilter()))
- selectNameFilter(f.first());
- emit nameFiltersChanged();
-}
-
-QString QQuickAbstractFileDialog::selectedNameFilter()
-{
- QString ret;
- if (m_dlgHelper)
- ret = m_dlgHelper->selectedNameFilter();
- if (ret.isEmpty())
- return m_options->initiallySelectedNameFilter();
- return ret;
-}
-
-void QQuickAbstractFileDialog::selectNameFilter(const QString &f)
-{
- // This should work whether the dialog is currently being shown already, or ahead of time.
- m_options->setInitiallySelectedNameFilter(f);
- if (m_dlgHelper)
- m_dlgHelper->selectNameFilter(f);
- emit filterSelected();
-}
-
-QUrl QQuickAbstractFileDialog::fileUrl()
-{
- QList<QUrl> urls = fileUrls();
- return (urls.count() == 1) ? urls[0] : QUrl();
-}
-
-QList<QUrl> QQuickAbstractFileDialog::fileUrls()
-{
- if (m_dlgHelper)
- return m_dlgHelper->selectedFiles();
- return QList<QUrl>();
-}
-
-void QQuickAbstractFileDialog::updateModes()
-{
- // The 4 possible modes are AnyFile, ExistingFile, Directory, ExistingFiles
- // Assume AnyFile until we find a reason to the contrary
- QFileDialogOptions::FileMode mode = QFileDialogOptions::AnyFile;
-
- if (m_selectFolder) {
- mode = QFileDialogOptions::Directory;
- m_options->setOption(QFileDialogOptions::ShowDirsOnly);
- m_selectMultiple = false;
- m_selectExisting = true;
- setNameFilters(QStringList());
- } else if (m_selectExisting) {
- mode = m_selectMultiple ?
- QFileDialogOptions::ExistingFiles : QFileDialogOptions::ExistingFile;
- m_options->setOption(QFileDialogOptions::ShowDirsOnly, false);
- } else if (m_selectMultiple) {
- m_selectExisting = true;
- }
- if (!m_selectExisting)
- m_selectMultiple = false;
- m_options->setFileMode(mode);
- m_options->setAcceptMode(m_selectExisting ?
- QFileDialogOptions::AcceptOpen : QFileDialogOptions::AcceptSave);
- emit fileModeChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickabstractfiledialog_p.h b/src/imports/dialogs/qquickabstractfiledialog_p.h
deleted file mode 100644
index 5ce48e8055..0000000000
--- a/src/imports/dialogs/qquickabstractfiledialog_p.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKABSTRACTFILEDIALOG_P_H
-#define QQUICKABSTRACTFILEDIALOG_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>
-#include <QQuickView>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include <qpa/qplatformtheme.h>
-#include "qquickabstractdialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQuickAbstractFileDialog : public QQuickAbstractDialog
-{
- Q_OBJECT
- Q_PROPERTY(bool selectExisting READ selectExisting WRITE setSelectExisting NOTIFY fileModeChanged)
- Q_PROPERTY(bool selectMultiple READ selectMultiple WRITE setSelectMultiple NOTIFY fileModeChanged)
- Q_PROPERTY(bool selectFolder READ selectFolder WRITE setSelectFolder NOTIFY fileModeChanged)
- Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged)
- Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
- Q_PROPERTY(QString selectedNameFilter READ selectedNameFilter WRITE selectNameFilter NOTIFY filterSelected)
- Q_PROPERTY(QUrl fileUrl READ fileUrl NOTIFY selectionAccepted)
- Q_PROPERTY(QList<QUrl> fileUrls READ fileUrls NOTIFY selectionAccepted)
-
-public:
- QQuickAbstractFileDialog(QObject *parent = 0);
- virtual ~QQuickAbstractFileDialog();
-
- virtual QString title() const;
- bool selectExisting() const { return m_selectExisting; }
- bool selectMultiple() const { return m_selectMultiple; }
- bool selectFolder() const { return m_selectFolder; }
- QUrl folder();
- QStringList nameFilters() const { return m_options->nameFilters(); }
- QString selectedNameFilter();
- QUrl fileUrl();
- virtual QList<QUrl> fileUrls();
-
-public Q_SLOTS:
- void setVisible(bool v);
- void setTitle(const QString &t);
- void setSelectExisting(bool s);
- void setSelectMultiple(bool s);
- void setSelectFolder(bool s);
- void setFolder(const QUrl &f);
- void setNameFilters(const QStringList &f);
- void selectNameFilter(const QString &f);
-
-Q_SIGNALS:
- void folderChanged();
- void nameFiltersChanged();
- void filterSelected();
- void fileModeChanged();
- void selectionAccepted();
-
-protected:
- void updateModes();
-
-protected:
- QPlatformFileDialogHelper *m_dlgHelper;
- QSharedPointer<QFileDialogOptions> m_options;
- bool m_selectExisting;
- bool m_selectMultiple;
- bool m_selectFolder;
-
- Q_DISABLE_COPY(QQuickAbstractFileDialog)
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKABSTRACTFILEDIALOG_P_H
diff --git a/src/imports/dialogs/qquickabstractfontdialog.cpp b/src/imports/dialogs/qquickabstractfontdialog.cpp
deleted file mode 100644
index 29dd15e8cc..0000000000
--- a/src/imports/dialogs/qquickabstractfontdialog.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickabstractfontdialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-QQuickAbstractFontDialog::QQuickAbstractFontDialog(QObject *parent)
- : QQuickAbstractDialog(parent)
- , m_dlgHelper(0)
- , m_options(QSharedPointer<QFontDialogOptions>(new QFontDialogOptions()))
-{
- // On the Mac, modality doesn't work unless you call exec(). But this is a reasonable default anyway.
- m_modality = Qt::NonModal;
- connect(this, SIGNAL(accepted()), this, SIGNAL(selectionAccepted()));
-}
-
-QQuickAbstractFontDialog::~QQuickAbstractFontDialog()
-{
-}
-
-void QQuickAbstractFontDialog::setVisible(bool v)
-{
- if (helper() && v) {
- m_dlgHelper->setOptions(m_options);
- // Due to the fact that QFontDialogOptions doesn't have currentFont...
- m_dlgHelper->setCurrentFont(m_font);
- }
- QQuickAbstractDialog::setVisible(v);
-}
-
-void QQuickAbstractFontDialog::setModality(Qt::WindowModality m)
-{
-#ifdef Q_OS_MAC
- // On the Mac, modality doesn't work unless you call exec()
- m_modality = Qt::NonModal;
- emit modalityChanged();
- return;
-#endif
- QQuickAbstractDialog::setModality(m);
-}
-
-QString QQuickAbstractFontDialog::title() const
-{
- return m_options->windowTitle();
-}
-
-bool QQuickAbstractFontDialog::scalableFonts() const
-{
- return m_options->testOption(QFontDialogOptions::ScalableFonts);
-}
-
-bool QQuickAbstractFontDialog::nonScalableFonts() const
-{
- return m_options->testOption(QFontDialogOptions::NonScalableFonts);
-}
-
-bool QQuickAbstractFontDialog::monospacedFonts() const
-{
- return m_options->testOption(QFontDialogOptions::MonospacedFonts);
-}
-
-bool QQuickAbstractFontDialog::proportionalFonts() const
-{
- return m_options->testOption(QFontDialogOptions::ProportionalFonts);
-}
-
-void QQuickAbstractFontDialog::setTitle(const QString &t)
-{
- if (m_options->windowTitle() == t) return;
- m_options->setWindowTitle(t);
- emit titleChanged();
-}
-
-void QQuickAbstractFontDialog::setFont(const QFont &arg)
-{
- if (m_font != arg) {
- m_font = arg;
- emit fontChanged();
- }
-}
-
-void QQuickAbstractFontDialog::setScalableFonts(bool arg)
-{
- m_options->setOption(QFontDialogOptions::ScalableFonts, arg);
- emit scalableFontsChanged();
-}
-
-void QQuickAbstractFontDialog::setNonScalableFonts(bool arg)
-{
- m_options->setOption(QFontDialogOptions::NonScalableFonts, arg);
- emit nonScalableFontsChanged();
-}
-
-void QQuickAbstractFontDialog::setMonospacedFonts(bool arg)
-{
- m_options->setOption(QFontDialogOptions::MonospacedFonts, arg);
- emit monospacedFontsChanged();
-}
-
-void QQuickAbstractFontDialog::setProportionalFonts(bool arg)
-{
- m_options->setOption(QFontDialogOptions::ProportionalFonts, arg);
- emit proportionalFontsChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickabstractfontdialog_p.h b/src/imports/dialogs/qquickabstractfontdialog_p.h
deleted file mode 100644
index 858a0d3eac..0000000000
--- a/src/imports/dialogs/qquickabstractfontdialog_p.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKABSTRACTFONTDIALOG_P_H
-#define QQUICKABSTRACTFONTDIALOG_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>
-#include <QQuickView>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include <QtGui/qfont.h>
-#include <qpa/qplatformtheme.h>
-#include "qquickabstractdialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQuickAbstractFontDialog : public QQuickAbstractDialog
-{
- Q_OBJECT
- Q_PROPERTY(bool scalableFonts READ scalableFonts WRITE setScalableFonts NOTIFY scalableFontsChanged)
- Q_PROPERTY(bool nonScalableFonts READ nonScalableFonts WRITE setNonScalableFonts NOTIFY nonScalableFontsChanged)
- Q_PROPERTY(bool monospacedFonts READ monospacedFonts WRITE setMonospacedFonts NOTIFY monospacedFontsChanged)
- Q_PROPERTY(bool proportionalFonts READ proportionalFonts WRITE setProportionalFonts NOTIFY proportionalFontsChanged)
- Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
-
-public:
- QQuickAbstractFontDialog(QObject *parent = 0);
- virtual ~QQuickAbstractFontDialog();
-
- virtual QString title() const;
- bool scalableFonts() const;
- bool nonScalableFonts() const;
- bool monospacedFonts() const;
- bool proportionalFonts() const;
- QFont font() const { return m_font; }
-
-public Q_SLOTS:
- void setVisible(bool v);
- void setModality(Qt::WindowModality m);
- void setTitle(const QString &t);
- void setFont(const QFont &arg);
- void setScalableFonts(bool arg);
- void setNonScalableFonts(bool arg);
- void setMonospacedFonts(bool arg);
- void setProportionalFonts(bool arg);
-
-Q_SIGNALS:
- void scalableFontsChanged();
- void nonScalableFontsChanged();
- void monospacedFontsChanged();
- void proportionalFontsChanged();
- void fontChanged();
- void selectionAccepted();
-
-protected:
- QPlatformFontDialogHelper *m_dlgHelper;
- QSharedPointer<QFontDialogOptions> m_options;
- QFont m_font;
-
- Q_DISABLE_COPY(QQuickAbstractFontDialog)
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKABSTRACTFONTDIALOG_P_H
diff --git a/src/imports/dialogs/qquickabstractmessagedialog.cpp b/src/imports/dialogs/qquickabstractmessagedialog.cpp
deleted file mode 100644
index a44464962a..0000000000
--- a/src/imports/dialogs/qquickabstractmessagedialog.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickabstractmessagedialog_p.h"
-#include <QtGui/qpa/qplatformdialoghelper.h>
-
-QT_BEGIN_NAMESPACE
-
-QQuickAbstractMessageDialog::QQuickAbstractMessageDialog(QObject *parent)
- : QQuickAbstractDialog(parent)
- , m_dlgHelper(0)
- , m_options(QSharedPointer<QMessageDialogOptions>(new QMessageDialogOptions()))
- , m_clickedButton(NoButton)
-{
-}
-
-QQuickAbstractMessageDialog::~QQuickAbstractMessageDialog()
-{
-}
-
-void QQuickAbstractMessageDialog::setVisible(bool v)
-{
- if (helper() && v)
- m_dlgHelper->setOptions(m_options);
- if (v)
- m_clickedButton = NoButton;
- QQuickAbstractDialog::setVisible(v);
-}
-
-void QQuickAbstractMessageDialog::setTitle(const QString &arg)
-{
- if (arg != m_options->windowTitle()) {
- m_options->setWindowTitle(arg);
- emit titleChanged();
- }
-}
-
-void QQuickAbstractMessageDialog::setText(const QString &arg)
-{
- if (arg != m_options->text()) {
- m_options->setText(arg);
- emit textChanged();
- }
-}
-
-void QQuickAbstractMessageDialog::setInformativeText(const QString &arg)
-{
- if (arg != m_options->informativeText()) {
- m_options->setInformativeText(arg);
- emit informativeTextChanged();
- }
-}
-
-void QQuickAbstractMessageDialog::setDetailedText(const QString &arg)
-{
- if (arg != m_options->detailedText()) {
- m_options->setDetailedText(arg);
- emit detailedTextChanged();
- }
-}
-
-void QQuickAbstractMessageDialog::setIcon(QQuickAbstractMessageDialog::Icon icon)
-{
- if (static_cast<int>(icon) != static_cast<int>(m_options->icon())) {
- m_options->setIcon(static_cast<QMessageDialogOptions::Icon>(icon));
- emit iconChanged();
- }
-}
-
-QUrl QQuickAbstractMessageDialog::standardIconSource()
-{
- switch (m_options->icon()) {
- case QMessageDialogOptions::Information:
- return QUrl("images/information.png");
- break;
- case QMessageDialogOptions::Warning:
- return QUrl("images/warning.png");
- break;
- case QMessageDialogOptions::Critical:
- return QUrl("images/critical.png");
- break;
- case QMessageDialogOptions::Question:
- return QUrl("images/question.png");
- break;
- default:
- return QUrl();
- break;
- }
-}
-
-void QQuickAbstractMessageDialog::setStandardButtons(StandardButtons buttons)
-{
- if (buttons != m_options->standardButtons()) {
- m_options->setStandardButtons(static_cast<QMessageDialogOptions::StandardButtons>(static_cast<int>(buttons)));
- emit standardButtonsChanged();
- }
-}
-
-void QQuickAbstractMessageDialog::click(QMessageDialogOptions::StandardButton button, QMessageDialogOptions::ButtonRole role)
-{
- setVisible(false);
- m_clickedButton = static_cast<StandardButton>(button);
- emit buttonClicked();
- switch (role) {
- case QMessageDialogOptions::AcceptRole:
- emit accept();
- break;
- case QMessageDialogOptions::RejectRole:
- emit reject();
- break;
- case QMessageDialogOptions::DestructiveRole:
- emit discard();
- break;
- case QMessageDialogOptions::HelpRole:
- emit help();
- break;
- case QMessageDialogOptions::YesRole:
- emit yes();
- break;
- case QMessageDialogOptions::NoRole:
- emit no();
- break;
- case QMessageDialogOptions::ApplyRole:
- emit apply();
- break;
- case QMessageDialogOptions::ResetRole:
- emit reset();
- break;
- default:
- qWarning("unhandled MessageDialog button %d with role %d", button, role);
- }
-}
-
-void QQuickAbstractMessageDialog::click(QQuickAbstractMessageDialog::StandardButton button)
-{
- click(static_cast<QMessageDialogOptions::StandardButton>(button),
- static_cast<QMessageDialogOptions::ButtonRole>(
- QMessageDialogOptions::buttonRole(static_cast<QMessageDialogOptions::StandardButton>(button))));
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickabstractmessagedialog_p.h b/src/imports/dialogs/qquickabstractmessagedialog_p.h
deleted file mode 100644
index f2427bb2e0..0000000000
--- a/src/imports/dialogs/qquickabstractmessagedialog_p.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKABSTRACTMESSAGEDIALOG_P_H
-#define QQUICKABSTRACTMESSAGEDIALOG_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>
-#include <QQuickView>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include <qpa/qplatformtheme.h>
-#include "qquickabstractdialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQuickAbstractMessageDialog : public QQuickAbstractDialog
-{
- Q_OBJECT
-
- Q_ENUMS(Icon)
- Q_ENUMS(StandardButton)
- Q_FLAGS(StandardButtons)
-
- Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
- Q_PROPERTY(QString informativeText READ informativeText WRITE setInformativeText NOTIFY informativeTextChanged)
- Q_PROPERTY(QString detailedText READ detailedText WRITE setDetailedText NOTIFY detailedTextChanged)
- Q_PROPERTY(Icon icon READ icon WRITE setIcon NOTIFY iconChanged)
- Q_PROPERTY(QUrl standardIconSource READ standardIconSource NOTIFY iconChanged)
- Q_PROPERTY(StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged)
- Q_PROPERTY(StandardButton clickedButton READ clickedButton NOTIFY buttonClicked)
-
-public:
- QQuickAbstractMessageDialog(QObject *parent = 0);
- virtual ~QQuickAbstractMessageDialog();
-
- virtual QString title() const { return m_options->windowTitle(); }
- QString text() const { return m_options->text(); }
- QString informativeText() const { return m_options->informativeText(); }
- QString detailedText() const { return m_options->detailedText(); }
-
- enum Icon {
- NoIcon = QMessageDialogOptions::NoIcon,
- Information = QMessageDialogOptions::Information,
- Warning = QMessageDialogOptions::Warning,
- Critical = QMessageDialogOptions::Critical,
- Question = QMessageDialogOptions::Question
- };
-
- Icon icon() const { return static_cast<Icon>(m_options->icon()); }
-
- QUrl standardIconSource();
-
- enum StandardButton {
- NoButton = QMessageDialogOptions::NoButton,
- Ok = QMessageDialogOptions::Ok,
- Save = QMessageDialogOptions::Save,
- SaveAll = QMessageDialogOptions::SaveAll,
- Open = QMessageDialogOptions::Open,
- Yes = QMessageDialogOptions::Yes,
- YesToAll = QMessageDialogOptions::YesToAll,
- No = QMessageDialogOptions::No,
- NoToAll = QMessageDialogOptions::NoToAll,
- Abort = QMessageDialogOptions::Abort,
- Retry = QMessageDialogOptions::Retry,
- Ignore = QMessageDialogOptions::Ignore,
- Close = QMessageDialogOptions::Close,
- Cancel = QMessageDialogOptions::Cancel,
- Discard = QMessageDialogOptions::Discard,
- Help = QMessageDialogOptions::Help,
- Apply = QMessageDialogOptions::Apply,
- Reset = QMessageDialogOptions::Reset,
- RestoreDefaults = QMessageDialogOptions::RestoreDefaults
- };
- Q_DECLARE_FLAGS(StandardButtons, StandardButton)
-
- StandardButtons standardButtons() const { return static_cast<StandardButtons>(static_cast<int>(m_options->standardButtons())); }
-
- StandardButton clickedButton() const { return m_clickedButton; }
-
-public Q_SLOTS:
- virtual void setVisible(bool v);
- virtual void setTitle(const QString &arg);
- void setText(const QString &arg);
- void setInformativeText(const QString &arg);
- void setDetailedText(const QString &arg);
- void setIcon(Icon icon);
- void setStandardButtons(StandardButtons buttons);
- void click(QMessageDialogOptions::StandardButton button, QMessageDialogOptions::ButtonRole);
- void click(QQuickAbstractMessageDialog::StandardButton button);
-
-Q_SIGNALS:
- void textChanged();
- void informativeTextChanged();
- void detailedTextChanged();
- void iconChanged();
- void standardButtonsChanged();
- void buttonClicked();
- void discard();
- void help();
- void yes();
- void no();
- void apply();
- void reset();
-
-protected:
- QPlatformMessageDialogHelper *m_dlgHelper;
- QSharedPointer<QMessageDialogOptions> m_options;
- StandardButton m_clickedButton;
-
- Q_DISABLE_COPY(QQuickAbstractMessageDialog)
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAbstractMessageDialog::StandardButtons)
-
-QT_END_NAMESPACE
-
-#endif // QQUICKABSTRACTMESSAGEDIALOG_P_H
diff --git a/src/imports/dialogs/qquickcolordialog.cpp b/src/imports/dialogs/qquickcolordialog.cpp
deleted file mode 100644
index d0e0e11b07..0000000000
--- a/src/imports/dialogs/qquickcolordialog.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickcolordialog_p.h"
-#include <QQuickItem>
-#include <private/qguiapplication_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype AbstractColorDialog
- \instantiates QQuickColorDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup qtquick-visual
- \brief API wrapper for QML file dialog implementations
- \since 5.1
- \internal
-
- AbstractColorDialog provides only the API for implementing a color dialog.
- The implementation (e.g. a Window or preferably an Item, in case it is
- shown on a device that doesn't support multiple windows) can be provided as
- \l implementation, which is the default property (the only allowed child
- element).
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractColorDialog::accepted
-
- This signal is emitted by \l accept().
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractColorDialog::rejected
-
- This signal is emitted by \l reject().
-*/
-
-/*!
- \class QQuickColorDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- The QQuickColorDialog class is a concrete subclass of
- \l QQuickAbstractColorDialog, but it is abstract from the QML perspective
- because it needs to enclose a graphical implementation. It exists in order
- to provide accessors and helper functions which the QML implementation will
- need.
-
- \since 5.1
-*/
-
-/*!
- Constructs a file dialog wrapper with parent window \a parent.
-*/
-QQuickColorDialog::QQuickColorDialog(QObject *parent)
- : QQuickAbstractColorDialog(parent)
-{
-}
-
-
-/*!
- Destroys the file dialog wrapper.
-*/
-QQuickColorDialog::~QQuickColorDialog()
-{
-}
-
-/*!
- \qmlproperty bool AbstractColorDialog::visible
-
- This property holds whether the dialog is visible. By default this is false.
-*/
-
-/*!
- \qmlproperty QObject AbstractColorDialog::implementation
-
- The QML object which implements the actual file dialog. Should be either a
- \l Window or an \l Item.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickcolordialog_p.h b/src/imports/dialogs/qquickcolordialog_p.h
deleted file mode 100644
index ff6953fc0f..0000000000
--- a/src/imports/dialogs/qquickcolordialog_p.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKCOLORDIALOG_P_H
-#define QQUICKCOLORDIALOG_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 "qquickabstractcolordialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQuickColorDialog : public QQuickAbstractColorDialog
-{
- Q_OBJECT
- Q_PROPERTY(QObject* implementation READ qmlImplementation WRITE setQmlImplementation DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "implementation") // AbstractColorDialog in QML can have only one child
-
-public:
- explicit QQuickColorDialog(QObject *parent = 0);
- ~QQuickColorDialog();
-
-protected:
- virtual QPlatformColorDialogHelper *helper() { return 0; }
-
- Q_DISABLE_COPY(QQuickColorDialog)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickColorDialog *)
-
-#endif // QQUICKCOLORDIALOG_P_H
diff --git a/src/imports/dialogs/qquickfiledialog.cpp b/src/imports/dialogs/qquickfiledialog.cpp
deleted file mode 100644
index 2ee4afc5d2..0000000000
--- a/src/imports/dialogs/qquickfiledialog.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickfiledialog_p.h"
-#include <QQuickItem>
-#include <private/qguiapplication_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype AbstractFileDialog
- \instantiates QQuickFileDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup qtquick-visual
- \brief API wrapper for QML file dialog implementations
- \since 5.1
- \internal
-
- AbstractFileDialog provides only the API for implementing a file dialog.
- The implementation (e.g. a Window or preferably an Item, in case it is
- shown on a device that doesn't support multiple windows) can be provided as
- \l implementation, which is the default property (the only allowed child
- element).
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractFileDialog::accepted
-
- This signal is emitted by \l accept().
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractFileDialog::rejected
-
- This signal is emitted by \l reject().
-*/
-
-/*!
- \class QQuickFileDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- The QQuickFileDialog class is a concrete subclass of
- \l QQuickAbstractFileDialog, but it is abstract from the QML perspective
- because it needs to enclose a graphical implementation. It exists in order
- to provide accessors and helper functions which the QML implementation will
- need.
-
- \since 5.1
-*/
-
-/*!
- Constructs a file dialog wrapper with parent window \a parent.
-*/
-QQuickFileDialog::QQuickFileDialog(QObject *parent)
- : QQuickAbstractFileDialog(parent)
-{
-}
-
-
-/*!
- Destroys the file dialog wrapper.
-*/
-QQuickFileDialog::~QQuickFileDialog()
-{
-}
-
-QList<QUrl> QQuickFileDialog::fileUrls()
-{
- return m_selections;
-}
-
-/*!
- \qmlproperty bool AbstractFileDialog::visible
-
- This property holds whether the dialog is visible. By default this is false.
-*/
-
-/*!
- \qmlproperty bool AbstractFileDialog::fileUrls
-
- A list of files to be populated as the user chooses.
-*/
-
-/*!
- \brief Clears \l fileUrls
-*/
-void QQuickFileDialog::clearSelection()
-{
- m_selections.clear();
-}
-
-/*!
- \brief Adds one file to \l fileUrls
-
- \l path should be given as an absolute file:// path URL.
- Returns true on success, false if the given path is
- not valid given the current property settings.
-*/
-bool QQuickFileDialog::addSelection(const QUrl &path)
-{
- QFileInfo info(path.toLocalFile());
- if (info.exists() && ((info.isDir() && m_selectFolder) || !info.isDir())) {
- if (m_selectFolder)
- m_selections.append(pathFolder(path.toLocalFile()));
- else
- m_selections.append(path);
- return true;
- }
- return false;
-}
-
-/*!
- \brief get a file's directory as a URL
-
- If \a path points to a directory, just convert it to a URL.
- If \a path points to a file, convert the file's directory to a URL.
-*/
-QUrl QQuickFileDialog::pathFolder(const QString &path)
-{
- QFileInfo info(path);
- if (info.exists() && info.isDir())
- return QUrl::fromLocalFile(path);
- return QUrl::fromLocalFile(QFileInfo(path).absolutePath());
-}
-
-/*!
- \qmlproperty QObject AbstractFileDialog::implementation
-
- The QML object which implements the actual file dialog. Should be either a
- \l Window or an \l Item.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickfontdialog.cpp b/src/imports/dialogs/qquickfontdialog.cpp
deleted file mode 100644
index 2f3c6d83bb..0000000000
--- a/src/imports/dialogs/qquickfontdialog.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickfontdialog_p.h"
-#include <QQuickItem>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype AbstractFontDialog
- \instantiates QQuickFontDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup qtquick-visual
- \brief API wrapper for QML font dialog implementations
- \since 5.2
- \internal
-
- AbstractFontDialog provides only the API for implementing a font dialog.
- The implementation (e.g. a Window or preferably an Item, in case it is
- shown on a device that doesn't support multiple windows) can be provided as
- \l implementation, which is the default property (the only allowed child
- element).
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractFontDialog::accepted
-
- The \a accepted signal is emitted by \l accept().
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractFontDialog::rejected
-
- The \a accepted signal is emitted by \l reject().
-*/
-
-/*!
- \class QQuickFontDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- The QQuickFontDialog class is a concrete subclass of \l
- QQuickAbstractFontDialog, but it is abstract from the QML perspective
- because it needs to enclose a graphical implementation. It exists in order
- to provide accessors and helper functions which the QML implementation will
- need.
-
- \since 5.2
-*/
-
-/*!
- Constructs a font dialog wrapper with parent window \a parent.
-*/
-QQuickFontDialog::QQuickFontDialog(QObject *parent)
- : QQuickAbstractFontDialog(parent)
-{
-}
-
-
-/*!
- Destroys the font dialog wrapper.
-*/
-QQuickFontDialog::~QQuickFontDialog()
-{
-}
-
-/*!
- \qmlproperty bool AbstractFontDialog::visible
-
- This property holds whether the dialog is visible. By default this is false.
-*/
-
-/*!
- \qmlproperty QObject AbstractFontDialog::implementation
-
- The QML object which implements the actual font dialog. Should be either a
- \l Window or an \l Item.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickmessagedialog.cpp b/src/imports/dialogs/qquickmessagedialog.cpp
deleted file mode 100644
index 5346aeeda8..0000000000
--- a/src/imports/dialogs/qquickmessagedialog.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickmessagedialog_p.h"
-#include <QQuickItem>
-#include <private/qguiapplication_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype AbstractMessageDialog
- \instantiates QQuickMessageDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup qtquick-visual
- \brief API wrapper for QML message dialog implementations
- \since 5.2
- \internal
-
- AbstractMessageDialog provides only the API for implementing a message dialog.
- The implementation (e.g. a Window or preferably an Item, in case it is
- shown on a device that doesn't support multiple windows) can be provided as
- \l implementation, which is the default property (the only allowed child
- element).
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractMessageDialog::accepted
-
- This signal is emitted by \l accept().
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::AbstractMessageDialog::rejected
-
- This signal is emitted by \l reject().
-*/
-
-/*!
- \class QQuickMessageDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- The QQuickMessageDialog class is a concrete subclass of
- \l QQuickAbstractMessageDialog, but it is abstract from the QML perspective
- because it needs to enclose a graphical implementation. It exists in order
- to provide accessors and helper functions which the QML implementation will
- need.
-
- \since 5.2
-*/
-
-/*!
- Constructs a message dialog wrapper with parent window \a parent.
-*/
-QQuickMessageDialog::QQuickMessageDialog(QObject *parent)
- : QQuickAbstractMessageDialog(parent)
-{
-}
-
-
-/*!
- Destroys the message dialog wrapper.
-*/
-QQuickMessageDialog::~QQuickMessageDialog()
-{
-}
-
-/*!
- \qmlproperty bool AbstractMessageDialog::visible
-
- This property holds whether the dialog is visible. By default this is false.
-*/
-
-/*!
- \qmlproperty QObject AbstractMessageDialog::implementation
-
- The QML object which implements the actual message dialog. Should be either a
- \l Window or an \l Item.
-*/
-
-void QQuickMessageDialog::accept() {
- // enter key is treated like OK
- if (m_clickedButton == NoButton)
- m_clickedButton = Ok;
- QQuickAbstractMessageDialog::accept();
-}
-
-void QQuickMessageDialog::reject() {
- // escape key is treated like cancel
- if (m_clickedButton == NoButton)
- m_clickedButton = Cancel;
- QQuickAbstractMessageDialog::reject();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickplatformcolordialog.cpp b/src/imports/dialogs/qquickplatformcolordialog.cpp
deleted file mode 100644
index 11ddbfe6c7..0000000000
--- a/src/imports/dialogs/qquickplatformcolordialog.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickplatformcolordialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickView>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype ColorDialog
- \instantiates QQuickPlatformColorDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup dialogs
- \brief Dialog component for choosing a color.
- \since 5.1
-
- ColorDialog allows the user to select a color. The dialog is initially
- invisible. You need to set the properties as desired first, then set
- \l visible to true or call \l open().
-
- Here is a minimal example to open a color dialog and exit after the user
- chooses a color:
-
- \qml
- import QtQuick 2.1
- import QtQuick.Dialogs 1.0
-
- ColorDialog {
- id: colorDialog
- title: "Please choose a color"
- onAccepted: {
- console.log("You chose: " + colorDialog.color)
- Qt.quit()
- }
- onRejected: {
- console.log("Canceled")
- Qt.quit()
- }
- Component.onCompleted: visible = true
- }
- \endqml
-
- A ColorDialog window is automatically transient for its parent window. So
- whether you declare the dialog inside an \l Item or inside a \l Window, the
- dialog will appear centered over the window containing the item, or over
- the Window that you declared.
-
- The implementation of ColorDialog will be a platform color dialog if
- possible. If that isn't possible, then it will try to instantiate a
- \l QColorDialog. If that also isn't possible, then it will fall back to a QML
- implementation, DefaultColorDialog.qml. In that case you can customize the
- appearance by editing this file. DefaultColorDialog.qml contains a Rectangle
- to hold the dialog's contents, because certain embedded systems do not
- support multiple top-level windows. When the dialog becomes visible, it
- will automatically be wrapped in a Window if possible, or simply reparented
- on top of the main window if there can only be one window.
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::ColorDialog::accepted
-
- This handler is called when the user has finished using the
- dialog. You can then inspect the \l color property to get the selection.
-
- Example:
-
- \qml
- ColorDialog {
- onAccepted: { console.log("Selected color: " + color) }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::ColorDialog::rejected
-
- This handler is called when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickPlatformColorDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- \brief The QQuickPlatformColorDialog class provides a color dialog
-
- The dialog is implemented via the QPlatformColorDialogHelper when possible;
- otherwise it falls back to a QColorDialog or a QML implementation.
-
- \since 5.1
-*/
-
-/*!
- Constructs a color dialog with parent window \a parent.
-*/
-QQuickPlatformColorDialog::QQuickPlatformColorDialog(QObject *parent) :
- QQuickAbstractColorDialog(parent)
-{
-}
-
-/*!
- Destroys the color dialog.
-*/
-QQuickPlatformColorDialog::~QQuickPlatformColorDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformColorDialogHelper *QQuickPlatformColorDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if ( !m_dlgHelper && QGuiApplicationPrivate::platformTheme()->
- usePlatformNativeDialog(QPlatformTheme::ColorDialog) ) {
- m_dlgHelper = static_cast<QPlatformColorDialogHelper *>(QGuiApplicationPrivate::platformTheme()
- ->createPlatformDialogHelper(QPlatformTheme::ColorDialog));
- if (!m_dlgHelper)
- return m_dlgHelper;
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- connect(m_dlgHelper, SIGNAL(currentColorChanged(QColor)), this, SLOT(setCurrentColor(QColor)));
- connect(m_dlgHelper, SIGNAL(colorSelected(QColor)), this, SLOT(setColor(QColor)));
- }
-
- return m_dlgHelper;
-}
-
-/*!
- \qmlproperty bool ColorDialog::visible
-
- This property holds whether the dialog is visible. By default this is
- false.
-
- \sa modality
-*/
-
-/*!
- \qmlproperty Qt::WindowModality ColorDialog::modality
-
- Whether the dialog should be shown modal with respect to the window
- containing the dialog's parent Item, modal with respect to the whole
- application, or non-modal.
-
- By default it is \l NonModal.
-
- Modality does not mean that there are any blocking calls to wait for the
- dialog to be accepted or rejected; it's only that the user will be
- prevented from interacting with the parent window and/or the application
- windows at the same time.
-
- On MacOS the color dialog is only allowed to be non-modal.
-*/
-
-/*!
- \qmlmethod void ColorDialog::open()
-
- Shows the dialog to the user. It is equivalent to setting \l visible to
- true.
-*/
-
-/*!
- \qmlmethod void ColorDialog::close()
-
- Closes the dialog.
-*/
-
-/*!
- \qmlproperty string ColorDialog::title
-
- The title of the dialog window.
-*/
-
-/*!
- \qmlproperty bool ColorDialog::showAlphaChannel
-
- Whether the dialog will provide a means of changing the opacity.
-
- By default, this property is true. This property must be set to the desired
- value before opening the dialog. Usually the alpha channel is represented
- by an additional slider control.
-*/
-
-/*!
- \qmlproperty color ColorDialog::color
-
- The color which the user selected.
-
- \note This color is not always the same as the color held by the
- currentColor property since the user can choose different colors before
- finally selecting the one to use.
-
- \sa currentColor
-*/
-
-/*!
- \qmlproperty color ColorDialog::currentColor
-
- The color which the user has currently selected.
-
- For the color that is set when the dialog is accepted, use the \l color
- property.
-
- \sa color
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickplatformfiledialog.cpp b/src/imports/dialogs/qquickplatformfiledialog.cpp
deleted file mode 100644
index 066aabe336..0000000000
--- a/src/imports/dialogs/qquickplatformfiledialog.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickplatformfiledialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickView>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype FileDialog
- \instantiates QQuickPlatformFileDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup dialogs
- \brief Dialog component for choosing files from a local filesystem.
- \since 5.1
-
- FileDialog provides a basic file chooser: it allows the user to select
- existing files and/or directories, or create new filenames. The dialog is
- initially invisible. You need to set the properties as desired first, then
- set \l visible to true or call \l open().
-
- Here is a minimal example to open a file dialog and exit after the user
- chooses a file:
-
- \qml
- import QtQuick 2.1
- import QtQuick.Dialogs 1.0
-
- FileDialog {
- id: fileDialog
- title: "Please choose a file"
- onAccepted: {
- console.log("You chose: " + fileDialog.fileUrls)
- Qt.quit()
- }
- onRejected: {
- console.log("Canceled")
- Qt.quit()
- }
- Component.onCompleted: visible = true
- }
- \endqml
-
- A FileDialog window is automatically transient for its parent window. So
- whether you declare the dialog inside an \l Item or inside a \l Window, the
- dialog will appear centered over the window containing the item, or over
- the Window that you declared.
-
- The implementation of FileDialog will be a platform file dialog if
- possible. If that isn't possible, then it will try to instantiate a
- \l QFileDialog. If that also isn't possible, then it will fall back to a QML
- implementation, DefaultFileDialog.qml. In that case you can customize the
- appearance by editing this file. DefaultFileDialog.qml contains a Rectangle
- to hold the dialog's contents, because certain embedded systems do not
- support multiple top-level windows. When the dialog becomes visible, it
- will automatically be wrapped in a Window if possible, or simply reparented
- on top of the main window if there can only be one window.
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FileDialog::accepted
-
- This handler is called when the user has finished using the
- dialog. You can then inspect the \l fileUrl or \l fileUrls properties to
- get the selection.
-
- Example:
-
- \qml
- FileDialog {
- onAccepted: { console.log("Selected file: " + fileUrl) }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FileDialog::rejected
-
- This handler is called when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickPlatformFileDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- \brief The QQuickPlatformFileDialog class provides a file dialog
-
- The dialog is implemented via the QPlatformFileDialogHelper when possible;
- otherwise it falls back to a QFileDialog or a QML implementation.
-
- \since 5.1
-*/
-
-/*!
- Constructs a file dialog with parent window \a parent.
-*/
-QQuickPlatformFileDialog::QQuickPlatformFileDialog(QObject *parent) :
- QQuickAbstractFileDialog(parent)
-{
-}
-
-/*!
- Destroys the file dialog.
-*/
-QQuickPlatformFileDialog::~QQuickPlatformFileDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformFileDialogHelper *QQuickPlatformFileDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if ( !m_dlgHelper && QGuiApplicationPrivate::platformTheme()->
- usePlatformNativeDialog(QPlatformTheme::FileDialog) ) {
- m_dlgHelper = static_cast<QPlatformFileDialogHelper *>(QGuiApplicationPrivate::platformTheme()
- ->createPlatformDialogHelper(QPlatformTheme::FileDialog));
- if (!m_dlgHelper)
- return m_dlgHelper;
- connect(m_dlgHelper, SIGNAL(directoryEntered(QUrl)), this, SIGNAL(folderChanged()));
- connect(m_dlgHelper, SIGNAL(filterSelected(QString)), this, SIGNAL(filterSelected()));
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- }
-
- return m_dlgHelper;
-}
-
-/*!
- \qmlproperty bool FileDialog::visible
-
- This property holds whether the dialog is visible. By default this is
- false.
-
- \sa modality
-*/
-
-/*!
- \qmlproperty Qt::WindowModality FileDialog::modality
-
- Whether the dialog should be shown modal with respect to the window
- containing the dialog's parent Item, modal with respect to the whole
- application, or non-modal.
-
- By default it is \c Qt.WindowModal.
-
- Modality does not mean that there are any blocking calls to wait for the
- dialog to be accepted or rejected; it's only that the user will be
- prevented from interacting with the parent window and/or the application
- windows at the same time. You probably need to write an onAccepted handler
- to actually load or save the chosen file.
-*/
-
-/*!
- \qmlmethod void FileDialog::open()
-
- Shows the dialog to the user. It is equivalent to setting \l visible to
- true.
-*/
-
-/*!
- \qmlmethod void FileDialog::close()
-
- Closes the dialog.
-*/
-
-/*!
- \qmlproperty string FileDialog::title
-
- The title of the dialog window.
-*/
-
-/*!
- \qmlproperty bool FileDialog::selectExisting
-
- Whether only existing files or directories can be selected.
-
- By default, this property is true. This property must be set to the desired
- value before opening the dialog. Setting this property to false implies
- that the dialog is for naming a file to which to save something, or naming
- a folder to be created; therefore \l selectMultiple must be false.
-*/
-
-/*!
- \qmlproperty bool FileDialog::selectMultiple
-
- Whether more than one filename can be selected.
-
- By default, this property is false. This property must be set to the
- desired value before opening the dialog. Setting this property to true
- implies that \l selectExisting must be true.
-*/
-
-/*!
- \qmlproperty bool FileDialog::selectFolder
-
- Whether the selected item should be a folder.
-
- By default, this property is false. This property must be set to the
- desired value before opening the dialog. Setting this property to true
- implies that \l selectMultiple must be false and \l selectExisting must be
- true.
-*/
-
-/*!
- \qmlproperty url FileDialog::folder
-
- The path to the currently selected folder. Setting this property before
- invoking open() will cause the file browser to be initially positioned on
- the specified folder.
-
- The value of this property is also updated after the dialog is closed.
-
- By default, this property is false.
-*/
-
-/*!
- \qmlproperty list<string> FileDialog::nameFilters
-
- A list of strings to be used as file name filters. Each string can be a
- space-separated list of filters; filters may include the ? and * wildcards.
- The list of filters can also be enclosed in parentheses and a textual
- description of the filter can be provided.
-
- For example:
-
- \qml
- FileDialog {
- nameFilters: [ "Image files (*.jpg *.png)", "All files (*)" ]
- }
- \endqml
-
- \note Directories are not excluded by filters.
- \sa selectedNameFilter
-*/
-
-/*!
- \qmlproperty string FileDialog::selectedNameFilter
-
- Which of the \l nameFilters is currently selected.
-
- This property can be set before the dialog is visible, to set the default
- name filter, and can also be set while the dialog is visible to set the
- current name filter. It is also updated when the user selects a different
- filter.
-*/
-
-/*!
- \qmlproperty url FileDialog::fileUrl
-
- The path of the file which was selected by the user.
-
- \note This property is set only if exactly one file was selected. In all
- other cases, it will be empty.
-
- \sa fileUrls
-*/
-
-/*!
- \qmlproperty list<url> FileDialog::fileUrls
-
- The list of file paths which were selected by the user.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickplatformfontdialog.cpp b/src/imports/dialogs/qquickplatformfontdialog.cpp
deleted file mode 100644
index 46ad5eb8df..0000000000
--- a/src/imports/dialogs/qquickplatformfontdialog.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickplatformfontdialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickView>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype FontDialog
- \instantiates QQuickPlatformFontDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup qtquick-visual
- \ingroup dialogs
- \brief Dialog component for choosing a font.
- \since 5.2
-
- FontDialog allows the user to select a font. The dialog is initially
- invisible. You need to set the properties as desired first, then set
- \l visible to true or call \l open().
-
- Here is a minimal example to open a font dialog and exit after the user
- chooses a font:
-
- \qml
- import QtQuick 2.2
- import QtQuick.Dialogs 1.1
-
- FontDialog {
- id: fontDialog
- title: "Please choose a font"
- font: Qt.font({ family: "Arial", pointSize: 24, weight: Font.Normal })
- onAccepted: {
- console.log("You chose: " + fontDialog.font)
- Qt.quit()
- }
- onRejected: {
- console.log("Canceled")
- Qt.quit()
- }
- Component.onCompleted: visible = true
- }
- \endqml
-
- A FontDialog window is automatically transient for its parent window. So
- whether you declare the dialog inside an \l Item or inside a \l Window, the
- dialog will appear centered over the window containing the item, or over
- the Window that you declared.
-
- The implementation of FontDialog will be a platform font dialog if
- possible. If that isn't possible, then it will try to instantiate a
- \l QFontDialog. If that also isn't possible, then it will fall back to a QML
- implementation, DefaultFontDialog.qml. In that case you can customize the
- appearance by editing this file. DefaultFontDialog.qml contains a Rectangle
- to hold the dialog's contents, because certain embedded systems do not
- support multiple top-level windows. When the dialog becomes visible, it
- will automatically be wrapped in a Window if possible, or simply reparented
- on top of the main window if there can only be one window.
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FontDialog::accepted
-
- The \a accepted signal is emitted when the user has finished using the
- dialog. You can then inspect the \a font property to get the selection.
-
- Example:
-
- \qml
- FontDialog {
- onAccepted: { console.log("Selected font: " + font) }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FontDialog::rejected
-
- The \a rejected signal is emitted when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickPlatformFontDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- \brief The QQuickPlatformFontDialog class provides a font dialog
-
- The dialog is implemented via the QQuickPlatformFontDialogHelper when possible;
- otherwise it falls back to a QFontDialog or a QML implementation.
-
- \since 5.2
-*/
-
-/*!
- Constructs a file dialog with parent window \a parent.
-*/
-QQuickPlatformFontDialog::QQuickPlatformFontDialog(QObject *parent) :
- QQuickAbstractFontDialog(parent)
-{
-}
-
-/*!
- Destroys the file dialog.
-*/
-QQuickPlatformFontDialog::~QQuickPlatformFontDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformFontDialogHelper *QQuickPlatformFontDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if ( !m_dlgHelper && QGuiApplicationPrivate::platformTheme()->
- usePlatformNativeDialog(QPlatformTheme::FontDialog) ) {
- m_dlgHelper = static_cast<QPlatformFontDialogHelper *>(QGuiApplicationPrivate::platformTheme()
- ->createPlatformDialogHelper(QPlatformTheme::FontDialog));
- if (!m_dlgHelper)
- return m_dlgHelper;
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- connect(m_dlgHelper, SIGNAL(currentFontChanged(const QFont&)), this, SLOT(setFont(const QFont&)));
- connect(m_dlgHelper, SIGNAL(fontSelected(const QFont&)), this, SLOT(setFont(const QFont&)));
- }
-
- return m_dlgHelper;
-}
-
-/*!
- \qmlproperty bool FontDialog::visible
-
- This property holds whether the dialog is visible. By default this is
- false.
-
- \sa modality
-*/
-
-/*!
- \qmlproperty Qt::WindowModality FontDialog::modality
-
- Whether the dialog should be shown modal with respect to the window
- containing the dialog's parent Item, modal with respect to the whole
- application, or non-modal.
-
- By default it is \l WindowModal.
-
- Modality does not mean that there are any blocking calls to wait for the
- dialog to be accepted or rejected; it's only that the user will be
- prevented from interacting with the parent window and/or the application
- windows at the same time. You probably need to write an onAccepted handler
- to actually load or save the chosen file.
-*/
-
-/*!
- \qmlmethod void FontDialog::open()
-
- Shows the dialog to the user. It is equivalent to setting \l visible to
- true.
-*/
-
-/*!
- \qmlmethod void FontDialog::close()
-
- Closes the dialog.
-*/
-
-/*!
- \qmlproperty string FontDialog::title
-
- The title of the dialog window.
-*/
-
-/*!
- \qmlproperty bool FontDialog::scalableFonts
-
- Whether the dialog will show scalable fonts or not.
-*/
-
-/*!
- \qmlproperty bool FontDialog::nonScalableFonts
-
- Whether the dialog will show non scalable fonts or not.
-*/
-
-/*!
- \qmlproperty bool FontDialog::monospacedFonts
-
- Whether the dialog will show monospaced fonts or not.
-*/
-
-/*!
- \qmlproperty bool FontDialog::proportionalFonts
-
- Whether the dialog will show proportional fonts or not.
-*/
-
-/*!
- \qmlproperty font FontDialog::font
-
- The font which the user selected.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickplatformmessagedialog.cpp b/src/imports/dialogs/qquickplatformmessagedialog.cpp
deleted file mode 100644
index 65114100d2..0000000000
--- a/src/imports/dialogs/qquickplatformmessagedialog.cpp
+++ /dev/null
@@ -1,398 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickplatformmessagedialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <QWindow>
-#include <QQuickView>
-#include <QQuickWindow>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype MessageDialog
- \instantiates QQuickPlatformMessageDialog
- \inqmlmodule QtQuick.Dialogs 1
- \ingroup dialogs
- \brief Dialog component for displaying popup messages.
- \since 5.2
-
- The most basic use case for a MessageDialog is a popup alert. It also
- allows the user to respond in various ways depending on which buttons are
- enabled. The dialog is initially invisible. You need to set the properties
- as desired first, then set \l visible to \c true or call \l open().
-
- Here is a minimal example to show an alert and exit after the user
- responds:
-
- \qml
- import QtQuick 2.2
- import QtQuick.Dialogs 1.1
-
- MessageDialog {
- id: messageDialog
- title: "May I have your attention please"
- text: "It's so cool that you are using Qt Quick."
- onAccepted: {
- console.log("And of course you could only agree.")
- Qt.quit()
- }
- Component.onCompleted: visible = true
- }
- \endqml
-
- There are several possible handlers depending on which \l standardButtons
- the dialog has and the \l {QMessageBox::ButtonRole} {ButtonRole} of each.
- For example, the \l {rejected} {onRejected} handler will be called if the
- user presses a \gui Cancel, \gui Close or \gui Abort button.
-
- A MessageDialog window is automatically transient for its parent window. So
- whether you declare the dialog inside an \l Item or inside a \l Window, the
- dialog will appear centered over the window containing the item, or over
- the Window that you declared.
-
- The implementation of MessageDialog will be a platform message dialog if
- possible. If that isn't possible, then it will try to instantiate a
- \l QMessageBox. If that also isn't possible, then it will fall back to a QML
- implementation, \c DefaultMessageDialog.qml. In that case you can customize
- the appearance by editing this file. \c DefaultMessageDialog.qml contains a
- \l Rectangle to hold the dialog's contents, because certain embedded systems
- do not support multiple top-level windows. When the dialog becomes visible,
- it will automatically be wrapped in a \l Window if possible, or simply
- reparented on top of the main window if there can only be one window.
-*/
-
-/*!
- \qmlsignal MessageDialog::accepted()
-
- This handler is called when the user has pressed any button which has the
- \l {QMessageBox::AcceptRole} {AcceptRole}: \gui OK, \gui Open, \gui Save,
- \gui {Save All}, \gui Retry or \gui Ignore.
-*/
-
-/*!
- \qmlsignal MessageDialog::rejected()
-
- This handler is called when the user has dismissed the dialog, by closing
- the dialog window, by pressing a \gui Cancel, \gui Close or \gui Abort
- button on the dialog, or by pressing the back button or the escape key.
-*/
-
-/*!
- \qmlsignal MessageDialog::discard()
-
- This handler is called when the user has pressed the \gui Discard button.
-*/
-
-/*!
- \qmlsignal MessageDialog::help()
-
- This handler is called when the user has pressed the \gui Help button.
- Depending on platform, the dialog may not be automatically dismissed
- because the help that your application provides may need to be relevant to
- the text shown in this dialog in order to assist the user in making a
- decision. However on other platforms it's not possible to show a dialog and
- a help window at the same time. If you want to be sure that the dialog will
- close, you can set \l visible to \c false in your handler.
-*/
-
-/*!
- \qmlsignal MessageDialog::yes()
-
- This handler is called when the user has pressed any button which has
- the \l {QMessageBox::YesRole} {YesRole}: \gui Yes or \gui {Yes to All}.
-*/
-
-/*!
- \qmlsignal MessageDialog::no()
-
- This handler is called when the user has pressed any button which has
- the \l {QMessageBox::NoRole} {NoRole}: \gui No or \gui {No to All}.
-*/
-
-/*!
- \qmlsignal MessageDialog::apply()
-
- This handler is called when the user has pressed the \gui Apply button.
-*/
-
-/*!
- \qmlsignal MessageDialog::reset()
-
- This handler is called when the user has pressed any button which has
- the \l {QMessageBox::ResetRole} {ResetRole}: \gui Reset or \gui {Restore Defaults}.
-*/
-
-/*!
- \class QQuickPlatformMessageDialog
- \inmodule QtQuick.Dialogs
- \internal
-
- \brief The QQuickPlatformMessageDialog class provides a message dialog
-
- The dialog is implemented via the QPlatformMessageDialogHelper when possible;
- otherwise it falls back to a QMessageBox or a QML implementation.
-
- \since 5.2
-*/
-
-/*!
- Constructs a file dialog with parent window \a parent.
-*/
-QQuickPlatformMessageDialog::QQuickPlatformMessageDialog(QObject *parent) :
- QQuickAbstractMessageDialog(parent)
-{
-}
-
-/*!
- Destroys the file dialog.
-*/
-QQuickPlatformMessageDialog::~QQuickPlatformMessageDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformMessageDialogHelper *QQuickPlatformMessageDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if ( !m_dlgHelper && QGuiApplicationPrivate::platformTheme()->
- usePlatformNativeDialog(QPlatformTheme::MessageDialog) ) {
- m_dlgHelper = static_cast<QPlatformMessageDialogHelper *>(QGuiApplicationPrivate::platformTheme()
- ->createPlatformDialogHelper(QPlatformTheme::MessageDialog));
- if (!m_dlgHelper)
- return m_dlgHelper;
- // accept() shouldn't be emitted. reject() happens only if the dialog is
- // dismissed by closing the window rather than by one of its button widgets.
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- connect(m_dlgHelper, SIGNAL(clicked(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole)),
- this, SLOT(click(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole)));
- }
-
- return m_dlgHelper;
-}
-
-/*!
- \qmlproperty bool MessageDialog::visible
-
- This property holds whether the dialog is visible. By default this is
- \c false.
-
- \sa modality
-*/
-
-/*!
- \qmlproperty Qt::WindowModality MessageDialog::modality
-
- Whether the dialog should be shown modal with respect to the window
- containing the dialog's parent Item, modal with respect to the whole
- application, or non-modal.
-
- By default it is \c Qt.WindowModal.
-
- Modality does not mean that there are any blocking calls to wait for the
- dialog to be accepted or rejected; it's only that the user will be
- prevented from interacting with the parent window and/or the application
- windows until the dialog is dismissed.
-*/
-
-/*!
- \qmlmethod void MessageDialog::open()
-
- Shows the dialog to the user. It is equivalent to setting \l visible to
- \c true.
-*/
-
-/*!
- \qmlmethod void MessageDialog::close()
-
- Closes the dialog.
-*/
-
-/*!
- \qmlproperty string MessageDialog::title
-
- The title of the dialog window.
-*/
-
-/*!
- \qmlproperty string MessageDialog::text
-
- The primary text to be displayed.
-*/
-
-/*!
- \qmlproperty string MessageDialog::informativeText
-
- The informative text that provides a fuller description for the message.
-
- Informative text can be used to supplement the \c text to give more
- information to the user. Depending on the platform, it may appear in a
- smaller font below the text, or simply appended to the text.
-
- \sa {MessageDialog::text}{text}
-*/
-
-/*!
- \qmlproperty string MessageDialog::detailedText
-
- The text to be displayed in the details area, which is hidden by default.
- The user will then be able to press the \gui {Show Details...} button to
- make it visible.
-
- \sa {MessageDialog::text}{text}
-*/
-
-/*!
- \enum QQuickStandardIcon::Icon
-
- This enum specifies a standard icon to be used on a dialog.
-*/
-
-/*!
- \qmlproperty QQuickStandardIcon::Icon MessageDialog::icon
-
- The icon of the message box can be specified with one of these values:
-
- \table
- \row
- \li no icon
- \li \l StandardIcon.NoIcon
- \li For an unadorned text alert.
- \row
- \li \inlineimage ../images/question.png "Question icon"
- \li \l StandardIcon.Question
- \li For asking a question during normal operations.
- \row
- \li \image information.png
- \li \l StandardIcon.Information
- \li For reporting information about normal operations.
- \row
- \li \image warning.png
- \li \l StandardIcon.Warning
- \li For reporting non-critical errors.
- \row
- \li \image critical.png
- \li \l StandardIcon.Critical
- \li For reporting critical errors.
- \endtable
-
- The default is \c StandardIcon.NoIcon.
-
- The enum values are the same as in \l QMessageBox::Icon.
-*/
-
-// TODO after QTBUG-35019 is fixed: fix links to this module's enums
-// rather than linking to those in QMessageBox
-/*!
- \enum QQuickStandardButton::StandardButton
-
- This enum specifies a button with a standard label to be used on a dialog.
-*/
-
-/*!
- \qmlproperty StandardButtons MessageDialog::standardButtons
-
- The MessageDialog has a row of buttons along the bottom, each of which has
- a \l {QMessageBox::ButtonRole} {ButtonRole} that determines which signal
- will be emitted when the button is pressed. You can also find out which
- specific button was pressed after the fact via the \l clickedButton
- property. You can control which buttons are available by setting
- standardButtons to a bitwise-or combination of the following flags:
-
- \table
- \row \li StandardButton.Ok \li An \gui OK button defined with the \l {QMessageBox::AcceptRole} {AcceptRole}.
- \row \li StandardButton.Open \li An \gui Open button defined with the \l {QMessageBox::AcceptRole} {AcceptRole}.
- \row \li StandardButton.Save \li A \gui Save button defined with the \l {QMessageBox::AcceptRole} {AcceptRole}.
- \row \li StandardButton.Cancel \li A \gui Cancel button defined with the \l {QMessageBox::RejectRole} {RejectRole}.
- \row \li StandardButton.Close \li A \gui Close button defined with the \l {QMessageBox::RejectRole} {RejectRole}.
- \row \li StandardButton.Discard \li A \gui Discard or \gui {Don't Save} button, depending on the platform,
- defined with the \l {QMessageBox::DestructiveRole} {DestructiveRole}.
- \row \li StandardButton.Apply \li An \gui Apply button defined with the \l {QMessageBox::ApplyRole} {ApplyRole}.
- \row \li StandardButton.Reset \li A \gui Reset button defined with the \l {QMessageBox::ResetRole} {ResetRole}.
- \row \li StandardButton.RestoreDefaults \li A \gui {Restore Defaults} button defined with the \l {QMessageBox::ResetRole} {ResetRole}.
- \row \li StandardButton.Help \li A \gui Help button defined with the \l {QMessageBox::HelpRole} {HelpRole}.
- \row \li StandardButton.SaveAll \li A \gui {Save All} button defined with the \l {QMessageBox::AcceptRole} {AcceptRole}.
- \row \li StandardButton.Yes \li A \gui Yes button defined with the \l {QMessageBox::YesRole} {YesRole}.
- \row \li StandardButton.YesToAll \li A \gui {Yes to All} button defined with the \l {QMessageBox::YesRole} {YesRole}.
- \row \li StandardButton.No \li A \gui No button defined with the \l {QMessageBox::NoRole} {NoRole}.
- \row \li StandardButton.NoToAll \li A \gui {No to All} button defined with the \l {QMessageBox::NoRole} {NoRole}.
- \row \li StandardButton.Abort \li An \gui Abort button defined with the \l {QMessageBox::RejectRole} {RejectRole}.
- \row \li StandardButton.Retry \li A \gui Retry button defined with the \l {QMessageBox::AcceptRole} {AcceptRole}.
- \row \li StandardButton.Ignore \li An \gui Ignore button defined with the \l {QMessageBox::AcceptRole} {AcceptRole}.
- \endtable
-
- For example the following dialog will ask a question with 5 possible answers:
-
- \qml
- import QtQuick 2.2
- import QtQuick.Dialogs 1.1
-
- MessageDialog {
- title: "Overwrite?"
- icon: StandardIcon.Question
- text: "file.txt already exists. Replace?"
- detailedText: "To replace a file means that its existing contents will be lost. " +
- "The file that you are copying now will be copied over it instead."
- standardButtons: StandardButton.Yes | StandardButton.YesToAll |
- StandardButton.No | StandardButton.NoToAll | StandardButton.Abort
- Component.onCompleted: visible = true
- onYes: console.log("copied")
- onNo: console.log("didn't copy")
- onRejected: console.log("aborted")
- }
- \endqml
-
- \image replacefile.png
-
- The default is \c StandardButton.Ok.
-
- The enum values are the same as in \l QMessageBox::StandardButtons.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickplatformmessagedialog_p.h b/src/imports/dialogs/qquickplatformmessagedialog_p.h
deleted file mode 100644
index 61f055bb38..0000000000
--- a/src/imports/dialogs/qquickplatformmessagedialog_p.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKPLATFORMMESSAGEDIALOG_P_H
-#define QQUICKPLATFORMMESSAGEDIALOG_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 "qquickabstractmessagedialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QQuickPlatformMessageDialog : public QQuickAbstractMessageDialog
-{
- Q_OBJECT
-
-public:
- QQuickPlatformMessageDialog(QObject *parent = 0);
- virtual ~QQuickPlatformMessageDialog();
-
-protected:
- QPlatformMessageDialogHelper *helper();
-
- Q_DISABLE_COPY(QQuickPlatformMessageDialog)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPlatformMessageDialog *)
-
-#endif // QQUICKPLATFORMMESSAGEDIALOG_P_H
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index f425eaa220..5ed38db3d7 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -96,10 +96,10 @@ void QQuickFolderListModelPrivate::init()
{
Q_Q(QQuickFolderListModel);
qRegisterMetaType<QList<FileProperty> >("QList<FileProperty>");
- q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString, QList<FileProperty>)),
- q, SLOT(_q_directoryChanged(QString, QList<FileProperty>)));
- q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString, QList<FileProperty>, int, int)),
- q, SLOT(_q_directoryUpdated(QString, QList<FileProperty>, int, int)));
+ q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString,QList<FileProperty>)),
+ q, SLOT(_q_directoryChanged(QString,QList<FileProperty>)));
+ q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString,QList<FileProperty>,int,int)),
+ q, SLOT(_q_directoryUpdated(QString,QList<FileProperty>,int,int)));
q->connect(&fileInfoThread, SIGNAL(sortFinished(QList<FileProperty>)),
q, SLOT(_q_sortFinished(QList<FileProperty>)));
q->connect(q, SIGNAL(rowCountChanged()), q, SIGNAL(countChanged()));
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 3f15755211..f1d262a6c3 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -11,11 +11,7 @@ qtHaveModule(quick) {
qtquick2 \
particles \
window \
- dialogs-private \
- dialogs \
testlib
}
qtHaveModule(xmlpatterns) : SUBDIRS += xmllistmodel
-
-qtHaveModule(quick):qtHaveModule(widgets): SUBDIRS += widgets
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 48693dbbf3..7a7649c6f1 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -101,14 +101,14 @@ V8_DEFINE_EXTENSION(QQmlSqlDatabaseData, databaseData)
class QQmlSqlDatabaseWrapper : public Object
{
- Q_MANAGED
+ V4_OBJECT
public:
enum Type { Database, Query, Rows };
QQmlSqlDatabaseWrapper(QV8Engine *e)
: Object(QV8Engine::getV4(e)), type(Database), inTransaction(false), readonly(false), forwardOnly(false)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
~QQmlSqlDatabaseWrapper() {
@@ -131,7 +131,8 @@ public:
bool forwardOnly; // type == Rows
};
-DEFINE_MANAGED_VTABLE(QQmlSqlDatabaseWrapper);
+DEFINE_REF(QQmlSqlDatabaseWrapper, Object);
+DEFINE_OBJECT_VTABLE(QQmlSqlDatabaseWrapper);
static ReturnedValue qmlsqldatabase_version(CallContext *ctx)
{
@@ -206,7 +207,7 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Eng
return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName;
}
-static ReturnedValue qmlsqldatabase_rows_index(QV4::Referenced<QQmlSqlDatabaseWrapper> r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
+static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapperRef r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
{
Scope scope(v4);
QV8Engine *v8 = v4->v8Engine;
@@ -281,7 +282,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
ScopedValue values(scope, ctx->callData->args[1]);
if (values->asArrayObject()) {
ScopedArrayObject array(scope, values);
- quint32 size = array->arrayLength();
+ quint32 size = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii)
query.bindValue(ii, engine->toVariant((v = array->getIndexed(ii)), -1));
diff --git a/src/imports/settings/qqmlsettings.cpp b/src/imports/settings/qqmlsettings.cpp
index 011a39f20c..128eb9ed38 100644
--- a/src/imports/settings/qqmlsettings.cpp
+++ b/src/imports/settings/qqmlsettings.cpp
@@ -273,6 +273,9 @@ QSettings *QQmlSettingsPrivate::instance() const
void QQmlSettingsPrivate::init()
{
if (!initialized) {
+#ifdef SETTINGS_DEBUG
+ qDebug() << "QQmlSettings: stored at" << instance()->fileName();
+#endif
load();
initialized = true;
}
diff --git a/src/imports/widgets/plugins.qmltypes b/src/imports/widgets/plugins.qmltypes
deleted file mode 100644
index a67443c5b7..0000000000
--- a/src/imports/widgets/plugins.qmltypes
+++ /dev/null
@@ -1,302 +0,0 @@
-import QtQuick.tooling 1.1
-
-// This file describes the plugin-supplied types contained in the library.
-// It is used for QML tooling purposes only.
-//
-// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtQuick.PrivateWidgets 1.1'
-
-Module {
- Component {
- name: "QQuickAbstractColorDialog"
- prototype: "QQuickAbstractDialog"
- Property { name: "showAlphaChannel"; type: "bool" }
- Property { name: "color"; type: "QColor" }
- Property { name: "currentColor"; type: "QColor" }
- Property { name: "currentHue"; type: "double"; isReadonly: true }
- Property { name: "currentSaturation"; type: "double"; isReadonly: true }
- Property { name: "currentLightness"; type: "double"; isReadonly: true }
- Property { name: "currentAlpha"; type: "double"; isReadonly: true }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setModality"
- Parameter { name: "m"; type: "Qt::WindowModality" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setColor"
- Parameter { name: "arg"; type: "QColor" }
- }
- Method {
- name: "setCurrentColor"
- Parameter { name: "currentColor"; type: "QColor" }
- }
- Method {
- name: "setShowAlphaChannel"
- Parameter { name: "arg"; type: "bool" }
- }
- }
- Component {
- name: "QQuickAbstractDialog"
- prototype: "QObject"
- Property { name: "visible"; type: "bool" }
- Property { name: "modality"; type: "Qt::WindowModality" }
- Property { name: "title"; type: "string" }
- Property { name: "isWindow"; type: "bool"; isReadonly: true }
- Property { name: "x"; type: "int" }
- Property { name: "y"; type: "int" }
- Property { name: "width"; type: "int" }
- Property { name: "height"; type: "int" }
- Signal { name: "visibilityChanged" }
- Signal { name: "geometryChanged" }
- Signal { name: "accepted" }
- Signal { name: "rejected" }
- Method { name: "open" }
- Method { name: "close" }
- Method {
- name: "setX"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setY"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setWidth"
- Parameter { name: "arg"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "arg"; type: "int" }
- }
- }
- Component {
- name: "QQuickAbstractFileDialog"
- prototype: "QQuickAbstractDialog"
- Property { name: "selectExisting"; type: "bool" }
- Property { name: "selectMultiple"; type: "bool" }
- Property { name: "selectFolder"; type: "bool" }
- Property { name: "folder"; type: "QUrl" }
- Property { name: "nameFilters"; type: "QStringList" }
- Property { name: "selectedNameFilter"; type: "string" }
- Property { name: "fileUrl"; type: "QUrl"; isReadonly: true }
- Property { name: "fileUrls"; type: "QList<QUrl>"; isReadonly: true }
- Signal { name: "filterSelected" }
- Signal { name: "fileModeChanged" }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setSelectExisting"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setSelectMultiple"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setSelectFolder"
- Parameter { name: "s"; type: "bool" }
- }
- Method {
- name: "setFolder"
- Parameter { name: "f"; type: "QUrl" }
- }
- Method {
- name: "setNameFilters"
- Parameter { name: "f"; type: "QStringList" }
- }
- Method {
- name: "selectNameFilter"
- Parameter { name: "f"; type: "string" }
- }
- }
- Component {
- name: "QQuickAbstractFontDialog"
- prototype: "QQuickAbstractDialog"
- Property { name: "scalableFonts"; type: "bool" }
- Property { name: "nonScalableFonts"; type: "bool" }
- Property { name: "monospacedFonts"; type: "bool" }
- Property { name: "proportionalFonts"; type: "bool" }
- Property { name: "font"; type: "QFont" }
- Signal { name: "selectionAccepted" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setModality"
- Parameter { name: "m"; type: "Qt::WindowModality" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "t"; type: "string" }
- }
- Method {
- name: "setFont"
- Parameter { name: "arg"; type: "QFont" }
- }
- Method {
- name: "setScalableFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setNonScalableFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setMonospacedFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- Method {
- name: "setProportionalFonts"
- Parameter { name: "arg"; type: "bool" }
- }
- }
- Component {
- name: "QQuickAbstractMessageDialog"
- prototype: "QQuickAbstractDialog"
- exports: ["QtQuick.PrivateWidgets/QtMessageDialog 1.1"]
- exportMetaObjectRevisions: [0]
- Enum {
- name: "Icon"
- values: {
- "NoIcon": 0,
- "Information": 1,
- "Warning": 2,
- "Critical": 3,
- "Question": 4
- }
- }
- Enum {
- name: "StandardButton"
- values: {
- "NoButton": 0,
- "Ok": 1024,
- "Save": 2048,
- "SaveAll": 4096,
- "Open": 8192,
- "Yes": 16384,
- "YesToAll": 32768,
- "No": 65536,
- "NoToAll": 131072,
- "Abort": 262144,
- "Retry": 524288,
- "Ignore": 1048576,
- "Close": 2097152,
- "Cancel": 4194304,
- "Discard": 8388608,
- "Help": 16777216,
- "Apply": 33554432,
- "Reset": 67108864,
- "RestoreDefaults": 134217728
- }
- }
- Enum {
- name: "StandardButtons"
- values: {
- "NoButton": 0,
- "Ok": 1024,
- "Save": 2048,
- "SaveAll": 4096,
- "Open": 8192,
- "Yes": 16384,
- "YesToAll": 32768,
- "No": 65536,
- "NoToAll": 131072,
- "Abort": 262144,
- "Retry": 524288,
- "Ignore": 1048576,
- "Close": 2097152,
- "Cancel": 4194304,
- "Discard": 8388608,
- "Help": 16777216,
- "Apply": 33554432,
- "Reset": 67108864,
- "RestoreDefaults": 134217728
- }
- }
- Property { name: "text"; type: "string" }
- Property { name: "informativeText"; type: "string" }
- Property { name: "detailedText"; type: "string" }
- Property { name: "icon"; type: "Icon" }
- Property { name: "standardIconSource"; type: "QUrl"; isReadonly: true }
- Property { name: "standardButtons"; type: "StandardButtons" }
- Property { name: "clickedButton"; type: "StandardButton"; isReadonly: true }
- Signal { name: "buttonClicked" }
- Signal { name: "discard" }
- Signal { name: "help" }
- Signal { name: "yes" }
- Signal { name: "no" }
- Signal { name: "apply" }
- Signal { name: "reset" }
- Method {
- name: "setVisible"
- Parameter { name: "v"; type: "bool" }
- }
- Method {
- name: "setTitle"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setInformativeText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setDetailedText"
- Parameter { name: "arg"; type: "string" }
- }
- Method {
- name: "setIcon"
- Parameter { name: "icon"; type: "Icon" }
- }
- Method {
- name: "setStandardButtons"
- Parameter { name: "buttons"; type: "StandardButtons" }
- }
- Method {
- name: "click"
- Parameter { name: "button"; type: "QMessageDialogOptions::StandardButton" }
- Parameter { type: "QMessageDialogOptions::ButtonRole" }
- }
- Method {
- name: "click"
- Parameter { name: "button"; type: "QQuickAbstractMessageDialog::StandardButton" }
- }
- }
- Component {
- name: "QQuickQColorDialog"
- prototype: "QQuickAbstractColorDialog"
- exports: ["QtQuick.PrivateWidgets/QtColorDialog 1.0"]
- exportMetaObjectRevisions: [0]
- }
- Component {
- name: "QQuickQFileDialog"
- prototype: "QQuickAbstractFileDialog"
- exports: ["QtQuick.PrivateWidgets/QtFileDialog 1.0"]
- exportMetaObjectRevisions: [0]
- }
- Component {
- name: "QQuickQFontDialog"
- prototype: "QQuickAbstractFontDialog"
- exports: ["QtQuick.PrivateWidgets/QtFontDialog 1.1"]
- exportMetaObjectRevisions: [0]
- }
-}
diff --git a/src/imports/widgets/qmessageboxhelper_p.h b/src/imports/widgets/qmessageboxhelper_p.h
deleted file mode 100644
index 4f1070f97d..0000000000
--- a/src/imports/widgets/qmessageboxhelper_p.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMESSAGEBOXHELPER_P_H
-#define QMESSAGEBOXHELPER_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 <QMessageBox>
-#include "../dialogs/qquickabstractmessagedialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QMessageBoxHelper : public QPlatformMessageDialogHelper
-{
- Q_OBJECT
-public:
- QMessageBoxHelper() {
- connect(&m_dialog, SIGNAL(accepted()), this, SIGNAL(accept()));
- connect(&m_dialog, SIGNAL(rejected()), this, SIGNAL(reject()));
- connect(&m_dialog, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*)));
- }
-
- virtual void exec() { m_dialog.exec(); }
-
- virtual bool show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) {
- m_dialog.winId();
- QWindow *window = m_dialog.windowHandle();
- Q_ASSERT(window);
- window->setTransientParent(parent);
- window->setFlags(f);
- m_dialog.setWindowModality(m);
- m_dialog.setWindowTitle(QPlatformMessageDialogHelper::options()->windowTitle());
- m_dialog.setIcon(static_cast<QMessageBox::Icon>(QPlatformMessageDialogHelper::options()->icon()));
- if (!QPlatformMessageDialogHelper::options()->text().isNull())
- m_dialog.setText(QPlatformMessageDialogHelper::options()->text());
- if (!QPlatformMessageDialogHelper::options()->informativeText().isNull())
- m_dialog.setInformativeText(QPlatformMessageDialogHelper::options()->informativeText());
- if (!QPlatformMessageDialogHelper::options()->detailedText().isNull())
- m_dialog.setDetailedText(QPlatformMessageDialogHelper::options()->detailedText());
- m_dialog.setStandardButtons(static_cast<QMessageBox::StandardButtons>(static_cast<int>(
- QPlatformMessageDialogHelper::options()->standardButtons())));
- m_dialog.show();
- return m_dialog.isVisible();
- }
-
- virtual void hide() { m_dialog.hide(); }
-
- QMessageBox m_dialog;
-
-public Q_SLOTS:
- void buttonClicked(QAbstractButton* button) {
- emit clicked(static_cast<QMessageDialogOptions::StandardButton>(m_dialog.standardButton(button)),
- static_cast<QMessageDialogOptions::ButtonRole>(m_dialog.buttonRole(button)));
- }
-};
-
-QT_END_NAMESPACE
-
-#endif // QMESSAGEBOXHELPER_P_H
diff --git a/src/imports/widgets/qmldir b/src/imports/widgets/qmldir
deleted file mode 100644
index da63c98e61..0000000000
--- a/src/imports/widgets/qmldir
+++ /dev/null
@@ -1,4 +0,0 @@
-module QtQuick.PrivateWidgets
-plugin widgetsplugin
-classname QtQuick2PrivateWidgetsPlugin
-typeinfo plugins.qmltypes
diff --git a/src/imports/widgets/qquickqcolordialog.cpp b/src/imports/widgets/qquickqcolordialog.cpp
deleted file mode 100644
index ee27d147e7..0000000000
--- a/src/imports/widgets/qquickqcolordialog.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickqcolordialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <private/qqmlcontext_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-#include <QColorDialog>
-
-QT_BEGIN_NAMESPACE
-
-class QColorDialogHelper : public QPlatformColorDialogHelper
-{
-public:
- QColorDialogHelper() :
- QPlatformColorDialogHelper()
- {
- connect(&m_dialog, SIGNAL(currentColorChanged(const QColor&)), this, SIGNAL(currentColorChanged(const QColor&)));
- connect(&m_dialog, SIGNAL(colorSelected(const QColor&)), this, SIGNAL(colorSelected(const QColor&)));
- connect(&m_dialog, SIGNAL(accepted()), this, SIGNAL(accept()));
- connect(&m_dialog, SIGNAL(rejected()), this, SIGNAL(reject()));
- }
-
- virtual void setCurrentColor(const QColor &c) { m_dialog.setCurrentColor(c); }
- virtual QColor currentColor() const { return m_dialog.currentColor(); }
-
- virtual void exec() { m_dialog.exec(); }
-
- virtual bool show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) {
- m_dialog.winId();
- QWindow *window = m_dialog.windowHandle();
- Q_ASSERT(window);
- window->setTransientParent(parent);
- window->setFlags(f);
- m_dialog.setWindowModality(m);
- m_dialog.setWindowTitle(QPlatformColorDialogHelper::options()->windowTitle());
- m_dialog.setOptions((QColorDialog::ColorDialogOptions)((int)(QPlatformColorDialogHelper::options()->options())));
- m_dialog.show();
- return m_dialog.isVisible();
- }
-
- virtual void hide() { m_dialog.hide(); }
-
-private:
- QColorDialog m_dialog;
-};
-
-/*!
- \qmltype QtColorDialog
- \instantiates QQuickQColorDialog
- \inqmlmodule QtQuick.PrivateWidgets 1
- \ingroup qtquick-visual
- \brief Dialog component for choosing a color.
- \since 5.1
- \internal
-
- QtColorDialog provides a means to instantiate and manage a QColorDialog.
- It is not recommended to be used directly; it is an implementation
- detail of \l ColorDialog in the \l QtQuick.Dialogs module.
-
- To use this type, you will need to import the module with the following line:
- \code
- import QtQuick.PrivateWidgets 1.0
- \endcode
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::ColorDialog::accepted
-
- The \a accepted signal is emitted when the user has finished using the
- dialog. You can then inspect the \a color property to get the selection.
-
- Example:
-
- \qml
- ColorDialog {
- onAccepted: { console.log("Selected color: " + color) }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::ColorDialog::rejected
-
- The \a rejected signal is emitted when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickQColorDialog
- \inmodule QtQuick.PrivateWidgets
- \internal
-
- \brief The QQuickQColorDialog class is a wrapper for a QColorDialog.
-
- \since 5.1
-*/
-
-/*!
- Constructs a file dialog with parent window \a parent.
-*/
-QQuickQColorDialog::QQuickQColorDialog(QObject *parent)
- : QQuickAbstractColorDialog(parent)
-{
-}
-
-/*!
- Destroys the file dialog.
-*/
-QQuickQColorDialog::~QQuickQColorDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformColorDialogHelper *QQuickQColorDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if (!m_dlgHelper) {
- m_dlgHelper = new QColorDialogHelper();
- connect(m_dlgHelper, SIGNAL(currentColorChanged(const QColor&)), this, SLOT(setCurrentColor(QColor)));
- connect(m_dlgHelper, SIGNAL(colorSelected(const QColor&)), this, SLOT(setColor(QColor)));
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- }
-
- return m_dlgHelper;
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/widgets/qquickqfiledialog.cpp b/src/imports/widgets/qquickqfiledialog.cpp
deleted file mode 100644
index 403577fabe..0000000000
--- a/src/imports/widgets/qquickqfiledialog.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickqfiledialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <private/qqmlcontext_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-#include <QFileDialog>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype QtFileDialog
- \instantiates QQuickQFileDialog
- \inqmlmodule QtQuick.PrivateWidgets 1
- \ingroup qtquick-visual
- \brief Dialog component for choosing files from a local filesystem.
- \since 5.1
- \internal
-
- QtFileDialog provides a means to instantiate and manage a QFileDialog.
- It is not recommended to be used directly; it is an implementation
- detail of \l FileDialog in the \l QtQuick.Dialogs module.
-
- To use this type, you will need to import the module with the following line:
- \code
- import QtQuick.PrivateWidgets 1.0
- \endcode
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FileDialog::accepted
-
- The \a accepted signal is emitted when the user has finished using the
- dialog. You can then inspect the \a fileUrl or \a fileUrls properties to
- get the selection.
-
- Example:
-
- \qml
- FileDialog {
- onAccepted: { console.log("Selected file: " + fileUrl) }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FileDialog::rejected
-
- The \a rejected signal is emitted when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickQFileDialog
- \inmodule QtQuick.PrivateWidgets
- \internal
-
- \brief The QQuickQFileDialog class is a wrapper for a QFileDialog.
-
- \since 5.1
-*/
-
-/*!
- Constructs a file dialog with parent window \a parent.
-*/
-QQuickQFileDialog::QQuickQFileDialog(QObject *parent)
- : QQuickAbstractFileDialog(parent)
-{
-}
-
-/*!
- Destroys the file dialog.
-*/
-QQuickQFileDialog::~QQuickQFileDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformFileDialogHelper *QQuickQFileDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if (!m_dlgHelper) {
- m_dlgHelper = new QFileDialogHelper();
- connect(m_dlgHelper, SIGNAL(directoryEntered(const QUrl &)), this, SIGNAL(folderChanged()));
- connect(m_dlgHelper, SIGNAL(filterSelected(const QString &)), this, SIGNAL(filterSelected()));
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- }
-
- return m_dlgHelper;
-}
-
-QFileDialogHelper::QFileDialogHelper() :
- QPlatformFileDialogHelper()
-{
- connect(&m_dialog, SIGNAL(currentChanged(const QString&)), this, SLOT(currentChanged(const QString&)));
- connect(&m_dialog, SIGNAL(directoryEntered(const QString&)), this, SLOT(directoryEntered(const QString&)));
- connect(&m_dialog, SIGNAL(fileSelected(const QString&)), this, SLOT(fileSelected(const QString&)));
- connect(&m_dialog, SIGNAL(filesSelected(const QStringList&)), this, SLOT(filesSelected(const QStringList&)));
- connect(&m_dialog, SIGNAL(filterSelected(const QString&)), this, SIGNAL(filterSelected(const QString&)));
- connect(&m_dialog, SIGNAL(accepted()), this, SIGNAL(accept()));
- connect(&m_dialog, SIGNAL(rejected()), this, SIGNAL(reject()));
-}
-
-QList<QUrl> QFileDialogHelper::selectedFiles() const
-{
- return m_dialog.selectedUrls();
-}
-
-void QFileDialogHelper::setFilter() {
- m_dialog.setWindowTitle(QPlatformFileDialogHelper::options()->windowTitle());
- if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::LookIn))
- m_dialog.setLabelText(m_dialog.LookIn, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::LookIn));
- if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::FileName))
- m_dialog.setLabelText(m_dialog.FileName, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::FileName));
- if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::FileType))
- m_dialog.setLabelText(m_dialog.FileType, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::FileType));
- if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::Accept))
- m_dialog.setLabelText(m_dialog.Accept, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::Accept));
- if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::Reject))
- m_dialog.setLabelText(m_dialog.Reject, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::Reject));
- m_dialog.setFilter(QPlatformFileDialogHelper::options()->filter());
- m_dialog.setNameFilters(QPlatformFileDialogHelper::options()->nameFilters());
- m_dialog.selectNameFilter(QPlatformFileDialogHelper::options()->initiallySelectedNameFilter());
- m_dialog.setFileMode(QFileDialog::FileMode(QPlatformFileDialogHelper::options()->fileMode()));
- m_dialog.setOptions((QFileDialog::Options)((int)(QPlatformFileDialogHelper::options()->options())));
- m_dialog.setAcceptMode(QFileDialog::AcceptMode(QPlatformFileDialogHelper::options()->acceptMode()));
-
- const QUrl initialDirectory = QPlatformFileDialogHelper::options()->initialDirectory();
- if (initialDirectory.isValid() && initialDirectory.isLocalFile())
- m_dialog.setDirectory(initialDirectory.toLocalFile());
-}
-
-bool QFileDialogHelper::show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) {
- m_dialog.winId();
- QWindow *window = m_dialog.windowHandle();
- Q_ASSERT(window);
- window->setTransientParent(parent);
- window->setFlags(f);
- m_dialog.setWindowModality(m);
- m_dialog.show();
- return m_dialog.isVisible();
-}
-
-void QFileDialogHelper::currentChanged(const QString& path)
-{
- emit QPlatformFileDialogHelper::currentChanged(QUrl::fromLocalFile(path));
-}
-
-void QFileDialogHelper::directoryEntered(const QString& path)
-{
- emit QPlatformFileDialogHelper::directoryEntered(QUrl::fromLocalFile(path));
-}
-
-void QFileDialogHelper::fileSelected(const QString& path)
-{
- emit QPlatformFileDialogHelper::fileSelected(QUrl::fromLocalFile(path));
-}
-
-void QFileDialogHelper::filesSelected(const QStringList& paths)
-{
- QList<QUrl> pathUrls;
- foreach (const QString &path, paths)
- pathUrls << QUrl::fromLocalFile(path);
- emit QPlatformFileDialogHelper::filesSelected(pathUrls);
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/widgets/qquickqfontdialog.cpp b/src/imports/widgets/qquickqfontdialog.cpp
deleted file mode 100644
index 6d637e1ddb..0000000000
--- a/src/imports/widgets/qquickqfontdialog.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQuick.Dialogs 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickqfontdialog_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <private/qqmlcontext_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-#include <QFontDialog>
-
-QT_BEGIN_NAMESPACE
-
-class QFontDialogHelper : public QPlatformFontDialogHelper
-{
-public:
- QFontDialogHelper() :
- QPlatformFontDialogHelper()
- {
- connect(&m_dialog, SIGNAL(currentFontChanged(const QFont &)), this, SIGNAL(currentFontChanged(const QFont &)));
- connect(&m_dialog, SIGNAL(fontSelected(const QFont &)), this, SIGNAL(fontSelected(const QFont &)));
- connect(&m_dialog, SIGNAL(accepted()), this, SIGNAL(accept()));
- connect(&m_dialog, SIGNAL(rejected()), this, SIGNAL(reject()));
- }
-
- virtual void setCurrentFont(const QFont &font) { m_dialog.setCurrentFont(font); }
- virtual QFont currentFont() const { return m_dialog.currentFont(); }
-
- virtual void exec() { m_dialog.exec(); }
-
- virtual bool show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) {
- m_dialog.winId();
- QWindow *window = m_dialog.windowHandle();
- Q_ASSERT(window);
- window->setTransientParent(parent);
- window->setFlags(f);
- m_dialog.windowHandle()->setTransientParent(parent);
- m_dialog.windowHandle()->setFlags(f);
- m_dialog.setWindowModality(m);
- m_dialog.setWindowTitle(QPlatformFontDialogHelper::options()->windowTitle());
- m_dialog.setOptions((QFontDialog::FontDialogOptions)((int)(QPlatformFontDialogHelper::options()->options())));
- m_dialog.show();
- return m_dialog.isVisible();
- }
-
- virtual void hide() { m_dialog.hide(); }
-
-private:
- QFontDialog m_dialog;
-};
-
-/*!
- \qmltype QtFontDialog
- \instantiates QQuickQFontDialog
- \inqmlmodule QtQuick.PrivateWidgets 1
- \ingroup qtquick-visual
- \brief Dialog component for choosing files from a local filesystem.
- \since 5.2
- \internal
-
- QtFontDialog provides a means to instantiate and manage a QFontDialog.
- It is not recommended to be used directly; it is an implementation
- detail of \l FontDialog in the \l QtQuick.Dialogs module.
-
- To use this type, you will need to import the module with the following line:
- \code
- import QtQuick.PrivateWidgets 1.1
- \endcode
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FontDialog::accepted
-
- The \a accepted signal is emitted when the user has finished using the
- dialog. You can then inspect the \a filePath or \a filePaths properties to
- get the selection.
-
- Example:
-
- \qml
- FontDialog {
- onAccepted: { console.log("Selected file: " + filePath) }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::FontDialog::rejected
-
- The \a rejected signal is emitted when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickQFontDialog
- \inmodule QtQuick.PrivateWidgets
- \internal
-
- \brief The QQuickQFontDialog class is a wrapper for a QFontDialog.
-
- \since 5.2
-*/
-
-/*!
- Constructs a file dialog with parent window \a parent.
-*/
-QQuickQFontDialog::QQuickQFontDialog(QObject *parent)
- : QQuickAbstractFontDialog(parent)
-{
-}
-
-/*!
- Destroys the file dialog.
-*/
-QQuickQFontDialog::~QQuickQFontDialog()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformFontDialogHelper *QQuickQFontDialog::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if (!m_dlgHelper) {
- m_dlgHelper = new QFontDialogHelper();
- connect(m_dlgHelper, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(setFont(const QFont &)));
- connect(m_dlgHelper, SIGNAL(fontSelected(const QFont &)), this, SLOT(setFont(const QFont &)));
- connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
- connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
- }
-
- return m_dlgHelper;
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/widgets/qquickqmessagebox.cpp b/src/imports/widgets/qquickqmessagebox.cpp
deleted file mode 100644
index 1b92efc5ef..0000000000
--- a/src/imports/widgets/qquickqmessagebox.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickqmessagebox_p.h"
-#include "qmessageboxhelper_p.h"
-#include "qquickitem.h"
-
-#include <private/qguiapplication_p.h>
-#include <private/qqmlcontext_p.h>
-#include <QWindow>
-#include <QQuickWindow>
-#include <QMessageBox>
-#include <QAbstractButton>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype QtMessageDialog
- \instantiates QQuickQMessageBox
- \inqmlmodule QtQuick.PrivateWidgets 1
- \ingroup qtquick-visual
- \brief Dialog component for choosing a color.
- \since 5.2
- \internal
-
- QtMessageDialog provides a means to instantiate and manage a QMessageBox.
- It is not recommended to be used directly; it is an implementation
- detail of \l MessageDialog in the \l QtQuick.Dialogs module.
-
- To use this type, you will need to import the module with the following line:
- \code
- import QtQuick.PrivateWidgets 1.1
- \endcode
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::MessageDialog::accepted
-
- The \a accepted signal is emitted when the user has pressed the OK button
- on the dialog.
-
- Example:
-
- \qml
- MessageDialog {
- onAccepted: { console.log("accepted") }
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick::Dialogs::MessageDialog::rejected
-
- The \a rejected signal is emitted when the user has dismissed the dialog,
- either by closing the dialog window or by pressing the Cancel button.
-*/
-
-/*!
- \class QQuickQMessageBox
- \inmodule QtQuick.PrivateWidgets
- \internal
-
- \brief The QQuickQMessageBox class is a wrapper for a QMessageBox.
-
- \since 5.2
-*/
-
-/*!
- Constructs a message dialog with parent window \a parent.
-*/
-QQuickQMessageBox::QQuickQMessageBox(QObject *parent)
- : QQuickAbstractMessageDialog(parent)
-{
-}
-
-/*!
- Destroys the message dialog.
-*/
-QQuickQMessageBox::~QQuickQMessageBox()
-{
- if (m_dlgHelper)
- m_dlgHelper->hide();
- delete m_dlgHelper;
-}
-
-QPlatformDialogHelper *QQuickQMessageBox::helper()
-{
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
- if (parentItem)
- m_parentWindow = parentItem->window();
-
- if (!QQuickAbstractMessageDialog::m_dlgHelper) {
- QMessageBoxHelper* helper = new QMessageBoxHelper();
- QQuickAbstractMessageDialog::m_dlgHelper = helper;
- // accept() shouldn't be emitted. reject() happens only if the dialog is
- // dismissed by closing the window rather than by one of its button widgets.
- connect(helper, SIGNAL(accept()), this, SLOT(accept()));
- connect(helper, SIGNAL(reject()), this, SLOT(reject()));
- connect(helper, SIGNAL(clicked(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole)),
- this, SLOT(click(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole)));
- }
-
- return QQuickAbstractMessageDialog::m_dlgHelper;
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/widgets/widgets.pro b/src/imports/widgets/widgets.pro
deleted file mode 100644
index 5320838082..0000000000
--- a/src/imports/widgets/widgets.pro
+++ /dev/null
@@ -1,32 +0,0 @@
-CXX_MODULE = qml
-TARGET = widgetsplugin
-TARGETPATH = QtQuick/PrivateWidgets
-IMPORT_VERSION = 1.1
-
-SOURCES += \
- qquickqmessagebox.cpp \
- ../dialogs/qquickabstractmessagedialog.cpp \
- qquickqfiledialog.cpp \
- ../dialogs/qquickabstractfiledialog.cpp \
- qquickqcolordialog.cpp \
- ../dialogs/qquickabstractcolordialog.cpp \
- qquickqfontdialog.cpp \
- ../dialogs/qquickabstractfontdialog.cpp \
- ../dialogs/qquickabstractdialog.cpp \
- widgetsplugin.cpp
-
-HEADERS += \
- qquickqmessagebox_p.h \
- qmessageboxhelper_p.h \
- ../dialogs/qquickabstractmessagedialog_p.h \
- qquickqfiledialog_p.h \
- ../dialogs/qquickabstractfiledialog_p.h \
- qquickqcolordialog_p.h \
- ../dialogs/qquickabstractcolordialog_p.h \
- qquickqfontdialog_p.h \
- ../dialogs/qquickabstractfontdialog_p.h \
- ../dialogs/qquickabstractdialog_p.h
-
-QT += quick-private gui-private core-private qml-private widgets
-
-load(qml_plugin)
diff --git a/src/imports/widgets/widgetsplugin.cpp b/src/imports/widgets/widgetsplugin.cpp
deleted file mode 100644
index 05c3a5e86c..0000000000
--- a/src/imports/widgets/widgetsplugin.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtQml/qqmlextensionplugin.h>
-#include <QtQml/qqml.h>
-#include "qquickqmessagebox_p.h"
-#include "qquickqfiledialog_p.h"
-#include "qquickqcolordialog_p.h"
-#include "qquickqfontdialog_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlmodule QtQuick.PrivateWidgets 1
- \title QWidget QML Types
- \ingroup qmlmodules
- \brief Provides QML types for certain QWidgets
- \internal
-
- This QML module contains types which should not be depended upon in Qt Quick
- applications, but are available if the Widgets module is linked. It is
- recommended to load components from this module conditionally, if at all,
- and to provide fallback implementations in case they fail to load.
-
- \code
- import QtQuick.PrivateWidgets 1.1
- \endcode
-
- \since 5.1
-*/
-
-class QtQuick2PrivateWidgetsPlugin : public QQmlExtensionPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
-
-public:
- virtual void registerTypes(const char *uri)
- {
- Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.PrivateWidgets"));
-
- qmlRegisterType<QQuickQMessageBox>(uri, 1, 1, "QtMessageDialog");
- qmlRegisterType<QQuickQFileDialog>(uri, 1, 0, "QtFileDialog");
- qmlRegisterType<QQuickQColorDialog>(uri, 1, 0, "QtColorDialog");
- qmlRegisterType<QQuickQFontDialog>(uri, 1, 1, "QtFontDialog");
- }
-};
-
-QT_END_NAMESPACE
-
-#include "widgetsplugin.moc"
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
index 97dc3aba1f..0b9be3105b 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
@@ -44,7 +44,7 @@
#include <qqmlcontext.h>
#include <private/qqmlengine_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
@@ -925,10 +925,12 @@ QQmlV4Handle QQuickXmlListModel::get(int index) const
ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
Scope scope(v4engine);
Scoped<Object> o(scope, v4engine->newObject());
+ ScopedString name(scope);
+ ScopedValue value(scope);
for (int ii = 0; ii < d->roleObjects.count(); ++ii) {
- ScopedString name(scope, v4engine->newIdentifier(d->roleObjects[ii]->name()));
- Property *p = o->insertMember(name, PropertyAttributes());
- p->value = v8engine->fromVariant(d->data.value(ii).value(index));
+ name = v4engine->newIdentifier(d->roleObjects[ii]->name());
+ value = v8engine->fromVariant(d->data.value(ii).value(index));
+ o->insertMember(name, value);
}
return QQmlV4Handle(o);
diff --git a/src/particles/qquickitemparticle.cpp b/src/particles/qquickitemparticle.cpp
index 728da57212..53aa9a9926 100644
--- a/src/particles/qquickitemparticle.cpp
+++ b/src/particles/qquickitemparticle.cpp
@@ -237,11 +237,12 @@ void QQuickItemParticle::prepareNextFrame()
//TODO: Size, better fade?
foreach (const QString &str, m_groups){
- int gIdx = m_system->groupIds[str];
- int count = m_system->groupData[gIdx]->size();
+ const int gIdx = m_system->groupIds[str];
+ const QVector<QQuickParticleData*> dataVector = m_system->groupData.value(gIdx)->data;
+ const int count = dataVector.size();
for (int i=0; i<count; i++){
- QQuickParticleData* data = m_system->groupData[gIdx]->data[i];
+ QQuickParticleData* data = dataVector.at(i);
QQuickItem* item = data->delegate;
if (!item)
continue;
diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp
index d0e9a392d4..1d7b7abd9c 100644
--- a/src/particles/qquickv4particledata.cpp
+++ b/src/particles/qquickv4particledata.cpp
@@ -273,11 +273,11 @@ QT_BEGIN_NAMESPACE
//### Particle data handles are not locked to within certain scopes like QQuickContext2D, but there's no way to reload either...
struct QV4ParticleData : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
QV4ParticleData(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
: Object(engine)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
this->datum = datum;
}
@@ -287,7 +287,7 @@ struct QV4ParticleData : public QV4::Object
{ that->as<QV4ParticleData>()->~QV4ParticleData(); }
};
-DEFINE_MANAGED_VTABLE(QV4ParticleData);
+DEFINE_OBJECT_VTABLE(QV4ParticleData);
class QV8ParticleDataDeletable : public QV8Engine::Deletable
{
diff --git a/src/particles/qquickv4particledata_p.h b/src/particles/qquickv4particledata_p.h
index b3614f94ff..10e9ecacc5 100644
--- a/src/particles/qquickv4particledata_p.h
+++ b/src/particles/qquickv4particledata_p.h
@@ -44,7 +44,7 @@
#include <private/qv8engine_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.cpp b/src/plugins/accessible/quick/qaccessiblequickitem.cpp
index 3521d4f98e..4b68574149 100644
--- a/src/plugins/accessible/quick/qaccessiblequickitem.cpp
+++ b/src/plugins/accessible/quick/qaccessiblequickitem.cpp
@@ -152,52 +152,24 @@ QList<QQuickItem *> QAccessibleQuickItem::childItems() const
QAccessible::State QAccessibleQuickItem::state() const
{
- QAccessible::State state;
+ QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item());
+ if (!attached)
+ return QAccessible::State();
- if (item()->hasActiveFocus()) {
- state.focusable = true;
- state.focused = true;
- }
-
- if (item()->activeFocusOnTab())
- state.focusable = true;
+ QAccessible::State st = attached->state();
if (!item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
- state.invisible = true;
+ st.invisible = true;
- QAccessible::Role r = role();
- switch (r) {
- case QAccessible::Button: {
- state.focusable = true;
- QVariant checkable = item()->property("checkable");
- if (!checkable.toBool())
- break;
- // fall through
- }
- case QAccessible::CheckBox:
- case QAccessible::RadioButton: {
- state.focusable = true;
- state.checkable = true;
- state.checked = item()->property("checked").toBool();
- break;
- }
- case QAccessible::MenuItem:
- case QAccessible::PageTab:
- case QAccessible::EditableText:
- case QAccessible::SpinBox:
- case QAccessible::Terminal:
- case QAccessible::ScrollBar:
- state.focusable = true;
- break;
- case QAccessible::ComboBox:
- state.focusable = true;
- state.editable = item()->property("editable").toBool();
- break;
- default:
- break;
- }
+ if (item()->activeFocusOnTab())
+ st.focusable = true;
+ if (item()->hasActiveFocus())
+ st.focused = true;
+
+ if (role() == QAccessible::ComboBox)
+ st.editable = item()->property("editable").toBool();
- return state;
+ return st;
}
QAccessible::Role QAccessibleQuickItem::role() const
diff --git a/src/plugins/accessible/shared/qqmlaccessible.cpp b/src/plugins/accessible/shared/qqmlaccessible.cpp
index d08f9bdb2c..ecf4e56acf 100644
--- a/src/plugins/accessible/shared/qqmlaccessible.cpp
+++ b/src/plugins/accessible/shared/qqmlaccessible.cpp
@@ -185,7 +185,7 @@ void QQmlAccessible::doAction(const QString &actionName)
// use the "stepSize" property on the item
if (QAccessibleValueInterface *valueIface = valueInterface()) {
QVariant valueV = valueIface->currentValue();
- qreal newValue = valueV.toInt();
+ qreal newValue = valueV.toReal();
QVariant stepSizeV = object()->property("stepSize");
qreal stepSize = stepSizeV.isValid() ? stepSizeV.toReal() : qreal(1.0);
diff --git a/src/plugins/qmltooling/shared/qpacketprotocol.cpp b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
index 0792dadfe3..7de5a7648e 100644
--- a/src/plugins/qmltooling/shared/qpacketprotocol.cpp
+++ b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
@@ -237,7 +237,7 @@ QPacketProtocol::~QPacketProtocol()
/*!
Returns the maximum packet size allowed. By default this is
2,147,483,647 bytes.
-
+
If a packet claiming to be larger than the maximum packet size is received,
the QPacketProtocol::invalidPacket() signal is emitted.
diff --git a/src/qml/animations/animations.pri b/src/qml/animations/animations.pri
index 01ac25af46..a379692567 100644
--- a/src/qml/animations/animations.pri
+++ b/src/qml/animations/animations.pri
@@ -5,6 +5,7 @@ HEADERS += \
$$PWD/qanimationgroupjob_p.h \
$$PWD/qsequentialanimationgroupjob_p.h \
$$PWD/qparallelanimationgroupjob_p.h \
+ $$PWD/qcontinuinganimationgroupjob_p.h \
$$PWD/qpauseanimationjob_p.h \
$$PWD/qanimationjobutil_p.h
@@ -13,4 +14,5 @@ SOURCES += \
$$PWD/qanimationgroupjob.cpp \
$$PWD/qsequentialanimationgroupjob.cpp \
$$PWD/qparallelanimationgroupjob.cpp \
+ $$PWD/qcontinuinganimationgroupjob.cpp \
$$PWD/qpauseanimationjob.cpp
diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp
index d9e3aff5a4..7fd72d97d2 100644
--- a/src/qml/animations/qabstractanimationjob.cpp
+++ b/src/qml/animations/qabstractanimationjob.cpp
@@ -59,7 +59,7 @@ QAnimationJobChangeListener::~QAnimationJobChangeListener()
}
QQmlAnimationTimer::QQmlAnimationTimer() :
- QAbstractAnimationTimer(), lastTick(0), lastDelta(0),
+ QAbstractAnimationTimer(), lastTick(0),
currentAnimationIdx(0), insideTick(false),
startAnimationPending(false), stopTimerPending(false),
runningLeafAnimations(0)
@@ -103,7 +103,6 @@ void QQmlAnimationTimer::updateAnimationsTime(qint64 delta)
return;
lastTick += delta;
- lastDelta = delta;
//we make sure we only call update time if the time has actually changed
//it might happen in some cases that the time doesn't change because events are delayed
@@ -142,8 +141,7 @@ void QQmlAnimationTimer::startAnimations()
{
startAnimationPending = false;
//force timer to update, which prevents large deltas for our newly added animations
- if (!animations.isEmpty())
- QUnifiedTimer::instance()->maybeUpdateAnimationsToCurrentTime();
+ QUnifiedTimer::instance()->maybeUpdateAnimationsToCurrentTime();
//we transfer the waiting animations into the "really running" state
animations += animationsToStart;
@@ -155,12 +153,11 @@ void QQmlAnimationTimer::startAnimations()
void QQmlAnimationTimer::stopTimer()
{
stopTimerPending = false;
- if (animations.isEmpty()) {
+ if (animations.isEmpty() && !startAnimationPending) {
QUnifiedTimer::resumeAnimationTimer(this);
QUnifiedTimer::stopAnimationTimer(this);
// invalidate the start reference time
lastTick = 0;
- lastDelta = 0;
}
}
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h
index d50bc4d849..e8745c8c92 100644
--- a/src/qml/animations/qabstractanimationjob_p.h
+++ b/src/qml/animations/qabstractanimationjob_p.h
@@ -209,8 +209,6 @@ public:
void restartAnimationTimer();
void updateAnimationsTime(qint64 timeStep);
- int currentDelta() { return lastDelta; }
-
//useful for profiling/debugging
int runningAnimationCount() { return animations.count(); }
@@ -220,7 +218,6 @@ private Q_SLOTS:
private:
qint64 lastTick;
- int lastDelta;
int currentAnimationIdx;
bool insideTick;
bool startAnimationPending;
diff --git a/src/qml/animations/qcontinuinganimationgroupjob.cpp b/src/qml/animations/qcontinuinganimationgroupjob.cpp
new file mode 100644
index 0000000000..eb54b6e9aa
--- /dev/null
+++ b/src/qml/animations/qcontinuinganimationgroupjob.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd.
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qcontinuinganimationgroupjob_p.h"
+#include "private/qanimationjobutil_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QContinuingAnimationGroupJob::QContinuingAnimationGroupJob()
+ : QAnimationGroupJob()
+{
+}
+
+QContinuingAnimationGroupJob::~QContinuingAnimationGroupJob()
+{
+}
+
+void QContinuingAnimationGroupJob::updateCurrentTime(int /*currentTime*/)
+{
+ if (!firstChild())
+ return;
+
+ for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) {
+ if (animation->state() == state()) {
+ RETURN_IF_DELETED(animation->setCurrentTime(m_currentTime));
+ }
+ }
+}
+
+void QContinuingAnimationGroupJob::updateState(QAbstractAnimationJob::State newState,
+ QAbstractAnimationJob::State oldState)
+{
+ QAnimationGroupJob::updateState(newState, oldState);
+
+ switch (newState) {
+ case Stopped:
+ for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling())
+ animation->stop();
+ break;
+ case Paused:
+ for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling())
+ if (animation->isRunning())
+ animation->pause();
+ break;
+ case Running:
+ for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) {
+ resetUncontrolledAnimationFinishTime(animation);
+ animation->setDirection(m_direction);
+ animation->start();
+ }
+ break;
+ }
+}
+
+void QContinuingAnimationGroupJob::updateDirection(QAbstractAnimationJob::Direction direction)
+{
+ if (!isStopped()) {
+ for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) {
+ animation->setDirection(direction);
+ }
+ }
+}
+
+void QContinuingAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimationJob *animation)
+{
+ Q_ASSERT(animation && (animation->duration() == -1));
+ int uncontrolledRunningCount = 0;
+
+ for (QAbstractAnimationJob *child = firstChild(); child; child = child->nextSibling()) {
+ if (child == animation)
+ setUncontrolledAnimationFinishTime(animation, animation->currentTime());
+ else if (uncontrolledAnimationFinishTime(child) == -1)
+ ++uncontrolledRunningCount;
+ }
+
+ if (uncontrolledRunningCount > 0)
+ return;
+
+ setUncontrolledAnimationFinishTime(this, currentTime());
+ stop();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/imports/widgets/qquickqfontdialog_p.h b/src/qml/animations/qcontinuinganimationgroupjob_p.h
index 6efd15995b..7578ab9709 100644
--- a/src/imports/widgets/qquickqfontdialog_p.h
+++ b/src/qml/animations/qcontinuinganimationgroupjob_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Jolla Ltd.
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,40 +39,29 @@
**
****************************************************************************/
-#ifndef QQUICKQFONTDIALOG_P_H
-#define QQUICKQFONTDIALOG_P_H
+#ifndef QCONTINUINGANIMATIONGROUPJOB_P_H
+#define QCONTINUINGANIMATIONGROUPJOB_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 "../dialogs/qquickabstractfontdialog_p.h"
+#include "private/qanimationgroupjob_p.h"
QT_BEGIN_NAMESPACE
-class QQuickQFontDialog : public QQuickAbstractFontDialog
+class Q_QML_PRIVATE_EXPORT QContinuingAnimationGroupJob : public QAnimationGroupJob
{
- Q_OBJECT
-
+ Q_DISABLE_COPY(QContinuingAnimationGroupJob)
public:
- QQuickQFontDialog(QObject *parent = 0);
- virtual ~QQuickQFontDialog();
+ QContinuingAnimationGroupJob();
+ ~QContinuingAnimationGroupJob();
-protected:
- QPlatformFontDialogHelper *helper();
+ int duration() const { return -1; }
- Q_DISABLE_COPY(QQuickQFontDialog)
+protected:
+ void updateCurrentTime(int currentTime);
+ void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
+ void updateDirection(QAbstractAnimationJob::Direction direction);
+ void uncontrolledAnimationFinished(QAbstractAnimationJob *animation);
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickQFontDialog *)
-
-#endif // QQUICKQFONTDIALOG_P_H
+#endif // QCONTINUINGANIMATIONGROUPJOB_P_H
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index df4f5e8dc3..24379ca5f3 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -1,5 +1,3 @@
-include(../../3rdparty/masm/masm-defs.pri)
-
INCLUDEPATH += $$PWD
INCLUDEPATH += $$OUT_PWD
@@ -13,9 +11,8 @@ HEADERS += \
$$PWD/qv4isel_moth_p.h \
$$PWD/qv4isel_util_p.h \
$$PWD/qv4ssa_p.h \
- $$PWD/qv4regalloc_p.h \
$$PWD/qqmlcodegenerator_p.h \
- $$PWD/qv4isel_masm_p.h
+ $$PWD/qqmltypecompiler_p.h
SOURCES += \
$$PWD/qv4compileddata.cpp \
@@ -26,8 +23,5 @@ SOURCES += \
$$PWD/qv4isel_p.cpp \
$$PWD/qv4jsir.cpp \
$$PWD/qv4ssa.cpp \
- $$PWD/qv4regalloc.cpp \
$$PWD/qqmlcodegenerator.cpp \
- $$PWD/qv4isel_masm.cpp
-
-include(../../3rdparty/masm/masm.pri)
+ $$PWD/qqmltypecompiler.cpp
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 13b23fde68..583cd110c9 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -54,6 +54,8 @@
QT_USE_NAMESPACE
+static const quint32 emptyStringIndex = 0;
+
DEFINE_BOOL_CONFIG_OPTION(lookupHints, QML_LOOKUP_HINTS);
using namespace QtQml;
@@ -64,6 +66,22 @@ using namespace QtQml;
return false; \
}
+void QmlObject::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &loc)
+{
+ inheritedTypeNameIndex = typeNameIndex;
+
+ location.line = loc.startLine;
+ location.column = loc.startColumn;
+
+ idIndex = id;
+ indexOfDefaultProperty = -1;
+ properties = pool->New<PoolList<QmlProperty> >();
+ qmlSignals = pool->New<PoolList<Signal> >();
+ bindings = pool->New<PoolList<Binding> >();
+ functions = pool->New<PoolList<Function> >();
+ declarationsOverride = 0;
+}
+
void QmlObject::dump(DebugStream &out)
{
out << inheritedTypeNameIndex << " {" << endl;
@@ -73,6 +91,95 @@ void QmlObject::dump(DebugStream &out)
out << "}" << endl;
}
+QString QmlObject::sanityCheckFunctionNames(const QList<CompiledFunctionOrExpression> &allFunctions, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation)
+{
+ QSet<int> functionNames;
+ for (Function *f = functions->first; f; f = f->next) {
+ QQmlJS::AST::FunctionDeclaration *function = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(allFunctions.at(f->index).node);
+ Q_ASSERT(function);
+ *errorLocation = function->identifierToken;
+ QString name = function->name.toString();
+ if (functionNames.contains(f->nameIndex))
+ return tr("Duplicate method name");
+ functionNames.insert(f->nameIndex);
+ if (signalNames.contains(f->nameIndex))
+ return tr("Duplicate method name");
+
+ if (name.at(0).isUpper())
+ return tr("Method names cannot begin with an upper case letter");
+ if (illegalNames.contains(name))
+ return tr("Illegal method name");
+ }
+ return QString(); // no error
+}
+
+QString QmlObject::appendSignal(Signal *signal)
+{
+ QmlObject *target = declarationsOverride;
+ if (!target)
+ target = this;
+ if (target->signalNames.contains(signal->nameIndex))
+ return tr("Duplicate signal name");
+ target->signalNames.insert(signal->nameIndex);
+ target->qmlSignals->append(signal);
+ return QString(); // no error
+}
+
+QString QmlObject::appendProperty(QmlProperty *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation)
+{
+ QmlObject *target = declarationsOverride;
+ if (!target)
+ target = this;
+
+ if (target->propertyNames.contains(prop->nameIndex))
+ return tr("Duplicate property name");
+
+ if (propertyName.constData()->isUpper())
+ return tr("Property names cannot begin with an upper case letter");
+
+ target->propertyNames.insert(prop->nameIndex);
+
+ const int index = target->properties->append(prop);
+ if (isDefaultProperty) {
+ if (target->indexOfDefaultProperty != -1) {
+ *errorLocation = defaultToken;
+ return tr("Duplicate default property");
+ }
+ target->indexOfDefaultProperty = index;
+ }
+ return QString(); // no error
+}
+
+void QmlObject::appendFunction(QtQml::Function *f)
+{
+ QmlObject *target = declarationsOverride;
+ if (!target)
+ target = this;
+ target->functions->append(f);
+}
+
+QString QmlObject::appendBinding(Binding *b, bool isListBinding)
+{
+ const bool bindingToDefaultProperty = (b->propertyNameIndex == 0);
+ if (!isListBinding && !bindingToDefaultProperty
+ && b->type != QV4::CompiledData::Binding::Type_GroupProperty
+ && b->type != QV4::CompiledData::Binding::Type_AttachedProperty
+ && !(b->flags & QV4::CompiledData::Binding::IsOnAssignment)) {
+ if (bindingNames.contains(b->propertyNameIndex))
+ return tr("Property value set multiple times");
+ bindingNames.insert(b->propertyNameIndex);
+ }
+ if (isListBinding) {
+ bindings->append(b);
+ } else if (bindingToDefaultProperty) {
+ Binding *insertionPoint = bindings->findSortedInsertionPoint<QV4::CompiledData::Location, QV4::CompiledData::Binding, &QV4::CompiledData::Binding::location>(b);
+ bindings->insertAfter(insertionPoint, b);
+ } else {
+ bindings->prepend(b);
+ }
+ return QString(); // no error
+}
+
QStringList Signal::parameterStringList(const QStringList &stringPool) const
{
QStringList result;
@@ -82,8 +189,10 @@ QStringList Signal::parameterStringList(const QStringList &stringPool) const
return result;
}
-QQmlCodeGenerator::QQmlCodeGenerator()
- : _object(0)
+QQmlCodeGenerator::QQmlCodeGenerator(const QSet<QString> &illegalNames)
+ : illegalNames(illegalNames)
+ , _object(0)
+ , _propertyDeclaration(0)
, jsGenerator(0)
{
}
@@ -91,7 +200,7 @@ QQmlCodeGenerator::QQmlCodeGenerator()
bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, const QString &urlString, ParsedQML *output)
{
this->url = url;
- AST::UiProgram *program = 0;
+ QQmlJS::AST::UiProgram *program = 0;
{
QQmlJS::Lexer lexer(&output->jsParserEngine);
lexer.setCode(code, /*line = */ 1);
@@ -101,7 +210,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
if (! parser.parse() || !parser.diagnosticMessages().isEmpty()) {
// Extract errors from the parser
- foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+ foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
if (m.isWarning()) {
qWarning("%s:%d : %s", qPrintable(urlString), m.loc.startLine, qPrintable(m.message));
@@ -132,7 +241,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
this->pool = output->jsParserEngine.pool();
this->jsGenerator = &output->jsGenerator;
- emptyStringIndex = registerString(QString());
+ Q_ASSERT(registerString(QString()) == emptyStringIndex);
sourceCode = code;
@@ -141,14 +250,14 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
if (program->members->next) {
QQmlError error;
error.setDescription(QCoreApplication::translate("QQmlParser", "Unexpected object definition"));
- AST::SourceLocation loc = program->members->next->firstSourceLocation();
+ QQmlJS::AST::SourceLocation loc = program->members->next->firstSourceLocation();
error.setLine(loc.startLine);
error.setColumn(loc.startColumn);
errors << error;
return false;
}
- AST::UiObjectDefinition *rootObject = AST::cast<AST::UiObjectDefinition*>(program->members->member);
+ QQmlJS::AST::UiObjectDefinition *rootObject = QQmlJS::AST::cast<QQmlJS::AST::UiObjectDefinition*>(program->members->member);
Q_ASSERT(rootObject);
output->indexOfRootObject = defineQMLObject(rootObject);
@@ -176,18 +285,18 @@ bool QQmlCodeGenerator::isSignalPropertyName(const QString &name)
return false; // consists solely of underscores - invalid.
}
-bool QQmlCodeGenerator::visit(AST::UiArrayMemberList *ast)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiArrayMemberList *ast)
{
- return AST::Visitor::visit(ast);
+ return QQmlJS::AST::Visitor::visit(ast);
}
-bool QQmlCodeGenerator::visit(AST::UiProgram *)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiProgram *)
{
Q_ASSERT(!"should not happen");
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiObjectDefinition *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiObjectDefinition *node)
{
// The grammar can't distinguish between two different definitions here:
// Item { ... }
@@ -197,7 +306,7 @@ bool QQmlCodeGenerator::visit(AST::UiObjectDefinition *node)
// and the latter is a binding to the font property with no type name but
// only initializer.
- AST::UiQualifiedId *lastId = node->qualifiedTypeNameId;
+ QQmlJS::AST::UiQualifiedId *lastId = node->qualifiedTypeNameId;
while (lastId->next)
lastId = lastId->next;
bool isType = lastId->name.unicode()->isUpper();
@@ -205,37 +314,37 @@ bool QQmlCodeGenerator::visit(AST::UiObjectDefinition *node)
int idx = defineQMLObject(node);
appendBinding(node->qualifiedTypeNameId->identifierToken, emptyStringIndex, idx);
} else {
- int idx = defineQMLObject(/*qualfied type name id*/0, node->initializer);
+ int idx = defineQMLObject(/*qualfied type name id*/0, node->qualifiedTypeNameId->firstSourceLocation(), node->initializer, /*declarations should go here*/_object);
appendBinding(node->qualifiedTypeNameId, idx);
}
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiObjectBinding *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiObjectBinding *node)
{
- int idx = defineQMLObject(node->qualifiedTypeNameId, node->initializer);
- appendBinding(node->qualifiedId, idx);
+ int idx = defineQMLObject(node->qualifiedTypeNameId, node->qualifiedTypeNameId->firstSourceLocation(), node->initializer);
+ appendBinding(node->qualifiedId, idx, node->hasOnToken);
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiScriptBinding *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiScriptBinding *node)
{
appendBinding(node->qualifiedId, node->statement);
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiArrayBinding *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiArrayBinding *node)
{
QmlObject *object = 0;
- AST::UiQualifiedId *name = node->qualifiedId;
+ QQmlJS::AST::UiQualifiedId *name = node->qualifiedId;
if (!resolveQualifiedId(&name, &object))
return false;
qSwap(_object, object);
- AST::UiArrayMemberList *member = node->members;
+ QQmlJS::AST::UiArrayMemberList *member = node->members;
while (member) {
- AST::UiObjectDefinition *def = AST::cast<AST::UiObjectDefinition*>(member->member);
+ QQmlJS::AST::UiObjectDefinition *def = QQmlJS::AST::cast<QQmlJS::AST::UiObjectDefinition*>(member->member);
int idx = defineQMLObject(def);
appendBinding(name->identifierToken, registerString(name->name.toString()), idx, /*isListItem*/ true);
@@ -247,97 +356,65 @@ bool QQmlCodeGenerator::visit(AST::UiArrayBinding *node)
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiHeaderItemList *list)
-{
- return AST::Visitor::visit(list);
-}
-
-bool QQmlCodeGenerator::visit(AST::UiObjectInitializer *ast)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiHeaderItemList *list)
{
- return AST::Visitor::visit(ast);
+ return QQmlJS::AST::Visitor::visit(list);
}
-bool QQmlCodeGenerator::visit(AST::UiObjectMemberList *ast)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiObjectInitializer *ast)
{
- return AST::Visitor::visit(ast);
+ return QQmlJS::AST::Visitor::visit(ast);
}
-bool QQmlCodeGenerator::visit(AST::UiParameterList *ast)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiObjectMemberList *ast)
{
- return AST::Visitor::visit(ast);
+ return QQmlJS::AST::Visitor::visit(ast);
}
-bool QQmlCodeGenerator::visit(AST::UiQualifiedId *id)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiParameterList *ast)
{
- return AST::Visitor::visit(id);
+ return QQmlJS::AST::Visitor::visit(ast);
}
-void QQmlCodeGenerator::accept(AST::Node *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiQualifiedId *id)
{
- AST::Node::acceptChild(node, this);
+ return QQmlJS::AST::Visitor::visit(id);
}
-bool QQmlCodeGenerator::sanityCheckFunctionNames()
+void QQmlCodeGenerator::accept(QQmlJS::AST::Node *node)
{
- QSet<QString> functionNames;
- for (Function *f = _object->functions->first; f; f = f->next) {
- AST::FunctionDeclaration *function = AST::cast<AST::FunctionDeclaration*>(_functions.at(f->index).node);
- Q_ASSERT(function);
- QString name = function->name.toString();
- if (functionNames.contains(name))
- COMPILE_EXCEPTION(function->identifierToken, tr("Duplicate method name"));
- functionNames.insert(name);
- if (_signalNames.contains(name))
- COMPILE_EXCEPTION(function->identifierToken, tr("Duplicate method name"));
-
- if (name.at(0).isUpper())
- COMPILE_EXCEPTION(function->identifierToken, tr("Method names cannot begin with an upper case letter"));
-#if 0 // ###
- if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name.toString()))
- COMPILE_EXCEPTION(&currSlot, tr("Illegal method name"));
-#endif
- }
- return true;
+ QQmlJS::AST::Node::acceptChild(node, this);
}
-int QQmlCodeGenerator::defineQMLObject(AST::UiQualifiedId *qualifiedTypeNameId, AST::UiObjectInitializer *initializer)
+int QQmlCodeGenerator::defineQMLObject(QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, QmlObject *declarationsOverride)
{
QmlObject *obj = New<QmlObject>();
_objects.append(obj);
const int objectIndex = _objects.size() - 1;
qSwap(_object, obj);
- _object->inheritedTypeNameIndex = registerString(asString(qualifiedTypeNameId));
-
- AST::SourceLocation loc;
- if (qualifiedTypeNameId)
- loc = qualifiedTypeNameId->firstSourceLocation();
- _object->location.line = loc.startLine;
- _object->location.column = loc.startColumn;
+ _object->init(pool, registerString(asString(qualifiedTypeNameId)), emptyStringIndex, location);
+ _object->declarationsOverride = declarationsOverride;
- _object->idIndex = emptyStringIndex;
- _object->indexOfDefaultProperty = -1;
- _object->properties = New<PoolList<QmlProperty> >();
- _object->qmlSignals = New<PoolList<Signal> >();
- _object->bindings = New<PoolList<Binding> >();
- _object->functions = New<PoolList<Function> >();
-
- QSet<QString> propertyNames;
- qSwap(_propertyNames, propertyNames);
- QSet<QString> signalNames;
- qSwap(_signalNames, signalNames);
+ // A new object is also a boundary for property declarations.
+ QmlProperty *declaration = 0;
+ qSwap(_propertyDeclaration, declaration);
accept(initializer);
- sanityCheckFunctionNames();
+ qSwap(_propertyDeclaration, declaration);
- qSwap(_propertyNames, propertyNames);
- qSwap(_signalNames, signalNames);
qSwap(_object, obj);
+
+ QQmlJS::AST::SourceLocation loc;
+ QString error = obj->sanityCheckFunctionNames(_functions, illegalNames, &loc);
+ if (!error.isEmpty())
+ recordError(loc, error);
+
return objectIndex;
}
-bool QQmlCodeGenerator::visit(AST::UiImport *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiImport *node)
{
QString uri;
QV4::CompiledData::Import *import = New<QV4::CompiledData::Import>();
@@ -429,7 +506,7 @@ bool QQmlCodeGenerator::visit(AST::UiImport *node)
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiPragma *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiPragma *node)
{
Pragma *pragma = New<Pragma>();
@@ -481,7 +558,7 @@ static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
return QStringList();
}
-bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiPublicMember *node)
{
static const struct TypeNameToType {
const char *name;
@@ -517,18 +594,18 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
static const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
sizeof(propTypeNameToTypes[0]);
- if (node->type == AST::UiPublicMember::Signal) {
+ if (node->type == QQmlJS::AST::UiPublicMember::Signal) {
Signal *signal = New<Signal>();
QString signalName = node->name.toString();
signal->nameIndex = registerString(signalName);
- AST::SourceLocation loc = node->firstSourceLocation();
+ QQmlJS::AST::SourceLocation loc = node->typeToken;
signal->location.line = loc.startLine;
signal->location.column = loc.startColumn;
signal->parameters = New<PoolList<SignalParameter> >();
- AST::UiParameterList *p = node->parameters;
+ QQmlJS::AST::UiParameterList *p = node->parameters;
while (p) {
const QStringRef &memberType = p->type;
@@ -582,19 +659,17 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
p = p->next;
}
- if (_signalNames.contains(signalName))
- COMPILE_EXCEPTION(node->identifierToken, tr("Duplicate signal name"));
- _signalNames.insert(signalName);
-
if (signalName.at(0).isUpper())
COMPILE_EXCEPTION(node->identifierToken, tr("Signal names cannot begin with an upper case letter"));
-#if 0 // ### cannot access identifier table from separate thread
- if (enginePrivate->v8engine()->illegalNames().contains(currSig.name.toString()))
- COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
-#endif
+ if (illegalNames.contains(signalName))
+ COMPILE_EXCEPTION(node->identifierToken, tr("Illegal signal name"));
- _object->qmlSignals->append(signal);
+ QString error = _object->appendSignal(signal);
+ if (!error.isEmpty()) {
+ recordError(node->identifierToken, error);
+ return false;
+ }
} else {
const QStringRef &memberType = node->memberType;
const QStringRef &name = node->name;
@@ -662,9 +737,10 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
else
property->customTypeNameIndex = emptyStringIndex;
- property->nameIndex = registerString(name.toString());
+ const QString propName = name.toString();
+ property->nameIndex = registerString(propName);
- AST::SourceLocation loc = node->firstSourceLocation();
+ QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
property->location.line = loc.startLine;
property->location.column = loc.startColumn;
@@ -674,7 +750,7 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
if (!node->statement && !node->binding)
COMPILE_EXCEPTION(loc, tr("No property alias location"));
- AST::SourceLocation rhsLoc;
+ QQmlJS::AST::SourceLocation rhsLoc;
if (node->binding)
rhsLoc = node->binding->firstSourceLocation();
else if (node->statement)
@@ -686,7 +762,7 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
QStringList alias;
- if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement*>(node->statement)) {
+ if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
alias = astNodeToStringList(stmt->expression);
if (alias.isEmpty()) {
if (isStatementNodeScript(node->statement)) {
@@ -710,37 +786,55 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
propertyValue += alias.at(2);
}
property->aliasPropertyValueIndex = registerString(propertyValue);
- } else if (node->statement)
- appendBinding(node->identifierToken, property->nameIndex, node->statement);
+ } else if (node->statement) {
+ qSwap(_propertyDeclaration, property);
+ appendBinding(node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ qSwap(_propertyDeclaration, property);
+ }
- _object->properties->append(property);
+ QQmlJS::AST::SourceLocation errorLocation;
+ QString error;
- if (node->isDefaultMember) {
- if (_object->indexOfDefaultProperty != -1) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Duplicate default property"));
- error.setLine(node->defaultToken.startLine);
- error.setColumn(node->defaultToken.startColumn);
- errors << error;
- return false;
- }
- _object->indexOfDefaultProperty = _object->properties->count - 1;
+ if (illegalNames.contains(propName))
+ error = tr("Illegal property name");
+ else
+ error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
+
+ if (!error.isEmpty()) {
+ if (errorLocation.startLine == 0)
+ errorLocation = node->identifierToken;
+
+ QQmlError qmlError;
+ qmlError.setDescription(error);
+ qmlError.setLine(errorLocation.startLine);
+ qmlError.setColumn(errorLocation.startColumn);
+ errors << qmlError;
+ return false;
}
- // process QML-like initializers (e.g. property Object o: Object {})
- AST::Node::accept(node->binding, this);
+ if (node->binding) {
+ qSwap(_propertyDeclaration, property);
+ // process QML-like initializers (e.g. property Object o: Object {})
+ QQmlJS::AST::Node::accept(node->binding, this);
+ qSwap(_propertyDeclaration, property);
+ }
}
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiSourceElement *node)
+bool QQmlCodeGenerator::visit(QQmlJS::AST::UiSourceElement *node)
{
- if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+ if (QQmlJS::AST::FunctionDeclaration *funDecl = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration *>(node->sourceElement)) {
_functions << funDecl;
Function *f = New<Function>();
+ f->functionDeclaration = funDecl;
+ QQmlJS::AST::SourceLocation loc = funDecl->identifierToken;
+ f->location.line = loc.startLine;
+ f->location.column = loc.startColumn;
f->index = _functions.size() - 1;
- _object->functions->append(f);
+ f->nameIndex = registerString(funDecl->name.toString());
+ _object->appendFunction(f);
} else {
QQmlError error;
error.setDescription(QCoreApplication::translate("QQmlParser","JavaScript declaration outside Script element"));
@@ -751,11 +845,11 @@ bool QQmlCodeGenerator::visit(AST::UiSourceElement *node)
return false;
}
-QString QQmlCodeGenerator::asString(AST::UiQualifiedId *node)
+QString QQmlCodeGenerator::asString(QQmlJS::AST::UiQualifiedId *node)
{
QString s;
- for (AST::UiQualifiedId *it = node; it; it = it->next) {
+ for (QQmlJS::AST::UiQualifiedId *it = node; it; it = it->next) {
s.append(it->name);
if (it->next)
@@ -765,7 +859,7 @@ QString QQmlCodeGenerator::asString(AST::UiQualifiedId *node)
return s;
}
-QStringRef QQmlCodeGenerator::asStringRef(AST::Node *node)
+QStringRef QQmlCodeGenerator::asStringRef(QQmlJS::AST::Node *node)
{
if (!node)
return QStringRef();
@@ -791,33 +885,38 @@ void QQmlCodeGenerator::extractVersion(QStringRef string, int *maj, int *min)
}
}
-QStringRef QQmlCodeGenerator::textRefAt(const AST::SourceLocation &first, const AST::SourceLocation &last) const
+QStringRef QQmlCodeGenerator::textRefAt(const QQmlJS::AST::SourceLocation &first, const QQmlJS::AST::SourceLocation &last) const
{
return QStringRef(&sourceCode, first.offset, last.offset + last.length - first.offset);
}
-void QQmlCodeGenerator::setBindingValue(QV4::CompiledData::Binding *binding, AST::Statement *statement)
+void QQmlCodeGenerator::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement)
{
+ QQmlJS::AST::SourceLocation loc = statement->firstSourceLocation();
+ binding->valueLocation.line = loc.startLine;
+ binding->valueLocation.column = loc.startColumn;
binding->type = QV4::CompiledData::Binding::Type_Invalid;
+ if (_propertyDeclaration && (_propertyDeclaration->flags & QV4::CompiledData::Property::IsReadOnly))
+ binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration;
- if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(statement)) {
- AST::ExpressionNode *expr = stmt->expression;
- if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
+ if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(statement)) {
+ QQmlJS::AST::ExpressionNode *expr = stmt->expression;
+ if (QQmlJS::AST::StringLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expr)) {
binding->type = QV4::CompiledData::Binding::Type_String;
binding->stringIndex = registerString(lit->value.toString());
- } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
+ } else if (expr->kind == QQmlJS::AST::Node::Kind_TrueLiteral) {
binding->type = QV4::CompiledData::Binding::Type_Boolean;
binding->value.b = true;
- } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
+ } else if (expr->kind == QQmlJS::AST::Node::Kind_FalseLiteral) {
binding->type = QV4::CompiledData::Binding::Type_Boolean;
binding->value.b = false;
- } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
+ } else if (QQmlJS::AST::NumericLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expr)) {
binding->type = QV4::CompiledData::Binding::Type_Number;
binding->value.d = lit->value;
} else {
- if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
- if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+ if (QQmlJS::AST::UnaryMinusExpression *unaryMinus = QQmlJS::AST::cast<QQmlJS::AST::UnaryMinusExpression *>(expr)) {
+ if (QQmlJS::AST::NumericLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(unaryMinus->expression)) {
binding->type = QV4::CompiledData::Binding::Type_Number;
binding->value.d = -lit->value;
}
@@ -834,7 +933,7 @@ void QQmlCodeGenerator::setBindingValue(QV4::CompiledData::Binding *binding, AST
}
}
-void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, AST::Statement *value)
+void QQmlCodeGenerator::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value)
{
QmlObject *object = 0;
if (!resolveQualifiedId(&name, &object))
@@ -844,23 +943,20 @@ void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, AST::Statement *
qSwap(_object, object);
}
-void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, int objectIndex)
+void QQmlCodeGenerator::appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment)
{
QmlObject *object = 0;
if (!resolveQualifiedId(&name, &object))
return;
qSwap(_object, object);
- appendBinding(name->identifierToken, registerString(name->name.toString()), objectIndex);
+ appendBinding(name->identifierToken, registerString(name->name.toString()), objectIndex, /*isListItem*/false, isOnAssignment);
qSwap(_object, object);
}
-void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, AST::Statement *value)
+void QQmlCodeGenerator::appendBinding(const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value)
{
- if (!sanityCheckPropertyName(nameLocation, propertyNameIndex))
- return;
-
if (stringAt(propertyNameIndex) == QStringLiteral("id")) {
- setId(value);
+ setId(nameLocation, value);
return;
}
@@ -870,14 +966,14 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i
binding->location.column = nameLocation.startColumn;
binding->flags = 0;
setBindingValue(binding, value);
- _object->bindings->append(binding);
+ QString error = bindingsTarget()->appendBinding(binding, /*isListBinding*/false);
+ if (!error.isEmpty()) {
+ recordError(nameLocation, error);
+ }
}
-void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex, bool isListItem)
+void QQmlCodeGenerator::appendBinding(const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem, bool isOnAssignment)
{
- if (!sanityCheckPropertyName(nameLocation, propertyNameIndex, isListItem))
- return;
-
if (stringAt(propertyNameIndex) == QStringLiteral("id")) {
recordError(nameLocation, tr("Invalid component id specification"));
return;
@@ -887,26 +983,55 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i
binding->propertyNameIndex = propertyNameIndex;
binding->location.line = nameLocation.startLine;
binding->location.column = nameLocation.startColumn;
+
+ const QmlObject *obj = _objects.at(objectIndex);
+ binding->valueLocation = obj->location;
+
binding->flags = 0;
- binding->type = QV4::CompiledData::Binding::Type_Object;
+
+ if (_propertyDeclaration && (_propertyDeclaration->flags & QV4::CompiledData::Property::IsReadOnly))
+ binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration;
+
+ // No type name on the initializer means it must be a group property
+ if (_objects.at(objectIndex)->inheritedTypeNameIndex == emptyStringIndex)
+ binding->type = QV4::CompiledData::Binding::Type_GroupProperty;
+ else
+ binding->type = QV4::CompiledData::Binding::Type_Object;
+
+ if (isOnAssignment)
+ binding->flags |= QV4::CompiledData::Binding::IsOnAssignment;
+ if (isListItem)
+ binding->flags |= QV4::CompiledData::Binding::IsListItem;
+
binding->value.objectIndex = objectIndex;
- _object->bindings->append(binding);
+ QString error = bindingsTarget()->appendBinding(binding, isListItem);
+ if (!error.isEmpty()) {
+ recordError(nameLocation, error);
+ }
+}
+
+QmlObject *QQmlCodeGenerator::bindingsTarget() const
+{
+ if (_propertyDeclaration && _object->declarationsOverride)
+ return _object->declarationsOverride;
+ return _object;
}
-bool QQmlCodeGenerator::setId(AST::Statement *value)
+bool QQmlCodeGenerator::setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value)
{
- AST::SourceLocation loc = value->firstSourceLocation();
+ QQmlJS::AST::SourceLocation loc = value->firstSourceLocation();
QStringRef str;
- AST::Node *node = value;
- if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node)) {
- if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(stmt->expression))
+ QQmlJS::AST::Node *node = value;
+ if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(node)) {
+ if (QQmlJS::AST::StringLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(stmt->expression)) {
str = lit->value;
- else
+ node = 0;
+ } else
node = stmt->expression;
}
- if (str.isEmpty())
+ if (node && str.isEmpty())
str = asStringRef(node);
if (str.isEmpty())
@@ -926,79 +1051,77 @@ bool QQmlCodeGenerator::setId(AST::Statement *value)
COMPILE_EXCEPTION(loc, tr( "IDs must contain only letters, numbers, and underscores"));
}
-#if 0 // ###
- if (enginePrivate->v8engine()->illegalNames().contains(str))
- COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
-#endif
+ QString idQString(str.toString());
+ if (illegalNames.contains(idQString))
+ COMPILE_EXCEPTION(loc, tr( "ID illegally masks global JavaScript property"));
+
+ if (_object->idIndex != emptyStringIndex)
+ COMPILE_EXCEPTION(idLocation, tr("Property value set multiple times"));
- _object->idIndex = registerString(str.toString());
- _object->locationOfIdProperty.line = loc.startLine;
- _object->locationOfIdProperty.column = loc.startColumn;
+ _object->idIndex = registerString(idQString);
+ _object->locationOfIdProperty.line = idLocation.startLine;
+ _object->locationOfIdProperty.column = idLocation.startColumn;
return true;
}
-bool QQmlCodeGenerator::resolveQualifiedId(AST::UiQualifiedId **nameToResolve, QmlObject **object)
+bool QQmlCodeGenerator::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, QmlObject **object)
{
- AST::UiQualifiedId *name = *nameToResolve;
+ QQmlJS::AST::UiQualifiedId *qualifiedIdElement = *nameToResolve;
- if (name->name == QStringLiteral("id") && name->next)
- COMPILE_EXCEPTION(name->identifierToken, tr( "Invalid use of id property"));
+ if (qualifiedIdElement->name == QStringLiteral("id") && qualifiedIdElement->next)
+ COMPILE_EXCEPTION(qualifiedIdElement->identifierToken, tr( "Invalid use of id property"));
+
+ // If it's a namespace, prepend the qualifier and we'll resolve it later to the correct type.
+ QString currentName = qualifiedIdElement->name.toString();
+ if (qualifiedIdElement->next) {
+ foreach (QV4::CompiledData::Import* import, _imports)
+ if (import->qualifierIndex != emptyStringIndex
+ && stringAt(import->qualifierIndex) == currentName) {
+ qualifiedIdElement = qualifiedIdElement->next;
+ currentName += QLatin1Char('.');
+ currentName += qualifiedIdElement->name;
+
+ if (!qualifiedIdElement->name.unicode()->isUpper())
+ COMPILE_EXCEPTION(qualifiedIdElement->firstSourceLocation(), tr("Expected type name"));
+
+ break;
+ }
+ }
*object = _object;
- while (name->next) {
+ while (qualifiedIdElement->next) {
Binding *binding = New<Binding>();
- binding->propertyNameIndex = registerString(name->name.toString());
- binding->location.line = name->identifierToken.startLine;
- binding->location.column = name->identifierToken.startColumn;
+ binding->propertyNameIndex = registerString(currentName);
+ binding->location.line = qualifiedIdElement->identifierToken.startLine;
+ binding->location.column = qualifiedIdElement->identifierToken.startColumn;
+ binding->valueLocation.line = binding->valueLocation.column = 0;
binding->flags = 0;
- if (name->name.unicode()->isUpper())
+ if (qualifiedIdElement->name.unicode()->isUpper())
binding->type = QV4::CompiledData::Binding::Type_AttachedProperty;
else
binding->type = QV4::CompiledData::Binding::Type_GroupProperty;
- int objIndex = defineQMLObject(0, 0);
+ int objIndex = defineQMLObject(0, QQmlJS::AST::SourceLocation(), 0, 0);
binding->value.objectIndex = objIndex;
- (*object)->bindings->append(binding);
+ QString error = (*object)->appendBinding(binding, /*isListBinding*/false);
+ if (!error.isEmpty()) {
+ recordError(qualifiedIdElement->identifierToken, error);
+ return false;
+ }
*object = _objects[objIndex];
- name = name->next;
+ qualifiedIdElement = qualifiedIdElement->next;
+ if (qualifiedIdElement)
+ currentName = qualifiedIdElement->name.toString();
}
- *nameToResolve = name;
+ *nameToResolve = qualifiedIdElement;
return true;
}
-bool QQmlCodeGenerator::sanityCheckPropertyName(const AST::SourceLocation &nameLocation, int nameIndex, bool isListItem)
-{
- const QString &name = jsGenerator->strings.at(nameIndex);
- if (name.isEmpty())
- return true;
-
- // List items are implement by multiple bindings to the same name, so allow duplicates.
- if (!isListItem) {
- if (_propertyNames.contains(name))
- COMPILE_EXCEPTION(nameLocation, tr("Duplicate property name"));
-
- _propertyNames.insert(name);
- }
-
- if (name.at(0).isUpper())
- COMPILE_EXCEPTION(nameLocation, tr("Property names cannot begin with an upper case letter"));
-
-#if 0 // ### how to check against illegalNames when in separate thread?
- if (enginePrivate->v8engine()->illegalNames().contains(prop.name.toString())) {
- COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
- prop.nameLocation.column,
- tr("Illegal property name"));
- }
-#endif
-
- return true;
-}
-
-void QQmlCodeGenerator::recordError(const AST::SourceLocation &location, const QString &description)
+void QQmlCodeGenerator::recordError(const QQmlJS::AST::SourceLocation &location, const QString &description)
{
QQmlError error;
error.setUrl(url);
@@ -1011,27 +1134,28 @@ void QQmlCodeGenerator::recordError(const AST::SourceLocation &location, const Q
void QQmlCodeGenerator::collectTypeReferences()
{
foreach (QmlObject *obj, _objects) {
- if (!stringAt(obj->inheritedTypeNameIndex).isEmpty())
- _typeReferences.add(obj->inheritedTypeNameIndex, obj->location);
-
- for (QmlProperty *prop = obj->properties->first; prop; prop = prop->next) {
- if (prop->type >= QV4::CompiledData::Property::Custom)
- _typeReferences.add(prop->customTypeNameIndex, prop->location);
+ if (obj->inheritedTypeNameIndex != emptyStringIndex) {
+ QV4::CompiledData::TypeReference &r = _typeReferences.add(obj->inheritedTypeNameIndex, obj->location);
+ r.needsCreation = true;
}
- for (Signal *sig = obj->qmlSignals->first; sig; sig = sig->next)
- for (SignalParameter *param = sig->parameters->first; param; param = param->next)
- if (!stringAt(param->customTypeNameIndex).isEmpty())
- _typeReferences.add(param->customTypeNameIndex, param->location);
+ for (const QmlProperty *prop = obj->firstProperty(); prop; prop = prop->next) {
+ if (prop->type >= QV4::CompiledData::Property::Custom) {
+ // ### FIXME: We could report the more accurate location here by using prop->location, but the old
+ // compiler can't and the tests expect it to be the object location right now.
+ QV4::CompiledData::TypeReference &r = _typeReferences.add(prop->customTypeNameIndex, obj->location);
+ r.needsCreation = true;
+ }
+ }
- for (Binding *binding = obj->bindings->first; binding; binding = binding->next) {
+ for (const Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty)
_typeReferences.add(binding->propertyNameIndex, binding->location);
}
}
}
-QQmlScript::LocationSpan QQmlCodeGenerator::location(AST::SourceLocation start, AST::SourceLocation end)
+QQmlScript::LocationSpan QQmlCodeGenerator::location(QQmlJS::AST::SourceLocation start, QQmlJS::AST::SourceLocation end)
{
QQmlScript::LocationSpan rv;
rv.start.line = start.startLine;
@@ -1043,22 +1167,22 @@ QQmlScript::LocationSpan QQmlCodeGenerator::location(AST::SourceLocation start,
return rv;
}
-bool QQmlCodeGenerator::isStatementNodeScript(AST::Statement *statement)
+bool QQmlCodeGenerator::isStatementNodeScript(QQmlJS::AST::Statement *statement)
{
- if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(statement)) {
- AST::ExpressionNode *expr = stmt->expression;
- if (AST::cast<AST::StringLiteral *>(expr))
+ if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(statement)) {
+ QQmlJS::AST::ExpressionNode *expr = stmt->expression;
+ if (QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expr))
return false;
- else if (expr->kind == AST::Node::Kind_TrueLiteral)
+ else if (expr->kind == QQmlJS::AST::Node::Kind_TrueLiteral)
return false;
- else if (expr->kind == AST::Node::Kind_FalseLiteral)
+ else if (expr->kind == QQmlJS::AST::Node::Kind_FalseLiteral)
return false;
- else if (AST::cast<AST::NumericLiteral *>(expr))
+ else if (QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expr))
return false;
else {
- if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
- if (AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+ if (QQmlJS::AST::UnaryMinusExpression *unaryMinus = QQmlJS::AST::cast<QQmlJS::AST::UnaryMinusExpression *>(expr)) {
+ if (QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(unaryMinus->expression)) {
return false;
}
}
@@ -1082,10 +1206,10 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const
int objectsSize = 0;
foreach (QmlObject *o, output.objects) {
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
- objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functions->count, o->properties->count, o->qmlSignals->count, o->bindings->count);
+ objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
int signalTableSize = 0;
- for (Signal *s = o->qmlSignals->first; s; s = s->next)
+ for (const Signal *s = o->firstSignal(); s; s = s->next)
signalTableSize += QV4::CompiledData::Signal::calculateSize(s->parameters->count);
objectsSize += signalTableSize;
@@ -1128,46 +1252,45 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const
quint32 nextOffset = sizeof(QV4::CompiledData::Object);
- objectToWrite->nFunctions = o->functions->count;
+ objectToWrite->nFunctions = o->functionCount();
objectToWrite->offsetToFunctions = nextOffset;
nextOffset += objectToWrite->nFunctions * sizeof(quint32);
- objectToWrite->nProperties = o->properties->count;
+ objectToWrite->nProperties = o->propertyCount();
objectToWrite->offsetToProperties = nextOffset;
nextOffset += objectToWrite->nProperties * sizeof(QV4::CompiledData::Property);
- objectToWrite->nSignals = o->qmlSignals->count;
+ objectToWrite->nSignals = o->signalCount();
objectToWrite->offsetToSignals = nextOffset;
nextOffset += objectToWrite->nSignals * sizeof(quint32);
- objectToWrite->nBindings = o->bindings->count;
+ objectToWrite->nBindings = o->bindingCount();
objectToWrite->offsetToBindings = nextOffset;
nextOffset += objectToWrite->nBindings * sizeof(QV4::CompiledData::Binding);
quint32 *functionsTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToFunctions);
- for (Function *f = o->functions->first; f; f = f->next)
+ for (const Function *f = o->firstFunction(); f; f = f->next)
*functionsTable++ = runtimeFunctionIndices[f->index];
char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties;
- for (QmlProperty *p = o->properties->first; p; p = p->next) {
+ for (const QmlProperty *p = o->firstProperty(); p; p = p->next) {
QV4::CompiledData::Property *propertyToWrite = reinterpret_cast<QV4::CompiledData::Property*>(propertiesPtr);
*propertyToWrite = *p;
propertiesPtr += sizeof(QV4::CompiledData::Property);
}
char *bindingPtr = objectPtr + objectToWrite->offsetToBindings;
- for (Binding *b = o->bindings->first; b; b = b->next) {
- QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr);
- *bindingToWrite = *b;
- if (b->type == QV4::CompiledData::Binding::Type_Script)
- bindingToWrite->value.compiledScriptIndex = runtimeFunctionIndices[b->value.compiledScriptIndex];
- bindingPtr += sizeof(QV4::CompiledData::Binding);
- }
+ bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isValueBindingNoAlias);
+ bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isSignalHandler);
+ bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isAttachedProperty);
+ bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isGroupProperty);
+ bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isValueBindingToAlias);
+ Q_ASSERT((bindingPtr - objectToWrite->offsetToBindings - objectPtr) / sizeof(QV4::CompiledData::Binding) == unsigned(o->bindingCount()));
quint32 *signalOffsetTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToSignals);
quint32 signalTableSize = 0;
char *signalPtr = objectPtr + nextOffset;
- for (Signal *s = o->qmlSignals->first; s; s = s->next) {
+ for (const Signal *s = o->firstSignal(); s; s = s->next) {
*signalOffsetTable++ = signalPtr - objectPtr;
QV4::CompiledData::Signal *signalToWrite = reinterpret_cast<QV4::CompiledData::Signal*>(signalPtr);
@@ -1184,7 +1307,7 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const
signalPtr += size;
}
- objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functions->count, o->properties->count, o->qmlSignals->count, o->bindings->count);
+ objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
objectPtr += signalTableSize;
}
@@ -1199,12 +1322,27 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const
return qmlUnit;
}
+char *QmlUnitGenerator::writeBindings(char *bindingPtr, QmlObject *o, const QVector<int> &runtimeFunctionIndices, BindingFilter filter) const
+{
+ for (const Binding *b = o->firstBinding(); b; b = b->next) {
+ if (!(b->*(filter))())
+ continue;
+ QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr);
+ *bindingToWrite = *b;
+ if (b->type == QV4::CompiledData::Binding::Type_Script)
+ bindingToWrite->value.compiledScriptIndex = runtimeFunctionIndices[b->value.compiledScriptIndex];
+ bindingPtr += sizeof(QV4::CompiledData::Binding);
+ }
+ return bindingPtr;
+}
+
int QmlUnitGenerator::getStringId(const QString &str) const
{
return jsUnitGenerator->getStringId(str);
}
-JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, V4IR::Module *jsModule, Engine *jsEngine, AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports)
+JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, IR::Module *jsModule, QQmlJS::Engine *jsEngine,
+ QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports)
: QQmlJS::Codegen(/*strict mode*/false)
, sourceCode(sourceCode)
, jsEngine(jsEngine)
@@ -1244,7 +1382,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
scan.enterQmlScope(qmlRoot, QStringLiteral("context scope"));
foreach (const CompiledFunctionOrExpression &f, functions) {
Q_ASSERT(f.node != qmlRoot);
- AST::FunctionDeclaration *function = AST::cast<AST::FunctionDeclaration*>(f.node);
+ QQmlJS::AST::FunctionDeclaration *function = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(f.node);
if (function)
scan.enterQmlFunction(function);
@@ -1262,10 +1400,10 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
for (int i = 0; i < functions.count(); ++i) {
const CompiledFunctionOrExpression &qmlFunction = functions.at(i);
- AST::Node *node = qmlFunction.node;
+ QQmlJS::AST::Node *node = qmlFunction.node;
Q_ASSERT(node != qmlRoot);
- AST::FunctionDeclaration *function = AST::cast<AST::FunctionDeclaration*>(node);
+ QQmlJS::AST::FunctionDeclaration *function = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(node);
QString name;
if (function)
@@ -1275,21 +1413,21 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
else
name = QStringLiteral("%qml-expression-entry");
- AST::SourceElements *body;
+ QQmlJS::AST::SourceElements *body;
if (function)
body = function->body ? function->body->elements : 0;
else {
// Synthesize source elements.
QQmlJS::MemoryPool *pool = jsEngine->pool();
- AST::Statement *stmt = node->statementCast();
+ QQmlJS::AST::Statement *stmt = node->statementCast();
if (!stmt) {
Q_ASSERT(node->expressionCast());
- AST::ExpressionNode *expr = node->expressionCast();
- stmt = new (pool) AST::ExpressionStatement(expr);
+ QQmlJS::AST::ExpressionNode *expr = node->expressionCast();
+ stmt = new (pool) QQmlJS::AST::ExpressionStatement(expr);
}
- AST::SourceElement *element = new (pool) AST::StatementSourceElement(stmt);
- body = new (pool) AST::SourceElements(element);
+ QQmlJS::AST::SourceElement *element = new (pool) QQmlJS::AST::StatementSourceElement(stmt);
+ body = new (pool) QQmlJS::AST::SourceElements(element);
body = body->finish();
}
@@ -1331,7 +1469,7 @@ QQmlPropertyData *JSCodeGen::lookupQmlCompliantProperty(QQmlPropertyCache *cache
return pd;
}
-static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
+static void initMetaObjectResolver(IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
enum MetaObjectResolverFlags {
AllPropertiesAreFinal = 0x1,
@@ -1340,11 +1478,11 @@ enum MetaObjectResolverFlags {
ResolveTypeInformationOnly = 0x8
};
-static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
+static void initMetaObjectResolver(IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
-static V4IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpressionResolver *resolver, V4IR::Member *member)
+static IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, IR::MemberExpressionResolver *resolver, IR::Member *member)
{
- V4IR::Type result = V4IR::VarType;
+ IR::Type result = IR::VarType;
QQmlType *type = static_cast<QQmlType*>(resolver->data);
@@ -1354,7 +1492,7 @@ static V4IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpre
if (ok) {
member->setEnumValue(value);
resolver->clear();
- return V4IR::SInt32Type;
+ return IR::SInt32Type;
}
}
@@ -1376,7 +1514,7 @@ static V4IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpre
return result;
}
-static void initQmlTypeResolver(V4IR::MemberExpressionResolver *resolver, QQmlType *qmlType)
+static void initQmlTypeResolver(IR::MemberExpressionResolver *resolver, QQmlType *qmlType)
{
resolver->resolveMember = &resolveQmlType;
resolver->data = qmlType;
@@ -1384,9 +1522,9 @@ static void initQmlTypeResolver(V4IR::MemberExpressionResolver *resolver, QQmlTy
resolver->flags = 0;
}
-static V4IR::Type resolveImportNamespace(QQmlEnginePrivate *, V4IR::MemberExpressionResolver *resolver, V4IR::Member *member)
+static IR::Type resolveImportNamespace(QQmlEnginePrivate *, IR::MemberExpressionResolver *resolver, IR::Member *member)
{
- V4IR::Type result = V4IR::VarType;
+ IR::Type result = IR::VarType;
QQmlTypeNameCache *typeNamespace = static_cast<QQmlTypeNameCache*>(resolver->extraData);
void *importNamespace = resolver->data;
@@ -1395,14 +1533,14 @@ static V4IR::Type resolveImportNamespace(QQmlEnginePrivate *, V4IR::MemberExpres
member->freeOfSideEffects = true;
if (r.scriptIndex != -1) {
// TODO: remember the index and replace with subscript later.
- result = V4IR::VarType;
+ result = IR::VarType;
} else if (r.type) {
// TODO: Propagate singleton information, so that it is loaded
// through the singleton getter in the run-time. Until then we
// can't accelerate access :(
if (!r.type->isSingleton()) {
initQmlTypeResolver(resolver, r.type);
- return V4IR::QObjectType;
+ return IR::QObjectType;
}
} else {
Q_ASSERT(false); // How can this happen?
@@ -1413,7 +1551,7 @@ static V4IR::Type resolveImportNamespace(QQmlEnginePrivate *, V4IR::MemberExpres
return result;
}
-static void initImportNamespaceResolver(V4IR::MemberExpressionResolver *resolver, QQmlTypeNameCache *imports, const void *importNamespace)
+static void initImportNamespaceResolver(IR::MemberExpressionResolver *resolver, QQmlTypeNameCache *imports, const void *importNamespace)
{
resolver->resolveMember = &resolveImportNamespace;
resolver->data = const_cast<void*>(importNamespace);
@@ -1421,9 +1559,9 @@ static void initImportNamespaceResolver(V4IR::MemberExpressionResolver *resolver
resolver->flags = 0;
}
-static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpressionResolver *resolver, V4IR::Member *member)
+static IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, IR::MemberExpressionResolver *resolver, IR::Member *member)
{
- V4IR::Type result = V4IR::VarType;
+ IR::Type result = IR::VarType;
QQmlPropertyCache *metaObject = static_cast<QQmlPropertyCache*>(resolver->data);
if (member->name->constData()->isUpper() && (resolver->flags & LookupsIncludeEnums)) {
@@ -1436,7 +1574,7 @@ static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::
if (ok) {
member->setEnumValue(value);
resolver->clear();
- return V4IR::SInt32Type;
+ return IR::SInt32Type;
}
}
}
@@ -1469,24 +1607,24 @@ static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::
// Enums cannot be mapped to IR types, they need to go through the run-time handling
// of accepting strings that will then be converted to the right values.
if (property->isEnum())
- return V4IR::VarType;
+ return IR::VarType;
switch (property->propType) {
- case QMetaType::Bool: result = V4IR::BoolType; break;
- case QMetaType::Int: result = V4IR::SInt32Type; break;
- case QMetaType::Double: result = V4IR::DoubleType; break;
- case QMetaType::QString: result = V4IR::StringType; break;
+ case QMetaType::Bool: result = IR::BoolType; break;
+ case QMetaType::Int: result = IR::SInt32Type; break;
+ case QMetaType::Double: result = IR::DoubleType; break;
+ case QMetaType::QString: result = IR::StringType; break;
default:
if (property->isQObject()) {
if (QQmlPropertyCache *cache = qmlEngine->propertyCacheForType(property->propType)) {
initMetaObjectResolver(resolver, cache);
- return V4IR::QObjectType;
+ return IR::QObjectType;
}
} else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType)) {
if (QQmlPropertyCache *cache = qmlEngine->cache(valueType->metaObject())) {
initMetaObjectResolver(resolver, cache);
resolver->flags |= ResolveTypeInformationOnly;
- return V4IR::QObjectType;
+ return IR::QObjectType;
}
}
break;
@@ -1497,7 +1635,7 @@ static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::
return result;
}
-static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject)
+static void initMetaObjectResolver(IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject)
{
resolver->resolveMember = &resolveMetaObjectProperty;
resolver->data = metaObject;
@@ -1512,19 +1650,19 @@ void JSCodeGen::beginFunctionBodyHook()
_importedScriptsTemp = _block->newTemp();
_idArrayTemp = _block->newTemp();
- V4IR::Temp *temp = _block->TEMP(_contextObjectTemp);
+ IR::Temp *temp = _block->TEMP(_contextObjectTemp);
initMetaObjectResolver(&temp->memberResolver, _contextObject);
- move(temp, _block->NAME(V4IR::Name::builtin_qml_context_object, 0, 0));
+ move(temp, _block->NAME(IR::Name::builtin_qml_context_object, 0, 0));
temp = _block->TEMP(_scopeObjectTemp);
initMetaObjectResolver(&temp->memberResolver, _scopeObject);
- move(temp, _block->NAME(V4IR::Name::builtin_qml_scope_object, 0, 0));
+ move(temp, _block->NAME(IR::Name::builtin_qml_scope_object, 0, 0));
- move(_block->TEMP(_importedScriptsTemp), _block->NAME(V4IR::Name::builtin_qml_imported_scripts_object, 0, 0));
- move(_block->TEMP(_idArrayTemp), _block->NAME(V4IR::Name::builtin_qml_id_array, 0, 0));
+ move(_block->TEMP(_importedScriptsTemp), _block->NAME(IR::Name::builtin_qml_imported_scripts_object, 0, 0));
+ move(_block->TEMP(_idArrayTemp), _block->NAME(IR::Name::builtin_qml_id_array, 0, 0));
}
-V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col)
+IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col)
{
if (_disableAcceleratedLookups)
return 0;
@@ -1546,8 +1684,8 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
foreach (const IdMapping &mapping, _idObjects)
if (name == mapping.name) {
_function->idObjectDependencies.insert(mapping.idIndex);
- V4IR::Expr *s = subscript(_block->TEMP(_idArrayTemp), _block->CONST(V4IR::SInt32Type, mapping.idIndex));
- V4IR::Temp *result = _block->TEMP(_block->newTemp());
+ IR::Expr *s = subscript(_block->TEMP(_idArrayTemp), _block->CONST(IR::SInt32Type, mapping.idIndex));
+ IR::Temp *result = _block->TEMP(_block->newTemp());
_block->MOVE(result, s);
result = _block->TEMP(result->index);
if (mapping.type) {
@@ -1562,13 +1700,13 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
QQmlTypeNameCache::Result r = imports->query(name);
if (r.isValid()) {
if (r.scriptIndex != -1) {
- return subscript(_block->TEMP(_importedScriptsTemp), _block->CONST(V4IR::SInt32Type, r.scriptIndex));
+ return subscript(_block->TEMP(_importedScriptsTemp), _block->CONST(IR::SInt32Type, r.scriptIndex));
} else if (r.type) {
- V4IR::Name *typeName = _block->NAME(name, line, col);
+ IR::Name *typeName = _block->NAME(name, line, col);
// Make sure the run-time loads this through the more efficient singleton getter.
typeName->qmlSingleton = r.type->isCompositeSingleton();
typeName->freeOfSideEffects = true;
- V4IR::Temp *result = _block->TEMP(_block->newTemp());
+ IR::Temp *result = _block->TEMP(_block->newTemp());
_block->MOVE(result, typeName);
result = _block->TEMP(result->index);
@@ -1576,9 +1714,9 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
return result;
} else {
Q_ASSERT(r.importNamespace);
- V4IR::Name *namespaceName = _block->NAME(name, line, col);
+ IR::Name *namespaceName = _block->NAME(name, line, col);
namespaceName->freeOfSideEffects = true;
- V4IR::Temp *result = _block->TEMP(_block->newTemp());
+ IR::Temp *result = _block->TEMP(_block->newTemp());
initImportNamespaceResolver(&result->memberResolver, imports, r.importNamespace);
_block->MOVE(result, namespaceName);
@@ -1593,9 +1731,9 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- V4IR::Temp *base = _block->TEMP(_scopeObjectTemp);
+ IR::Temp *base = _block->TEMP(_scopeObjectTemp);
initMetaObjectResolver(&base->memberResolver, _scopeObject);
- return _block->MEMBER(base, _function->newString(name), pd, V4IR::Member::MemberOfQmlScopeObject);
+ return _block->MEMBER(base, _function->newString(name), pd, IR::Member::MemberOfQmlScopeObject);
}
}
@@ -1605,9 +1743,9 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- V4IR::Temp *base = _block->TEMP(_contextObjectTemp);
+ IR::Temp *base = _block->TEMP(_contextObjectTemp);
initMetaObjectResolver(&base->memberResolver, _contextObject);
- return _block->MEMBER(base, _function->newString(name), pd, V4IR::Member::MemberOfQmlContextObject);
+ return _block->MEMBER(base, _function->newString(name), pd, IR::Member::MemberOfQmlContextObject);
}
}
@@ -1620,16 +1758,24 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlEnginePrivate *enginePrivate,
: enginePrivate(enginePrivate)
, parsedQML(parsedQML)
, unit(unit)
+ , illegalNames(QV8Engine::get(QQmlEnginePrivate::get(enginePrivate))->illegalNames())
{
}
bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclarations()
{
- foreach (QmlObject *obj, parsedQML->objects) {
+ for (int objectIndex = 0; objectIndex < parsedQML->objects.count(); ++objectIndex) {
+ QmlObject * const obj = parsedQML->objects.at(objectIndex);
QString elementName = stringAt(obj->inheritedTypeNameIndex);
if (elementName.isEmpty())
continue;
- QQmlPropertyCache *cache = unit->resolvedTypes[obj->inheritedTypeNameIndex].createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ QQmlCompiledData::TypeReference *tr = unit->resolvedTypes.value(obj->inheritedTypeNameIndex);
+ QQmlCustomParser *customParser = (tr && tr->type) ? tr->type->customParser() : 0;
+ if (customParser && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers))
+ continue;
+ QQmlPropertyCache *cache = unit->propertyCaches.value(objectIndex);
+ if (!cache)
+ continue;
if (!convertSignalHandlerExpressionsToFunctionDeclarations(obj, elementName, cache))
return false;
}
@@ -1641,12 +1787,13 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
// map from signal name defined in qml itself to list of parameters
QHash<QString, QStringList> customSignals;
- for (Binding *binding = obj->bindings->first; binding; binding = binding->next) {
+ for (Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
QString propertyName = stringAt(binding->propertyNameIndex);
// Attached property?
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
QmlObject *attachedObj = parsedQML->objects[binding->value.objectIndex];
- QQmlType *type = unit->resolvedTypes.value(binding->propertyNameIndex).type;
+ QQmlCompiledData::TypeReference *typeRef = unit->resolvedTypes.value(binding->propertyNameIndex);
+ QQmlType *type = typeRef ? typeRef->type : 0;
const QMetaObject *attachedType = type ? type->attachedPropertiesType() : 0;
if (!attachedType)
COMPILE_EXCEPTION(binding->location, tr("Non-existent attached object"));
@@ -1659,10 +1806,6 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (!QQmlCodeGenerator::isSignalPropertyName(propertyName))
continue;
- if (binding->type != QV4::CompiledData::Binding::Type_Script) {
- COMPILE_EXCEPTION(binding->location, tr("Incorrectly specified signal assignment"));
- }
-
PropertyResolver resolver(propertyCache);
Q_ASSERT(propertyName.startsWith(QStringLiteral("on")));
@@ -1683,8 +1826,22 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
QQmlPropertyData *signal = resolver.signal(propertyName, &notInRevision);
if (signal) {
int sigIndex = propertyCache->methodIndexToSignalIndex(signal->coreIndex);
- foreach (const QByteArray &param, propertyCache->signalParameterNames(sigIndex))
- parameters << QString::fromUtf8(param);
+ sigIndex = propertyCache->originalClone(sigIndex);
+
+ bool unnamedParameter = false;
+
+ QList<QByteArray> parameterNames = propertyCache->signalParameterNames(sigIndex);
+ for (int i = 0; i < parameterNames.count(); ++i) {
+ const QString param = QString::fromUtf8(parameterNames.at(i));
+ if (param.isEmpty())
+ unnamedParameter = true;
+ else if (unnamedParameter) {
+ COMPILE_EXCEPTION(binding->location, tr("Signal uses unnamed parameter followed by named parameter."));
+ } else if (illegalNames.contains(param)) {
+ COMPILE_EXCEPTION(binding->location, tr("Signal parameter \"%1\" hides global variable.").arg(param));
+ }
+ parameters += param;
+ }
} else {
if (notInRevision) {
// Try assinging it as a property later
@@ -1693,7 +1850,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
- const QQmlType *type = unit->resolvedTypes.value(obj->inheritedTypeNameIndex).type;
+ QQmlCompiledData::TypeReference *typeRef = unit->resolvedTypes.value(obj->inheritedTypeNameIndex);
+ const QQmlType *type = typeRef ? typeRef->type : 0;
if (type) {
COMPILE_EXCEPTION(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type->module()).arg(type->majorVersion()).arg(type->minorVersion()));
} else {
@@ -1705,12 +1863,12 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
// build cache if necessary
if (customSignals.isEmpty()) {
- for (Signal *signal = obj->qmlSignals->first; signal; signal = signal->next) {
+ for (const Signal *signal = obj->firstSignal(); signal; signal = signal->next) {
const QString &signalName = stringAt(signal->nameIndex);
customSignals.insert(signalName, signal->parameterStringList(parsedQML->jsGenerator.strings));
}
- for (QmlProperty *property = obj->properties->first; property; property = property->next) {
+ for (const QmlProperty *property = obj->firstProperty(); property; property = property->next) {
const QString propName = stringAt(property->nameIndex);
customSignals.insert(propName, QStringList());
}
@@ -1731,34 +1889,45 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
parameters = entry.value();
}
+ binding->propertyNameIndex = parsedQML->jsGenerator.registerString(propertyName);
+
+ // Binding object to signal means connect the signal to the object's default method.
+ if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerObject;
+ continue;
+ }
+
+ if (binding->type != QV4::CompiledData::Binding::Type_Script) {
+ COMPILE_EXCEPTION(binding->location, tr("Incorrectly specified signal assignment"));
+ }
+
QQmlJS::Engine &jsEngine = parsedQML->jsParserEngine;
QQmlJS::MemoryPool *pool = jsEngine.pool();
- AST::FormalParameterList *paramList = 0;
+ QQmlJS::AST::FormalParameterList *paramList = 0;
foreach (const QString &param, parameters) {
QStringRef paramNameRef = jsEngine.newStringRef(param);
if (paramList)
- paramList = new (pool) AST::FormalParameterList(paramList, paramNameRef);
+ paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, paramNameRef);
else
- paramList = new (pool) AST::FormalParameterList(paramNameRef);
+ paramList = new (pool) QQmlJS::AST::FormalParameterList(paramNameRef);
}
if (paramList)
paramList = paramList->finish();
- AST::Statement *statement = static_cast<AST::Statement*>(parsedQML->functions[binding->value.compiledScriptIndex].node);
- AST::SourceElement *sourceElement = new (pool) AST::StatementSourceElement(statement);
- AST::SourceElements *elements = new (pool) AST::SourceElements(sourceElement);
+ QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(parsedQML->functions[binding->value.compiledScriptIndex].node);
+ QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement);
+ QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement);
elements = elements->finish();
- AST::FunctionBody *body = new (pool) AST::FunctionBody(elements);
+ QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements);
- AST::FunctionDeclaration *functionDeclaration = new (pool) AST::FunctionDeclaration(jsEngine.newStringRef(propertyName), paramList, body);
+ QQmlJS::AST::FunctionDeclaration *functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(jsEngine.newStringRef(propertyName), paramList, body);
parsedQML->functions[binding->value.compiledScriptIndex] = functionDeclaration;
binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerExpression;
- binding->propertyNameIndex = parsedQML->jsGenerator.registerString(propertyName);
}
return true;
}
@@ -1773,11 +1942,11 @@ void SignalHandlerConverter::recordError(const QV4::CompiledData::Location &loca
errors << error;
}
-QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision)
+QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, QObject *object, QQmlContextData *context)
{
if (notInRevision) *notInRevision = false;
- QQmlPropertyData *d = cache->property(name, 0, 0);
+ QQmlPropertyData *d = cache->property(name, object, context);
// Find the first property
while (d && d->isFunction())
@@ -1792,11 +1961,11 @@ QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRev
}
-QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision)
+QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision, QObject *object, QQmlContextData *context)
{
if (notInRevision) *notInRevision = false;
- QQmlPropertyData *d = cache->property(name, 0, 0);
+ QQmlPropertyData *d = cache->property(name, object, context);
if (notInRevision) *notInRevision = false;
while (d && !(d->isFunction()))
@@ -1812,7 +1981,7 @@ QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevis
if (name.endsWith(QStringLiteral("Changed"))) {
QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
- d = property(propName, notInRevision);
+ d = property(propName, notInRevision, object, context);
if (d)
return cache->signal(d->notifyIndex);
}
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index 0a0e4f2d5b..d895dbaf33 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -59,7 +59,7 @@ class QQmlTypeNameCache;
namespace QtQml {
-using namespace QQmlJS;
+using namespace QV4;
struct DebugStream
{
@@ -93,15 +93,49 @@ struct PoolList
T *last;
int count;
- void append(T *item) {
+ int append(T *item) {
item->next = 0;
if (last)
last->next = item;
else
first = item;
last = item;
+ return count++;
+ }
+
+ void prepend(T *item) {
+ item->next = first;
+ first = item;
+ if (!last)
+ last = first;
++count;
}
+
+ template <typename Sortable, typename Base, Sortable Base::*sortMember>
+ T *findSortedInsertionPoint(T *item) const
+ {
+ T *insertPos = 0;
+
+ for (T *it = first; it; it = it->next) {
+ if (!(it->*sortMember < item->*sortMember))
+ break;
+ insertPos = it;
+ }
+
+ return insertPos;
+ }
+
+ void insertAfter(T *insertionPoint, T *item) {
+ if (!insertionPoint) {
+ prepend(item);
+ } else if (insertionPoint == last) {
+ append(item);
+ } else {
+ item->next = insertionPoint->next;
+ insertionPoint->next = item;
+ ++count;
+ }
+ }
};
struct QmlObject;
@@ -135,25 +169,73 @@ struct Binding : public QV4::CompiledData::Binding
struct Function
{
+ QQmlJS::AST::FunctionDeclaration *functionDeclaration;
+ QV4::CompiledData::Location location;
+ int nameIndex;
int index; // index in parsedQML::functions
Function *next;
};
+struct CompiledFunctionOrExpression
+{
+ CompiledFunctionOrExpression()
+ : node(0)
+ , disableAcceleratedLookups(false)
+ {}
+ CompiledFunctionOrExpression(QQmlJS::AST::Node *n)
+ : node(n)
+ , disableAcceleratedLookups(false)
+ {}
+ QQmlJS::AST::Node *node; // FunctionDeclaration, Statement or Expression
+ QString name;
+ bool disableAcceleratedLookups;
+};
+
struct QmlObject
{
- int inheritedTypeNameIndex;
- int idIndex;
+ Q_DECLARE_TR_FUNCTIONS(QmlObject)
+public:
+ quint32 inheritedTypeNameIndex;
+ quint32 idIndex;
int indexOfDefaultProperty;
QV4::CompiledData::Location location;
QV4::CompiledData::Location locationOfIdProperty;
+ const QmlProperty *firstProperty() const { return properties->first; }
+ int propertyCount() const { return properties->count; }
+ const Signal *firstSignal() const { return qmlSignals->first; }
+ int signalCount() const { return qmlSignals->count; }
+ Binding *firstBinding() const { return bindings->first; }
+ int bindingCount() const { return bindings->count; }
+ const Function *firstFunction() const { return functions->first; }
+ int functionCount() const { return functions->count; }
+
+ // If set, then declarations for this object (and init bindings for these) should go into the
+ // specified object. Used for declarations inside group properties.
+ QmlObject *declarationsOverride;
+
+ void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation());
+
+ void dump(DebugStream &out);
+
+ QString sanityCheckFunctionNames(const QList<CompiledFunctionOrExpression> &allFunctions, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
+
+ QString appendSignal(Signal *signal);
+ QString appendProperty(QmlProperty *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
+ void appendFunction(QtQml::Function *f);
+
+ QString appendBinding(Binding *b, bool isListBinding);
+
+private:
PoolList<QmlProperty> *properties;
PoolList<Signal> *qmlSignals;
PoolList<Binding> *bindings;
PoolList<Function> *functions;
- void dump(DebugStream &out);
+ QSet<int> propertyNames;
+ QSet<int> bindingNames;
+ QSet<int> signalNames;
};
struct Pragma
@@ -166,20 +248,6 @@ struct Pragma
QV4::CompiledData::Location location;
};
-struct CompiledFunctionOrExpression
-{
- CompiledFunctionOrExpression()
- : disableAcceleratedLookups(false)
- {}
- CompiledFunctionOrExpression(AST::Node *n)
- : node(n)
- , disableAcceleratedLookups(false)
- {}
- AST::Node *node; // FunctionDeclaration, Statement or Expression
- QString name;
- bool disableAcceleratedLookups;
-};
-
struct ParsedQML
{
ParsedQML(bool debugMode)
@@ -188,10 +256,10 @@ struct ParsedQML
{}
QString code;
QQmlJS::Engine jsParserEngine;
- V4IR::Module jsModule;
+ QV4::IR::Module jsModule;
QList<QV4::CompiledData::Import*> imports;
QList<Pragma*> pragmas;
- AST::UiProgram *program;
+ QQmlJS::AST::UiProgram *program;
int indexOfRootObject;
QList<QmlObject*> objects;
QList<CompiledFunctionOrExpression> functions;
@@ -203,83 +271,85 @@ struct ParsedQML
};
// Doesn't really generate code per-se, but more the data structure
-struct Q_QML_EXPORT QQmlCodeGenerator : public AST::Visitor
+struct Q_QML_EXPORT QQmlCodeGenerator : public QQmlJS::AST::Visitor
{
Q_DECLARE_TR_FUNCTIONS(QQmlCodeGenerator)
public:
- QQmlCodeGenerator();
+ QQmlCodeGenerator(const QSet<QString> &illegalNames);
bool generateFromQml(const QString &code, const QUrl &url, const QString &urlString, ParsedQML *output);
static bool isSignalPropertyName(const QString &name);
- using AST::Visitor::visit;
- using AST::Visitor::endVisit;
-
- virtual bool visit(AST::UiArrayMemberList *ast);
- virtual bool visit(AST::UiImport *ast);
- virtual bool visit(AST::UiPragma *ast);
- virtual bool visit(AST::UiHeaderItemList *ast);
- virtual bool visit(AST::UiObjectInitializer *ast);
- virtual bool visit(AST::UiObjectMemberList *ast);
- virtual bool visit(AST::UiParameterList *ast);
- virtual bool visit(AST::UiProgram *);
- virtual bool visit(AST::UiQualifiedId *ast);
- virtual bool visit(AST::UiArrayBinding *ast);
- virtual bool visit(AST::UiObjectBinding *ast);
- virtual bool visit(AST::UiObjectDefinition *ast);
- virtual bool visit(AST::UiPublicMember *ast);
- virtual bool visit(AST::UiScriptBinding *ast);
- virtual bool visit(AST::UiSourceElement *ast);
-
- void accept(AST::Node *node);
+ using QQmlJS::AST::Visitor::visit;
+ using QQmlJS::AST::Visitor::endVisit;
+
+ virtual bool visit(QQmlJS::AST::UiArrayMemberList *ast);
+ virtual bool visit(QQmlJS::AST::UiImport *ast);
+ virtual bool visit(QQmlJS::AST::UiPragma *ast);
+ virtual bool visit(QQmlJS::AST::UiHeaderItemList *ast);
+ virtual bool visit(QQmlJS::AST::UiObjectInitializer *ast);
+ virtual bool visit(QQmlJS::AST::UiObjectMemberList *ast);
+ virtual bool visit(QQmlJS::AST::UiParameterList *ast);
+ virtual bool visit(QQmlJS::AST::UiProgram *);
+ virtual bool visit(QQmlJS::AST::UiQualifiedId *ast);
+ virtual bool visit(QQmlJS::AST::UiArrayBinding *ast);
+ virtual bool visit(QQmlJS::AST::UiObjectBinding *ast);
+ virtual bool visit(QQmlJS::AST::UiObjectDefinition *ast);
+ virtual bool visit(QQmlJS::AST::UiPublicMember *ast);
+ virtual bool visit(QQmlJS::AST::UiScriptBinding *ast);
+ virtual bool visit(QQmlJS::AST::UiSourceElement *ast);
+
+ void accept(QQmlJS::AST::Node *node);
// returns index in _objects
- int defineQMLObject(AST::UiQualifiedId *qualifiedTypeNameId, AST::UiObjectInitializer *initializer);
- int defineQMLObject(AST::UiObjectDefinition *node)
- { return defineQMLObject(node->qualifiedTypeNameId, node->initializer); }
+ int defineQMLObject(QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, QmlObject *declarationsOverride = 0);
+ int defineQMLObject(QQmlJS::AST::UiObjectDefinition *node, QmlObject *declarationsOverride = 0)
+ { return defineQMLObject(node->qualifiedTypeNameId, node->qualifiedTypeNameId->firstSourceLocation(), node->initializer, declarationsOverride); }
- static QString asString(AST::UiQualifiedId *node);
- QStringRef asStringRef(AST::Node *node);
+ static QString asString(QQmlJS::AST::UiQualifiedId *node);
+ QStringRef asStringRef(QQmlJS::AST::Node *node);
static void extractVersion(QStringRef string, int *maj, int *min);
- QStringRef textRefAt(const AST::SourceLocation &loc) const
+ QStringRef textRefAt(const QQmlJS::AST::SourceLocation &loc) const
{ return QStringRef(&sourceCode, loc.offset, loc.length); }
- QStringRef textRefAt(const AST::SourceLocation &first,
- const AST::SourceLocation &last) const;
- static QQmlScript::LocationSpan location(AST::UiQualifiedId *id)
+ QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first,
+ const QQmlJS::AST::SourceLocation &last) const;
+ static QQmlScript::LocationSpan location(QQmlJS::AST::UiQualifiedId *id)
{
return location(id->identifierToken, id->identifierToken);
}
- void setBindingValue(QV4::CompiledData::Binding *binding, AST::Statement *statement);
+ void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement);
+
+ void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value);
+ void appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment = false);
+ void appendBinding(const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value);
+ void appendBinding(const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false);
- void appendBinding(AST::UiQualifiedId *name, AST::Statement *value);
- void appendBinding(AST::UiQualifiedId *name, int objectIndex);
- void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, AST::Statement *value);
- void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex, bool isListItem = false);
+ QmlObject *bindingsTarget() const;
- bool setId(AST::Statement *value);
+ bool setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value);
// resolves qualified name (font.pixelSize for example) and returns the last name along
// with the object any right-hand-side of a binding should apply to.
- bool resolveQualifiedId(AST::UiQualifiedId **nameToResolve, QmlObject **object);
+ bool resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, QmlObject **object);
- bool sanityCheckPropertyName(const AST::SourceLocation &nameLocation, int nameIndex, bool isListItem = false);
-
- void recordError(const AST::SourceLocation &location, const QString &description);
+ void recordError(const QQmlJS::AST::SourceLocation &location, const QString &description);
void collectTypeReferences();
- static QQmlScript::LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
+ static QQmlScript::LocationSpan location(QQmlJS::AST::SourceLocation start, QQmlJS::AST::SourceLocation end);
- int registerString(const QString &str) const { return jsGenerator->registerString(str); }
- template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
+ quint32 registerString(const QString &str) const { return jsGenerator->registerString(str); }
+ template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
QString stringAt(int index) const { return jsGenerator->strings.at(index); }
- static bool isStatementNodeScript(AST::Statement *statement);
+ static bool isStatementNodeScript(QQmlJS::AST::Statement *statement);
QList<QQmlError> errors;
+ QSet<QString> illegalNames;
+
QList<QV4::CompiledData::Import*> _imports;
QList<Pragma*> _pragmas;
QList<QmlObject*> _objects;
@@ -288,15 +358,12 @@ public:
QV4::CompiledData::TypeReferenceMap _typeReferences;
QmlObject *_object;
- QSet<QString> _propertyNames;
- QSet<QString> _signalNames;
+ QmlProperty *_propertyDeclaration;
QQmlJS::MemoryPool *pool;
QString sourceCode;
QUrl url;
QV4::Compiler::JSUnitGenerator *jsGenerator;
- int emptyStringIndex;
- bool sanityCheckFunctionNames();
};
struct Q_QML_EXPORT QmlUnitGenerator
@@ -309,6 +376,9 @@ struct Q_QML_EXPORT QmlUnitGenerator
QV4::CompiledData::QmlUnit *generate(ParsedQML &output, const QVector<int> &runtimeFunctionIndices);
private:
+ typedef bool (Binding::*BindingFilter)() const;
+ char *writeBindings(char *bindingPtr, QmlObject *o, const QVector<int> &runtimeFunctionIndices, BindingFilter filter) const;
+
int getStringId(const QString &str) const;
QV4::Compiler::JSUnitGenerator *jsUnitGenerator;
@@ -325,10 +395,10 @@ struct PropertyResolver
return cache->property(index);
}
- QQmlPropertyData *property(const QString &name, bool *notInRevision = 0);
+ QQmlPropertyData *property(const QString &name, bool *notInRevision = 0, QObject *object = 0, QQmlContextData *context = 0);
// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
- QQmlPropertyData *signal(const QString &name, bool *notInRevision);
+ QQmlPropertyData *signal(const QString &name, bool *notInRevision, QObject *object = 0, QQmlContextData *context = 0);
QQmlPropertyCache *cache;
};
@@ -357,12 +427,13 @@ private:
QQmlEnginePrivate *enginePrivate;
ParsedQML *parsedQML;
QQmlCompiledData *unit;
+ const QSet<QString> &illegalNames;
};
struct Q_QML_EXPORT JSCodeGen : public QQmlJS::Codegen
{
- JSCodeGen(const QString &fileName, const QString &sourceCode, V4IR::Module *jsModule,
- QQmlJS::Engine *jsEngine, AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports);
+ JSCodeGen(const QString &fileName, const QString &sourceCode, IR::Module *jsModule,
+ QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports);
struct IdMapping
{
@@ -375,19 +446,19 @@ struct Q_QML_EXPORT JSCodeGen : public QQmlJS::Codegen
void beginContextScope(const ObjectIdMapping &objectIds, QQmlPropertyCache *contextObject);
void beginObjectScope(QQmlPropertyCache *scopeObject);
- // Returns mapping from input functions to index in V4IR::Module::functions / compiledData->runtimeFunctions
+ // Returns mapping from input functions to index in IR::Module::functions / compiledData->runtimeFunctions
QVector<int> generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions);
protected:
virtual void beginFunctionBodyHook();
- virtual V4IR::Expr *fallbackNameLookup(const QString &name, int line, int col);
+ virtual IR::Expr *fallbackNameLookup(const QString &name, int line, int col);
private:
QQmlPropertyData *lookupQmlCompliantProperty(QQmlPropertyCache *cache, const QString &name, bool *propertyExistsButForceNameLookup = 0);
QString sourceCode;
QQmlJS::Engine *jsEngine; // needed for memory pool
- AST::UiProgram *qmlRoot;
+ QQmlJS::AST::UiProgram *qmlRoot;
QQmlTypeNameCache *imports;
bool _disableAcceleratedLookups;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
new file mode 100644
index 0000000000..868c80b47f
--- /dev/null
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -0,0 +1,1951 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmltypecompiler_p.h"
+
+#include <private/qqmlcompiler_p.h>
+#include <private/qqmlobjectcreator_p.h>
+#include <private/qqmlcustomparser_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+#include <private/qqmlcomponent_p.h>
+#include <private/qqmlstringconverters_p.h>
+
+#define COMPILE_EXCEPTION(token, desc) \
+ { \
+ recordError((token)->location, desc); \
+ return false; \
+ }
+
+QT_BEGIN_NAMESPACE
+
+QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlCompiledData *compiledData, QQmlTypeData *typeData, QtQml::ParsedQML *parsedQML)
+ : engine(engine)
+ , compiledData(compiledData)
+ , typeData(typeData)
+ , parsedQML(parsedQML)
+{
+}
+
+bool QQmlTypeCompiler::compile()
+{
+ compiledData->importCache = new QQmlTypeNameCache;
+
+ foreach (const QString &ns, typeData->namespaces())
+ compiledData->importCache->add(ns);
+
+ // Add any Composite Singletons that were used to the import cache
+ foreach (const QQmlTypeData::TypeReference &singleton, typeData->compositeSingletons())
+ compiledData->importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
+
+ typeData->imports().populateCache(compiledData->importCache);
+ compiledData->importCache->addref();
+
+ const QHash<int, QQmlTypeData::TypeReference> &resolvedTypes = typeData->resolvedTypeRefs();
+ for (QHash<int, QQmlTypeData::TypeReference>::ConstIterator resolvedType = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
+ resolvedType != end; ++resolvedType) {
+ QScopedPointer<QQmlCompiledData::TypeReference> ref(new QQmlCompiledData::TypeReference);
+ QQmlType *qmlType = resolvedType->type;
+ if (resolvedType->typeData) {
+ if (resolvedType->needsCreation && qmlType->isCompositeSingleton()) {
+ QQmlError error;
+ QString reason = tr("Composite Singleton Type %1 is not creatable.").arg(qmlType->qmlTypeName());
+ error.setDescription(reason);
+ error.setColumn(resolvedType->location.column);
+ error.setLine(resolvedType->location.line);
+ recordError(error);
+ return false;
+ }
+ ref->component = resolvedType->typeData->compiledData();
+ ref->component->addref();
+ } else if (qmlType) {
+ ref->type = qmlType;
+ Q_ASSERT(ref->type);
+
+ if (resolvedType->needsCreation && !ref->type->isCreatable()) {
+ QQmlError error;
+ QString reason = ref->type->noCreationReason();
+ if (reason.isEmpty())
+ reason = tr("Element is not creatable.");
+ error.setDescription(reason);
+ error.setColumn(resolvedType->location.column);
+ error.setLine(resolvedType->location.line);
+ recordError(error);
+ return false;
+ }
+
+ if (ref->type->containsRevisionedAttributes()) {
+ QQmlError cacheError;
+ ref->typePropertyCache = engine->cache(ref->type,
+ resolvedType->minorVersion,
+ cacheError);
+ if (!ref->typePropertyCache) {
+ cacheError.setColumn(resolvedType->location.column);
+ cacheError.setLine(resolvedType->location.line);
+ recordError(cacheError);
+ return false;
+ }
+ ref->typePropertyCache->addref();
+ }
+ }
+ ref->majorVersion = resolvedType->majorVersion;
+ ref->minorVersion = resolvedType->minorVersion;
+ compiledData->resolvedTypes.insert(resolvedType.key(), ref.take());
+ }
+
+ // Build property caches and VME meta object data
+
+ const int objectCount = parsedQML->objects.count();
+ compiledData->datas.reserve(objectCount);
+ compiledData->propertyCaches.reserve(objectCount);
+
+ {
+ QQmlPropertyCacheCreator propertyCacheBuilder(this);
+ if (!propertyCacheBuilder.buildMetaObjects())
+ return false;
+ }
+
+ {
+ SignalHandlerConverter converter(engine, parsedQML, compiledData);
+ if (!converter.convertSignalHandlerExpressionsToFunctionDeclarations()) {
+ errors << converter.errors;
+ return false;
+ }
+ }
+
+ {
+ QQmlEnumTypeResolver enumResolver(this);
+ if (!enumResolver.resolveEnumBindings())
+ return false;
+ }
+
+ {
+ QQmlAliasAnnotator annotator(this);
+ annotator.annotateBindingsToAliases();
+ }
+
+ // Collect imported scripts
+ const QList<QQmlTypeData::ScriptReference> &scripts = typeData->resolvedScripts();
+ compiledData->scripts.reserve(scripts.count());
+ for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
+ const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
+
+ QString qualifier = script.qualifier;
+ QString enclosingNamespace;
+
+ const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
+ if (lastDotIndex != -1) {
+ enclosingNamespace = qualifier.left(lastDotIndex);
+ qualifier = qualifier.mid(lastDotIndex+1);
+ }
+
+ compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace);
+ QQmlScriptData *scriptData = script.script->scriptData();
+ scriptData->addref();
+ compiledData->scripts << scriptData;
+ }
+
+ // Resolve component boundaries and aliases
+
+ {
+ // Scan for components, determine their scopes and resolve aliases within the scope.
+ QQmlComponentAndAliasResolver resolver(this);
+ if (!resolver.resolve())
+ return false;
+ }
+
+ // Compile JS binding expressions and signal handlers
+
+ JSCodeGen jsCodeGen(typeData->finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, compiledData->importCache);
+ const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions);
+ QList<QQmlError> jsErrors = jsCodeGen.errors();
+ if (!jsErrors.isEmpty()) {
+ errors << jsErrors;
+ return false;
+ }
+
+ QV4::ExecutionEngine *v4 = engine->v4engine();
+
+ QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(engine, v4->executableAllocator, &parsedQML->jsModule, &parsedQML->jsGenerator));
+ isel->setUseFastLookups(false);
+ QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/false);
+
+ // Generate QML compiled type data structures
+
+ QmlUnitGenerator qmlGenerator;
+ QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML, runtimeFunctionIndices);
+
+ if (jsUnit) {
+ Q_ASSERT(!jsUnit->data);
+ jsUnit->ownsData = false;
+ jsUnit->data = &qmlUnit->header;
+ }
+
+ compiledData->compilationUnit = jsUnit;
+ if (compiledData->compilationUnit)
+ compiledData->compilationUnit->ref();
+ compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData
+
+ // Add to type registry of composites
+ if (compiledData->isCompositeType())
+ engine->registerInternalCompositeType(compiledData);
+ else {
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
+ QQmlCompiledData::TypeReference *typeRef = compiledData->resolvedTypes.value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+ if (typeRef->component) {
+ compiledData->metaTypeId = typeRef->component->metaTypeId;
+ compiledData->listMetaTypeId = typeRef->component->listMetaTypeId;
+ } else {
+ compiledData->metaTypeId = typeRef->type->typeId();
+ compiledData->listMetaTypeId = typeRef->type->qListTypeId();
+ }
+ }
+
+ // Sanity check property bindings
+ QQmlPropertyValidator validator(this, runtimeFunctionIndices);
+ if (!validator.validate())
+ return false;
+
+ // Collect some data for instantiation later.
+ int bindingCount = 0;
+ int parserStatusCount = 0;
+ for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
+ bindingCount += obj->nBindings;
+ if (QQmlCompiledData::TypeReference *typeRef = compiledData->resolvedTypes.value(obj->inheritedTypeNameIndex)) {
+ if (QQmlType *qmlType = typeRef->type) {
+ if (qmlType->parserStatusCast() != -1)
+ ++parserStatusCount;
+ }
+ if (typeRef->component) {
+ bindingCount += typeRef->component->totalBindingsCount;
+ parserStatusCount += typeRef->component->totalParserStatusCount;
+ }
+ }
+ }
+
+ compiledData->totalBindingsCount = bindingCount;
+ compiledData->totalParserStatusCount = parserStatusCount;
+
+ return errors.isEmpty();
+}
+
+void QQmlTypeCompiler::recordError(const QQmlError &error)
+{
+ QQmlError e = error;
+ e.setUrl(compiledData->url);
+ errors << e;
+}
+
+QString QQmlTypeCompiler::stringAt(int idx) const
+{
+ return parsedQML->stringAt(idx);
+}
+
+int QQmlTypeCompiler::registerString(const QString &str)
+{
+ return parsedQML->jsGenerator.registerString(str);
+}
+
+const QV4::CompiledData::QmlUnit *QQmlTypeCompiler::qmlUnit() const
+{
+ return compiledData->qmlUnit;
+}
+
+const QQmlImports *QQmlTypeCompiler::imports() const
+{
+ return &typeData->imports();
+}
+
+QHash<int, QQmlCompiledData::TypeReference*> *QQmlTypeCompiler::resolvedTypes()
+{
+ return &compiledData->resolvedTypes;
+}
+
+QList<QmlObject *> *QQmlTypeCompiler::qmlObjects()
+{
+ return &parsedQML->objects;
+}
+
+int QQmlTypeCompiler::rootObjectIndex() const
+{
+ return parsedQML->indexOfRootObject;
+}
+
+void QQmlTypeCompiler::setPropertyCaches(const QVector<QQmlPropertyCache *> &caches)
+{
+ Q_ASSERT(compiledData->propertyCaches.isEmpty());
+ compiledData->propertyCaches = caches;
+ Q_ASSERT(caches.count() >= parsedQML->indexOfRootObject);
+ compiledData->rootPropertyCache = caches.at(parsedQML->indexOfRootObject);
+ compiledData->rootPropertyCache->addref();
+}
+
+const QVector<QQmlPropertyCache *> &QQmlTypeCompiler::propertyCaches() const
+{
+ return compiledData->propertyCaches;
+}
+
+void QQmlTypeCompiler::setVMEMetaObjects(const QVector<QByteArray> &metaObjects)
+{
+ Q_ASSERT(compiledData->datas.isEmpty());
+ compiledData->datas = metaObjects;
+}
+
+QVector<QByteArray> *QQmlTypeCompiler::vmeMetaObjects() const
+{
+ return &compiledData->datas;
+}
+
+QHash<int, int> *QQmlTypeCompiler::objectIndexToIdForRoot()
+{
+ return &compiledData->objectIndexToIdForRoot;
+}
+
+QHash<int, QHash<int, int> > *QQmlTypeCompiler::objectIndexToIdPerComponent()
+{
+ return &compiledData->objectIndexToIdPerComponent;
+}
+
+QHash<int, QByteArray> *QQmlTypeCompiler::customParserData()
+{
+ return &compiledData->customParserData;
+}
+
+QQmlJS::MemoryPool *QQmlTypeCompiler::memoryPool()
+{
+ return parsedQML->jsParserEngine.pool();
+}
+
+const QList<CompiledFunctionOrExpression> &QQmlTypeCompiler::functions() const
+{
+ return parsedQML->functions;
+}
+
+void QQmlTypeCompiler::setCustomParserBindings(const QVector<int> &bindings)
+{
+ compiledData->customParserBindings = bindings;
+}
+
+QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
+ : compiler(typeCompiler)
+{
+}
+
+void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description)
+{
+ QQmlError error;
+ error.setLine(location.line);
+ error.setColumn(location.column);
+ error.setDescription(description);
+ compiler->recordError(error);
+}
+
+static QAtomicInt classIndexCounter(0);
+
+QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlTypeCompiler *typeCompiler)
+ : QQmlCompilePass(typeCompiler)
+ , enginePrivate(typeCompiler->enginePrivate())
+ , qmlObjects(*typeCompiler->qmlObjects())
+ , imports(typeCompiler->imports())
+ , resolvedTypes(typeCompiler->resolvedTypes())
+{
+}
+
+QQmlPropertyCacheCreator::~QQmlPropertyCacheCreator()
+{
+ for (int i = 0; i < propertyCaches.count(); ++i)
+ if (QQmlPropertyCache *cache = propertyCaches.at(i))
+ cache->release();
+ propertyCaches.clear();
+}
+
+bool QQmlPropertyCacheCreator::buildMetaObjects()
+{
+ propertyCaches.resize(qmlObjects.count());
+ vmeMetaObjects.resize(qmlObjects.count());
+
+ if (!buildMetaObjectRecursively(compiler->rootObjectIndex(), /*referencing object*/-1, /*instantiating binding*/0))
+ return false;
+
+ compiler->setVMEMetaObjects(vmeMetaObjects);
+ compiler->setPropertyCaches(propertyCaches);
+ propertyCaches.clear();
+
+ return true;
+}
+
+bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding)
+{
+ const QmlObject *obj = qmlObjects.at(objectIndex);
+
+ QQmlPropertyCache *baseTypeCache = 0;
+ QQmlPropertyData *instantiatingProperty = 0;
+ if (instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
+ Q_ASSERT(referencingObjectIndex >= 0);
+ QQmlPropertyCache *parentCache = propertyCaches.at(referencingObjectIndex);
+ Q_ASSERT(parentCache);
+ Q_ASSERT(instantiatingBinding->propertyNameIndex != 0);
+
+ bool notInRevision = false;
+ instantiatingProperty = PropertyResolver(parentCache).property(stringAt(instantiatingBinding->propertyNameIndex), &notInRevision);
+ if (instantiatingProperty) {
+ if (instantiatingProperty->isQObject()) {
+ baseTypeCache = enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType);
+ Q_ASSERT(baseTypeCache);
+ } else if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(instantiatingProperty->propType)) {
+ baseTypeCache = enginePrivate->cache(vt->metaObject());
+ Q_ASSERT(baseTypeCache);
+ }
+ }
+ }
+
+ bool needVMEMetaObject = obj->propertyCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
+ if (!needVMEMetaObject) {
+ for (const QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ if (binding->type == QV4::CompiledData::Binding::Type_Object && (binding->flags & QV4::CompiledData::Binding::IsOnAssignment)) {
+
+ // On assignments are implemented using value interceptors, which require a VME meta object.
+ needVMEMetaObject = true;
+
+ // If the on assignment is inside a group property, we need to distinguish between QObject based
+ // group properties and value type group properties. For the former the base type is derived from
+ // the property that references us, for the latter we only need a meta-object on the referencing object
+ // because interceptors can't go to the shared value type instances.
+ if (instantiatingProperty && QQmlValueTypeFactory::isValueType(instantiatingProperty->propType)) {
+ needVMEMetaObject = false;
+ if (!ensureMetaObject(referencingObjectIndex))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ if (obj->inheritedTypeNameIndex != 0) {
+ QQmlCompiledData::TypeReference *typeRef = resolvedTypes->value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+ baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ Q_ASSERT(baseTypeCache);
+ }
+
+ if (needVMEMetaObject) {
+ if (!createMetaObject(objectIndex, obj, baseTypeCache))
+ return false;
+ } else if (baseTypeCache) {
+ propertyCaches[objectIndex] = baseTypeCache;
+ baseTypeCache->addref();
+ }
+
+ if (propertyCaches.at(objectIndex)) {
+ for (const QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next)
+ if (binding->type == QV4::CompiledData::Binding::Type_Object || binding->type == QV4::CompiledData::Binding::Type_GroupProperty)
+ if (!buildMetaObjectRecursively(binding->value.objectIndex, objectIndex, binding))
+ return false;
+ }
+
+ return true;
+}
+
+bool QQmlPropertyCacheCreator::ensureMetaObject(int objectIndex)
+{
+ if (!vmeMetaObjects.at(objectIndex).isEmpty())
+ return true;
+ const QtQml::QmlObject *obj = qmlObjects.at(objectIndex);
+ QQmlCompiledData::TypeReference *typeRef = resolvedTypes->value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+ QQmlPropertyCache *baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ return createMetaObject(objectIndex, obj, baseTypeCache);
+}
+
+bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QtQml::QmlObject *obj, QQmlPropertyCache *baseTypeCache)
+{
+ QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate),
+ obj->propertyCount(),
+ obj->functionCount() + obj->propertyCount() + obj->signalCount(),
+ obj->signalCount() + obj->propertyCount());
+ propertyCaches[objectIndex] = cache;
+
+ struct TypeData {
+ QV4::CompiledData::Property::Type dtype;
+ int metaType;
+ } builtinTypes[] = {
+ { QV4::CompiledData::Property::Var, qMetaTypeId<QJSValue>() },
+ { QV4::CompiledData::Property::Variant, QMetaType::QVariant },
+ { QV4::CompiledData::Property::Int, QMetaType::Int },
+ { QV4::CompiledData::Property::Bool, QMetaType::Bool },
+ { QV4::CompiledData::Property::Real, QMetaType::Double },
+ { QV4::CompiledData::Property::String, QMetaType::QString },
+ { QV4::CompiledData::Property::Url, QMetaType::QUrl },
+ { QV4::CompiledData::Property::Color, QMetaType::QColor },
+ { QV4::CompiledData::Property::Font, QMetaType::QFont },
+ { QV4::CompiledData::Property::Time, QMetaType::QTime },
+ { QV4::CompiledData::Property::Date, QMetaType::QDate },
+ { QV4::CompiledData::Property::DateTime, QMetaType::QDateTime },
+ { QV4::CompiledData::Property::Rect, QMetaType::QRectF },
+ { QV4::CompiledData::Property::Point, QMetaType::QPointF },
+ { QV4::CompiledData::Property::Size, QMetaType::QSizeF },
+ { QV4::CompiledData::Property::Vector2D, QMetaType::QVector2D },
+ { QV4::CompiledData::Property::Vector3D, QMetaType::QVector3D },
+ { QV4::CompiledData::Property::Vector4D, QMetaType::QVector4D },
+ { QV4::CompiledData::Property::Matrix4x4, QMetaType::QMatrix4x4 },
+ { QV4::CompiledData::Property::Quaternion, QMetaType::QQuaternion }
+ };
+ static const uint builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
+
+ QByteArray newClassName;
+
+ if (false /* ### compileState->root == obj && !compileState->nested*/) {
+#if 0 // ###
+ QString path = output->url.path();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash > -1) {
+ QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
+ if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
+ newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
+ QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
+ }
+#endif
+ }
+ if (newClassName.isEmpty()) {
+ newClassName = QQmlMetaObject(baseTypeCache).className();
+ newClassName.append("_QML_");
+ newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
+ }
+
+ cache->_dynamicClassName = newClassName;
+
+ int aliasCount = 0;
+ int varPropCount = 0;
+
+ PropertyResolver resolver(baseTypeCache);
+
+ for (const QtQml::QmlProperty *p = obj->firstProperty(); p; p = p->next) {
+ if (p->type == QV4::CompiledData::Property::Alias)
+ aliasCount++;
+ else if (p->type == QV4::CompiledData::Property::Var)
+ varPropCount++;
+
+ // No point doing this for both the alias and non alias cases
+ bool notInRevision = false;
+ QQmlPropertyData *d = resolver.property(stringAt(p->nameIndex), &notInRevision);
+ if (d && d->isFinal())
+ COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
+ }
+
+ typedef QQmlVMEMetaData VMD;
+
+ QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData)
+ + obj->propertyCount() * sizeof(VMD::PropertyData)
+ + obj->functionCount() * sizeof(VMD::MethodData)
+ + aliasCount * sizeof(VMD::AliasData), 0);
+
+ int effectivePropertyIndex = cache->propertyIndexCacheStart;
+ int effectiveMethodIndex = cache->methodIndexCacheStart;
+
+ // For property change signal override detection.
+ // We prepopulate a set of signal names which already exist in the object,
+ // and throw an error if there is a signal/method defined as an override.
+ QSet<QString> seenSignals;
+ seenSignals << QStringLiteral("destroyed") << QStringLiteral("parentChanged") << QStringLiteral("objectNameChanged");
+ QQmlPropertyCache *parentCache = cache;
+ while ((parentCache = parentCache->parent())) {
+ if (int pSigCount = parentCache->signalCount()) {
+ int pSigOffset = parentCache->signalOffset();
+ for (int i = pSigOffset; i < pSigCount; ++i) {
+ QQmlPropertyData *currPSig = parentCache->signal(i);
+ // XXX TODO: find a better way to get signal name from the property data :-/
+ for (QQmlPropertyCache::StringCache::ConstIterator iter = parentCache->stringCache.begin();
+ iter != parentCache->stringCache.end(); ++iter) {
+ if (currPSig == (*iter).second) {
+ seenSignals.insert(iter.key());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // First set up notify signals for properties - first normal, then var, then alias
+ enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
+ for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
+
+ if (ii == NSS_Var && varPropCount == 0) continue;
+ else if (ii == NSS_Alias && aliasCount == 0) continue;
+
+ for (const QtQml::QmlProperty *p = obj->firstProperty(); p; p = p->next) {
+ if ((ii == NSS_Normal && (p->type == QV4::CompiledData::Property::Alias ||
+ p->type == QV4::CompiledData::Property::Var)) ||
+ ((ii == NSS_Var) && (p->type != QV4::CompiledData::Property::Var)) ||
+ ((ii == NSS_Alias) && (p->type != QV4::CompiledData::Property::Alias)))
+ continue;
+
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
+
+ QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
+ seenSignals.insert(changedSigName);
+
+ cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
+ }
+ }
+
+ // Dynamic signals
+ for (const QtQml::Signal *s = obj->firstSignal(); s; s = s->next) {
+ const int paramCount = s->parameters->count;
+
+ QList<QByteArray> names;
+ QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
+
+ if (paramCount) {
+ paramTypes[0] = paramCount;
+
+ QtQml::SignalParameter *param = s->parameters->first;
+ for (int i = 0; i < paramCount; ++i, param = param->next) {
+ names.append(stringAt(param->nameIndex).toUtf8());
+ if (param->type < builtinTypeCount) {
+ // built-in type
+ paramTypes[i + 1] = builtinTypes[param->type].metaType;
+ } else {
+ // lazily resolved type
+ Q_ASSERT(param->type == QV4::CompiledData::Property::Custom);
+ const QString customTypeName = stringAt(param->customTypeNameIndex);
+ QQmlType *qmltype = 0;
+ if (!imports->resolveType(customTypeName, &qmltype, 0, 0, 0))
+ COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(customTypeName));
+
+ if (qmltype->isComposite()) {
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
+
+ QQmlCompiledData *data = tdata->compiledData();
+
+ paramTypes[i + 1] = data->metaTypeId;
+
+ tdata->release();
+ } else {
+ paramTypes[i + 1] = qmltype->typeId();
+ }
+ }
+ }
+ }
+
+ ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
+
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
+ if (paramCount)
+ flags |= QQmlPropertyData::HasArguments;
+
+ QString signalName = stringAt(s->nameIndex);
+ if (seenSignals.contains(signalName))
+ COMPILE_EXCEPTION(s, tr("Duplicate signal name: invalid override of property change signal or superclass signal"));
+ seenSignals.insert(signalName);
+
+ cache->appendSignal(signalName, flags, effectiveMethodIndex++,
+ paramCount?paramTypes.constData():0, names);
+ }
+
+
+ // Dynamic slots
+ for (const QtQml::Function *s = obj->firstFunction(); s; s = s->next) {
+ QQmlJS::AST::FunctionDeclaration *astFunction = s->functionDeclaration;
+
+ quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
+
+ if (astFunction->formals)
+ flags |= QQmlPropertyData::HasArguments;
+
+ QString slotName = astFunction->name.toString();
+ if (seenSignals.contains(slotName))
+ COMPILE_EXCEPTION(s, tr("Duplicate method name: invalid override of property change signal or superclass signal"));
+ // Note: we don't append slotName to the seenSignals list, since we don't
+ // protect against overriding change signals or methods with properties.
+
+ QList<QByteArray> parameterNames;
+ QQmlJS::AST::FormalParameterList *param = astFunction->formals;
+ while (param) {
+ parameterNames << param->name.toUtf8();
+ param = param->next;
+ }
+
+ cache->appendMethod(slotName, flags, effectiveMethodIndex++, parameterNames);
+ }
+
+
+ // Dynamic properties (except var and aliases)
+ int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
+ int propertyIdx = 0;
+ for (const QtQml::QmlProperty *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
+
+ if (p->type == QV4::CompiledData::Property::Alias ||
+ p->type == QV4::CompiledData::Property::Var)
+ continue;
+
+ int propertyType = 0;
+ int vmePropertyType = 0;
+ quint32 propertyFlags = 0;
+
+ if (p->type < builtinTypeCount) {
+ propertyType = builtinTypes[p->type].metaType;
+ vmePropertyType = propertyType;
+
+ if (p->type == QV4::CompiledData::Property::Variant)
+ propertyFlags |= QQmlPropertyData::IsQVariant;
+ } else {
+ Q_ASSERT(p->type == QV4::CompiledData::Property::CustomList ||
+ p->type == QV4::CompiledData::Property::Custom);
+
+ QQmlType *qmltype = 0;
+ if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) {
+ COMPILE_EXCEPTION(p, tr("Invalid property type"));
+ }
+
+ Q_ASSERT(qmltype);
+ if (qmltype->isComposite()) {
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
+
+ QQmlCompiledData *data = tdata->compiledData();
+
+ if (p->type == QV4::CompiledData::Property::Custom) {
+ propertyType = data->metaTypeId;
+ vmePropertyType = QMetaType::QObjectStar;
+ } else {
+ propertyType = data->listMetaTypeId;
+ vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
+ }
+
+ tdata->release();
+ } else {
+ if (p->type == QV4::CompiledData::Property::Custom) {
+ propertyType = qmltype->typeId();
+ vmePropertyType = QMetaType::QObjectStar;
+ } else {
+ propertyType = qmltype->qListTypeId();
+ vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
+ }
+ }
+
+ if (p->type == QV4::CompiledData::Property::Custom)
+ propertyFlags |= QQmlPropertyData::IsQObjectDerived;
+ else
+ propertyFlags |= QQmlPropertyData::IsQList;
+ }
+
+ if ((!p->flags & QV4::CompiledData::Property::IsReadOnly) && p->type != QV4::CompiledData::Property::CustomList)
+ propertyFlags |= QQmlPropertyData::IsWritable;
+
+
+ QString propertyName = stringAt(p->nameIndex);
+ if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ propertyType, effectiveSignalIndex);
+
+ effectiveSignalIndex++;
+
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
+ vmd->propertyCount++;
+ }
+
+ // Now do var properties
+ propertyIdx = 0;
+ for (const QtQml::QmlProperty *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
+
+ if (p->type != QV4::CompiledData::Property::Var)
+ continue;
+
+ quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
+ if (!p->flags & QV4::CompiledData::Property::IsReadOnly)
+ propertyFlags |= QQmlPropertyData::IsWritable;
+
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
+ vmd->propertyCount++;
+ ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
+
+ QString propertyName = stringAt(p->nameIndex);
+ if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ QMetaType::QVariant, effectiveSignalIndex);
+
+ effectiveSignalIndex++;
+ }
+
+ // Alias property count. Actual data is setup in buildDynamicMetaAliases
+ ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
+
+ // Dynamic slot data - comes after the property data
+ for (const QtQml::Function *s = obj->firstFunction(); s; s = s->next) {
+ QQmlJS::AST::FunctionDeclaration *astFunction = s->functionDeclaration;
+ int formalsCount = 0;
+ QQmlJS::AST::FormalParameterList *param = astFunction->formals;
+ while (param) {
+ formalsCount++;
+ param = param->next;
+ }
+
+ VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
+ formalsCount,
+ /* s->location.start.line */0 }; // ###
+
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
+ vmd->methodCount++;
+ md = methodData;
+ }
+
+ return true;
+}
+
+QQmlEnumTypeResolver::QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler)
+ : QQmlCompilePass(typeCompiler)
+ , qmlObjects(*typeCompiler->qmlObjects())
+ , propertyCaches(typeCompiler->propertyCaches())
+ , imports(typeCompiler->imports())
+ , resolvedTypes(typeCompiler->resolvedTypes())
+{
+}
+
+bool QQmlEnumTypeResolver::resolveEnumBindings()
+{
+ for (int i = 0; i < qmlObjects.count(); ++i) {
+ QQmlPropertyCache *propertyCache = propertyCaches.at(i);
+ if (!propertyCache)
+ continue;
+ const QmlObject *obj = qmlObjects.at(i);
+
+ PropertyResolver resolver(propertyCache);
+
+ for (QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
+ if (binding->type != QV4::CompiledData::Binding::Type_Script)
+ continue;
+
+ const QString propertyName = stringAt(binding->propertyNameIndex);
+ bool notInRevision = false;
+ QQmlPropertyData *pd = resolver.property(propertyName, &notInRevision);
+ if (!pd)
+ continue;
+
+ if (!pd->isEnum() && pd->propType != QMetaType::Int)
+ continue;
+
+ if (!tryQualifiedEnumAssignment(obj, propertyCache, pd, binding))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+};
+
+bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlObject *obj, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *prop, Binding *binding)
+{
+ bool isIntProp = (prop->propType == QMetaType::Int) && !prop->isEnum();
+ if (!prop->isEnum() && !isIntProp)
+ return true;
+
+ if (!prop->isWritable() && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration))
+ COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property").arg(stringAt(binding->propertyNameIndex)));
+
+ Q_ASSERT(binding->type = QV4::CompiledData::Binding::Type_Script);
+ QString string = stringAt(binding->stringIndex);
+ if (!string.at(0).isUpper())
+ return true;
+
+ int dot = string.indexOf(QLatin1Char('.'));
+ if (dot == -1 || dot == string.length()-1)
+ return true;
+
+ if (string.indexOf(QLatin1Char('.'), dot+1) != -1)
+ return true;
+
+ QHashedStringRef typeName(string.constData(), dot);
+ QString enumValue = string.mid(dot+1);
+
+ if (isIntProp) {
+ // Allow enum assignment to ints.
+ bool ok;
+ int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok);
+ if (ok) {
+ binding->type = QV4::CompiledData::Binding::Type_Number;
+ binding->value.d = (double)enumval;
+ binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum;
+ }
+ return true;
+ }
+ QQmlType *type = 0;
+ imports->resolveType(typeName, &type, 0, 0, 0);
+
+ if (!type && typeName != QLatin1String("Qt"))
+ return true;
+ if (type && type->isComposite()) //No enums on composite (or composite singleton) types
+ return true;
+
+ int value = 0;
+ bool ok = false;
+
+ QQmlCompiledData::TypeReference *tr = resolvedTypes->value(obj->inheritedTypeNameIndex);
+ if (type && tr && tr->type == type) {
+ QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex);
+
+ // When these two match, we can short cut the search
+ if (mprop.isFlagType()) {
+ value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok);
+ } else {
+ value = mprop.enumerator().keyToValue(enumValue.toUtf8().constData(), &ok);
+ }
+ } else {
+ // Otherwise we have to search the whole type
+ if (type) {
+ value = type->enumValue(QHashedStringRef(enumValue), &ok);
+ } else {
+ QByteArray enumName = enumValue.toUtf8();
+ const QMetaObject *metaObject = StaticQtMetaObject::get();
+ for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ value = e.keyToValue(enumName.constData(), &ok);
+ }
+ }
+ }
+
+ if (!ok)
+ return true;
+
+ binding->type = QV4::CompiledData::Binding::Type_Number;
+ binding->value.d = (double)value;
+ binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum;
+ return true;
+}
+
+int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
+{
+ Q_ASSERT_X(ok, "QQmlEnumTypeResolver::evaluateEnum", "ok must not be a null pointer");
+ *ok = false;
+
+ if (scope != QLatin1String("Qt")) {
+ QQmlType *type = 0;
+ imports->resolveType(scope, &type, 0, 0, 0);
+ return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ }
+
+ const QMetaObject *mo = StaticQtMetaObject::get();
+ int i = mo->enumeratorCount();
+ while (i--) {
+ int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+ if (*ok)
+ return v;
+ }
+ return -1;
+}
+
+
+QQmlAliasAnnotator::QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler)
+ : QQmlCompilePass(typeCompiler)
+ , qmlObjects(*typeCompiler->qmlObjects())
+ , propertyCaches(typeCompiler->propertyCaches())
+{
+}
+
+void QQmlAliasAnnotator::annotateBindingsToAliases()
+{
+ for (int i = 0; i < qmlObjects.count(); ++i) {
+ QQmlPropertyCache *propertyCache = propertyCaches.at(i);
+ if (!propertyCache)
+ continue;
+
+ const QmlObject *obj = qmlObjects.at(i);
+
+ PropertyResolver resolver(propertyCache);
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+
+ for (QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ if (!binding->isValueBinding())
+ continue;
+ bool notInRevision = false;
+ QQmlPropertyData *pd = binding->propertyNameIndex != 0 ? resolver.property(stringAt(binding->propertyNameIndex), &notInRevision) : defaultProperty;
+ if (pd && pd->isAlias())
+ binding->flags |= QV4::CompiledData::Binding::IsBindingToAlias;
+ }
+ }
+}
+
+QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *typeCompiler)
+ : QQmlCompilePass(typeCompiler)
+ , enginePrivate(typeCompiler->enginePrivate())
+ , pool(typeCompiler->memoryPool())
+ , qmlObjects(typeCompiler->qmlObjects())
+ , indexOfRootObject(typeCompiler->rootObjectIndex())
+ , _componentIndex(-1)
+ , _objectIndexToIdInScope(0)
+ , resolvedTypes(typeCompiler->resolvedTypes())
+ , propertyCaches(typeCompiler->propertyCaches())
+ , vmeMetaObjectData(typeCompiler->vmeMetaObjects())
+ , objectIndexToIdForRoot(typeCompiler->objectIndexToIdForRoot())
+ , objectIndexToIdPerComponent(typeCompiler->objectIndexToIdPerComponent())
+{
+}
+
+void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QtQml::QmlObject *obj, int objectIndex)
+{
+ QQmlPropertyCache *propertyCache = propertyCaches.value(objectIndex);
+ if (!propertyCache)
+ return;
+
+ PropertyResolver propertyResolver(propertyCache);
+
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+
+ for (QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Object)
+ continue;
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
+ const QtQml::QmlObject *targetObject = qmlObjects->at(binding->value.objectIndex);
+ QQmlCompiledData::TypeReference *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
+ Q_ASSERT(tr);
+ QQmlType *targetType = tr->type;
+ if (targetType && targetType->metaObject() == &QQmlComponent::staticMetaObject)
+ continue;
+
+ QQmlPropertyData *pd = 0;
+ if (binding->propertyNameIndex != 0) {
+ bool notInRevision = false;
+ pd = propertyResolver.property(stringAt(binding->propertyNameIndex), &notInRevision);
+ } else {
+ pd = defaultProperty;
+ }
+ if (!pd || !pd->isQObject())
+ continue;
+
+ QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType);
+ const QMetaObject *mo = pc->firstCppMetaObject();
+ while (mo) {
+ if (mo == &QQmlComponent::staticMetaObject)
+ break;
+ mo = mo->superClass();
+ }
+
+ if (!mo)
+ continue;
+
+ static QQmlType *componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject);
+ Q_ASSERT(componentType);
+
+ QtQml::QmlObject *syntheticComponent = pool->New<QtQml::QmlObject>();
+ syntheticComponent->init(pool, compiler->registerString(QString::fromUtf8(componentType->typeName())), compiler->registerString(QString()));
+
+ if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
+ QQmlCompiledData::TypeReference *typeRef = new QQmlCompiledData::TypeReference;
+ typeRef->type = componentType;
+ typeRef->majorVersion = componentType->majorVersion();
+ typeRef->minorVersion = componentType->minorVersion();
+ resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef);
+ }
+
+ qmlObjects->append(syntheticComponent);
+ const int componentIndex = qmlObjects->count() - 1;
+
+ QtQml::Binding *syntheticBinding = pool->New<QtQml::Binding>();
+ *syntheticBinding = *binding;
+ syntheticBinding->type = QV4::CompiledData::Binding::Type_Object;
+ QString error = syntheticComponent->appendBinding(syntheticBinding, /*isListBinding*/false);
+ Q_ASSERT(error.isEmpty());
+ Q_UNUSED(error);
+
+ binding->value.objectIndex = componentIndex;
+
+ componentRoots.append(componentIndex);
+ componentBoundaries.append(syntheticBinding->value.objectIndex);
+ }
+}
+
+bool QQmlComponentAndAliasResolver::resolve()
+{
+ // Detect real Component {} objects as well as implicitly defined components, such as
+ // someItemDelegate: Item {}
+ // In the implicit case Item is surrounded by a synthetic Component {} because the property
+ // on the left hand side is of QQmlComponent type.
+ const int objCountWithoutSynthesizedComponents = qmlObjects->count();
+ for (int i = 0; i < objCountWithoutSynthesizedComponents; ++i) {
+ const QtQml::QmlObject *obj = qmlObjects->at(i);
+ if (obj->inheritedTypeNameIndex == 0)
+ continue;
+
+ QQmlCompiledData::TypeReference *tref = resolvedTypes->value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(tref);
+ if (!tref->type || tref->type->metaObject() != &QQmlComponent::staticMetaObject) {
+ findAndRegisterImplicitComponents(obj, i);
+ continue;
+ }
+
+ componentRoots.append(i);
+
+ if (obj->functionCount() > 0)
+ COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
+ if (obj->propertyCount() > 0)
+ COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
+ if (obj->signalCount() > 0)
+ COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
+
+ if (obj->bindingCount() == 0)
+ COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification"));
+
+ const QtQml::Binding *rootBinding = obj->firstBinding();
+ if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
+ COMPILE_EXCEPTION(rootBinding, tr("Component elements may not contain properties other than id"));
+
+ componentBoundaries.append(rootBinding->value.objectIndex);
+ }
+
+ std::sort(componentBoundaries.begin(), componentBoundaries.end());
+
+ for (int i = 0; i < componentRoots.count(); ++i) {
+ const QtQml::QmlObject *component = qmlObjects->at(componentRoots.at(i));
+ const QtQml::Binding *rootBinding = component->firstBinding();
+
+ _componentIndex = i;
+ _idToObjectIndex.clear();
+
+ _objectIndexToIdInScope = &(*objectIndexToIdPerComponent)[componentRoots.at(i)];
+
+ _objectsWithAliases.clear();
+
+ if (!collectIdsAndAliases(rootBinding->value.objectIndex))
+ return false;
+
+ if (!resolveAliases())
+ return false;
+ }
+
+ // Collect ids and aliases for root
+ _componentIndex = -1;
+ _idToObjectIndex.clear();
+ _objectIndexToIdInScope = objectIndexToIdForRoot;
+ _objectsWithAliases.clear();
+
+ collectIdsAndAliases(indexOfRootObject);
+
+ resolveAliases();
+
+ return true;
+}
+
+bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
+{
+ const QtQml::QmlObject *obj = qmlObjects->at(objectIndex);
+
+ if (obj->idIndex != 0) {
+ if (_idToObjectIndex.contains(obj->idIndex)) {
+ recordError(obj->locationOfIdProperty, tr("id is not unique"));
+ return false;
+ }
+ _idToObjectIndex.insert(obj->idIndex, objectIndex);
+ _objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
+ }
+
+ for (const QtQml::QmlProperty *property = obj->firstProperty(); property; property = property->next) {
+ if (property->type == QV4::CompiledData::Property::Alias) {
+ _objectsWithAliases.append(objectIndex);
+ break;
+ }
+ }
+
+ for (const QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Object
+ && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
+ && binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
+ continue;
+
+ // Stop at Component boundary
+ if (std::binary_search(componentBoundaries.constBegin(), componentBoundaries.constEnd(), binding->value.objectIndex))
+ continue;
+
+ if (!collectIdsAndAliases(binding->value.objectIndex))
+ return false;
+ }
+
+ return true;
+}
+
+bool QQmlComponentAndAliasResolver::resolveAliases()
+{
+ foreach (int objectIndex, _objectsWithAliases) {
+ const QtQml::QmlObject *obj = qmlObjects->at(objectIndex);
+
+ QQmlPropertyCache *propertyCache = propertyCaches.value(objectIndex);
+ Q_ASSERT(propertyCache);
+
+ int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.count();
+ int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
+ int effectiveAliasIndex = 0;
+
+ const QtQml::QmlProperty *p = obj->firstProperty();
+ for (int propertyIndex = 0; propertyIndex < obj->propertyCount(); ++propertyIndex, p = p->next) {
+ if (p->type != QV4::CompiledData::Property::Alias)
+ continue;
+
+ const int idIndex = p->aliasIdValueIndex;
+ const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
+ if (targetObjectIndex == -1) {
+ recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
+ return false;
+ }
+ const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
+ Q_ASSERT(targetId != -1);
+
+ const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex);
+
+ QStringRef property;
+ QStringRef subProperty;
+
+ const int propertySeparator = aliasPropertyValue.indexOf(QLatin1Char('.'));
+ if (propertySeparator != -1) {
+ property = aliasPropertyValue.leftRef(propertySeparator);
+ subProperty = aliasPropertyValue.midRef(propertySeparator + 1);
+ } else
+ property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length());
+
+ int propIdx = -1;
+ int propType = 0;
+ int notifySignal = -1;
+ int flags = 0;
+ int type = 0;
+ bool writable = false;
+ bool resettable = false;
+
+ quint32 propertyFlags = QQmlPropertyData::IsAlias;
+
+ if (property.isEmpty()) {
+ const QtQml::QmlObject *targetObject = qmlObjects->at(targetObjectIndex);
+ QQmlCompiledData::TypeReference *typeRef = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+
+ if (typeRef->type)
+ type = typeRef->type->typeId();
+ else
+ type = typeRef->component->metaTypeId;
+
+ flags |= QML_ALIAS_FLAG_PTR;
+ propertyFlags |= QQmlPropertyData::IsQObjectDerived;
+ } else {
+ QQmlPropertyCache *targetCache = propertyCaches.value(targetObjectIndex);
+ Q_ASSERT(targetCache);
+ QtQml::PropertyResolver resolver(targetCache);
+
+ QQmlPropertyData *targetProperty = resolver.property(property.toString());
+ if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
+ recordError(p->aliasLocation, tr("Invalid alias location"));
+ return false;
+ }
+
+ propIdx = targetProperty->coreIndex;
+ type = targetProperty->propType;
+
+ writable = targetProperty->isWritable();
+ resettable = targetProperty->isResettable();
+ notifySignal = targetProperty->notifyIndex;
+
+ if (!subProperty.isEmpty()) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
+ if (!valueType) {
+ recordError(p->aliasLocation, tr("Invalid alias location"));
+ return false;
+ }
+
+ propType = type;
+
+ int valueTypeIndex =
+ valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData());
+ if (valueTypeIndex == -1) {
+ recordError(p->aliasLocation, tr("Invalid alias location"));
+ return false;
+ }
+ Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
+
+ propIdx |= (valueTypeIndex << 16);
+ if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
+ type = QVariant::Int;
+ else
+ type = valueType->metaObject()->property(valueTypeIndex).userType();
+
+ } else {
+ if (targetProperty->isEnum()) {
+ type = QVariant::Int;
+ } else {
+ // Copy type flags
+ propertyFlags |= targetProperty->getFlags() & QQmlPropertyData::PropTypeFlagMask;
+
+ if (targetProperty->isVarProperty())
+ propertyFlags |= QQmlPropertyData::IsQVariant;
+
+ if (targetProperty->isQObject())
+ flags |= QML_ALIAS_FLAG_PTR;
+ }
+ }
+ }
+
+ QQmlVMEMetaData::AliasData aliasData = { targetId, propIdx, propType, flags, notifySignal };
+
+ typedef QQmlVMEMetaData VMD;
+ QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex];
+ Q_ASSERT(!dynamicData.isEmpty());
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ *(vmd->aliasData() + effectiveAliasIndex++) = aliasData;
+
+ Q_ASSERT(dynamicData.isDetached());
+
+ if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
+ propertyFlags |= QQmlPropertyData::IsWritable;
+ else
+ propertyFlags &= ~QQmlPropertyData::IsWritable;
+
+ if (resettable)
+ propertyFlags |= QQmlPropertyData::IsResettable;
+ else
+ propertyFlags &= ~QQmlPropertyData::IsResettable;
+
+ QString propertyName = stringAt(p->nameIndex);
+ if (propertyIndex == obj->indexOfDefaultProperty) propertyCache->_defaultPropertyName = propertyName;
+ propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ type, effectiveSignalIndex++);
+
+ }
+ }
+ return true;
+}
+
+
+QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector<int> &runtimeFunctionIndices)
+ : QQmlCompilePass(typeCompiler)
+ , enginePrivate(typeCompiler->enginePrivate())
+ , qmlUnit(typeCompiler->qmlUnit())
+ , resolvedTypes(*typeCompiler->resolvedTypes())
+ , propertyCaches(typeCompiler->propertyCaches())
+ , objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
+ , customParserData(typeCompiler->customParserData())
+ , runtimeFunctionIndices(runtimeFunctionIndices)
+{
+}
+
+bool QQmlPropertyValidator::validate()
+{
+ if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
+ return false;
+ compiler->setCustomParserBindings(customParserBindings);
+ return true;
+}
+
+const QQmlImports &QQmlPropertyValidator::imports() const
+{
+ return *compiler->imports();
+}
+
+QQmlJS::AST::Node *QQmlPropertyValidator::astForBinding(int scriptIndex) const
+{
+ // ####
+ int reverseIndex = runtimeFunctionIndices.indexOf(scriptIndex);
+ if (reverseIndex == -1)
+ return 0;
+ return compiler->functions().value(reverseIndex).node;
+}
+
+QQmlBinding::Identifier QQmlPropertyValidator::bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *)
+{
+ int id = customParserBindings.count();
+ customParserBindings.append(binding->value.compiledScriptIndex);
+ return id;
+}
+
+bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding)
+{
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
+
+ if (isComponent(objectIndex)) {
+ Q_ASSERT(obj->nBindings == 1);
+ const QV4::CompiledData::Binding *componentBinding = obj->bindingTable();
+ Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
+ return validateObject(componentBinding->value.objectIndex, componentBinding);
+ }
+
+ QQmlPropertyCache *propertyCache = propertyCaches.at(objectIndex);
+ if (!propertyCache)
+ return true;
+
+ QQmlCustomParser *customParser = 0;
+ QQmlCompiledData::TypeReference *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ if (objectType && objectType->type)
+ customParser = objectType->type->customParser();
+ QList<const QV4::CompiledData::Binding*> customBindings;
+
+ PropertyResolver propertyResolver(propertyCache);
+
+ QString defaultPropertyName;
+ QQmlPropertyData *defaultProperty = 0;
+ if (obj->indexOfDefaultProperty != -1) {
+ QQmlPropertyCache *cache = propertyCache->parent();
+ defaultPropertyName = cache->defaultPropertyName();
+ defaultProperty = cache->defaultProperty();
+ } else {
+ defaultPropertyName = propertyCache->defaultPropertyName();
+ defaultProperty = propertyCache->defaultProperty();
+ }
+
+ const QV4::CompiledData::Binding *binding = obj->bindingTable();
+ for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
+
+ if (customParser) {
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
+ customBindings << binding;
+ continue;
+ }
+ } else if ((binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
+ customBindings << binding;
+ continue;
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Object
+ || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
+ customBindings << binding;
+ continue;
+ }
+ }
+
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
+ if (!validateObject(binding->value.objectIndex, binding))
+ return false;
+ // Nothing further to check for attached properties.
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty)
+ continue;
+ }
+
+ // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
+ QString name = stringAt(binding->propertyNameIndex);
+
+ bool bindingToDefaultProperty = false;
+
+ bool notInRevision = false;
+ QQmlPropertyData *pd = 0;
+ if (!name.isEmpty()) {
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ pd = propertyResolver.signal(name, &notInRevision);
+ else
+ pd = propertyResolver.property(name, &notInRevision);
+
+ if (notInRevision) {
+ QString typeName = stringAt(obj->inheritedTypeNameIndex);
+ if (objectType && objectType->type) {
+ COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type->module()).arg(objectType->majorVersion).arg(objectType->minorVersion));
+ } else {
+ COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
+ }
+ }
+ } else {
+ if (instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty)
+ COMPILE_EXCEPTION(binding, tr("Cannot assign a value directly to a grouped property"));
+
+ pd = defaultProperty;
+ name = defaultPropertyName;
+ bindingToDefaultProperty = true;
+ }
+
+ if (pd) {
+ if (!pd->isWritable()
+ && !pd->isQList()
+ && binding->type != QV4::CompiledData::Binding::Type_GroupProperty
+ && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration)
+ ) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name));
+ return false;
+ }
+
+ if (!pd->isQList() && (binding->flags & QV4::CompiledData::Binding::IsListItem)) {
+ QString error;
+ if (pd->propType == qMetaTypeId<QQmlScriptString>())
+ error = tr( "Cannot assign multiple values to a script property");
+ else
+ error = tr( "Cannot assign multiple values to a singular property");
+ recordError(binding->valueLocation, error);
+ return false;
+ }
+
+ if (binding->type < QV4::CompiledData::Binding::Type_Script) {
+ if (!validateLiteralBinding(propertyCache, pd, binding))
+ return false;
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ if (!validateObjectBinding(pd, name, binding))
+ return false;
+ } else if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
+ if (QQmlValueTypeFactory::isValueType(pd->propType)) {
+ if (!QQmlValueTypeFactory::valueType(pd->propType)) {
+ recordError(binding->location, tr("Invalid grouped property access"));
+ return false;
+ }
+ } else {
+ if (!enginePrivate->propertyCacheForType(pd->propType)) {
+ recordError(binding->location, tr("Invalid grouped property access"));
+ return false;
+ }
+ }
+ }
+ } else {
+ if (customParser) {
+ customBindings << binding;
+ continue;
+ }
+ if (bindingToDefaultProperty) {
+ COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent default property"));
+ } else {
+ COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent property \"%1\"").arg(name));
+ }
+ }
+ }
+
+ if (customParser && !customBindings.isEmpty()) {
+ customParser->clearErrors();
+ customParser->compiler = this;
+ QByteArray data = customParser->compile(qmlUnit, customBindings);
+ customParser->compiler = 0;
+ customParserData->insert(objectIndex, data);
+ const QList<QQmlError> parserErrors = customParser->errors();
+ if (!parserErrors.isEmpty()) {
+ foreach (QQmlError error, parserErrors)
+ compiler->recordError(error);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+{
+ if (property->isQList()) {
+ recordError(binding->valueLocation, tr("Cannot assign primitives to lists"));
+ return false;
+ }
+
+ if (property->isEnum()) {
+ if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum)
+ return true;
+
+ QString value = binding->valueAsString(&qmlUnit->header);
+ QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex);
+ bool ok;
+ if (p.isFlagType()) {
+ p.enumerator().keysToValue(value.toUtf8().constData(), &ok);
+ } else
+ p.enumerator().keyToValue(value.toUtf8().constData(), &ok);
+
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration"));
+ return false;
+ }
+ return true;
+ }
+
+ switch (property->propType) {
+ case QMetaType::QVariant:
+ break;
+ case QVariant::String: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: string expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::StringList: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: string or string list expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::ByteArray: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: byte array expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Url: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: url expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::UInt: {
+ if (binding->type == QV4::CompiledData::Binding::Type_Number) {
+ double d = binding->valueAsNumber();
+ if (double(uint(d)) == d)
+ return true;
+ }
+ recordError(binding->valueLocation, tr("Invalid property assignment: unsigned int expected"));
+ return false;
+ }
+ break;
+ case QVariant::Int: {
+ if (binding->type == QV4::CompiledData::Binding::Type_Number) {
+ double d = binding->valueAsNumber();
+ if (double(int(d)) == d)
+ return true;
+ }
+ recordError(binding->valueLocation, tr("Invalid property assignment: int expected"));
+ return false;
+ }
+ break;
+ case QMetaType::Float: {
+ if (binding->type != QV4::CompiledData::Binding::Type_Number) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: number expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Double: {
+ if (binding->type != QV4::CompiledData::Binding::Type_Number) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: number expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Color: {
+ bool ok = false;
+ QQmlStringConverters::rgbaFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: color expected"));
+ return false;
+ }
+ }
+ break;
+#ifndef QT_NO_DATESTRING
+ case QVariant::Date: {
+ bool ok = false;
+ QQmlStringConverters::dateFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: date expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Time: {
+ bool ok = false;
+ QQmlStringConverters::timeFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: time expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::DateTime: {
+ bool ok = false;
+ QQmlStringConverters::dateTimeFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: datetime expected"));
+ return false;
+ }
+ }
+ break;
+#endif // QT_NO_DATESTRING
+ case QVariant::Point: {
+ bool ok = false;
+ QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::PointF: {
+ bool ok = false;
+ QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Size: {
+ bool ok = false;
+ QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::SizeF: {
+ bool ok = false;
+ QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Rect: {
+ bool ok = false;
+ QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: rect expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::RectF: {
+ bool ok = false;
+ QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Bool: {
+ if (binding->type != QV4::CompiledData::Binding::Type_Boolean) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: boolean expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Vector3D: {
+ struct {
+ float xp;
+ float yp;
+ float zy;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: 3D vector expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Vector4D: {
+ struct {
+ float xp;
+ float yp;
+ float zy;
+ float wp;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: 4D vector expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::RegExp:
+ recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
+ return false;
+ default: {
+ // generate single literal value assignment to a list property if required
+ if (property->propType == qMetaTypeId<QList<qreal> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Number) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: real or array of reals expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QList<int> >()) {
+ bool ok = (binding->type == QV4::CompiledData::Binding::Type_Number);
+ if (ok) {
+ double n = binding->valueAsNumber();
+ if (double(int(n)) != n)
+ ok = false;
+ }
+ if (!ok)
+ recordError(binding->valueLocation, tr("Invalid property assignment: int or array of ints expected"));
+ break;
+ } else if (property->propType == qMetaTypeId<QList<bool> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Boolean) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: bool or array of bools expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: url or array of urls expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QList<QString> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: string or array of strings expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QJSValue>()) {
+ break;
+ } else if (property->propType == qMetaTypeId<QQmlScriptString>()) {
+ break;
+ }
+
+ // otherwise, try a custom type assignment
+ QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
+ if (!converter) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType))));
+ return false;
+ }
+ }
+ break;
+ }
+ return true;
+}
+
+/*!
+ Returns true if from can be assigned to a (QObject) property of type
+ to.
+*/
+bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo)
+{
+ QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
+
+ while (fromMo) {
+ if (fromMo == toMo)
+ return true;
+ fromMo = fromMo->parent();
+ }
+ return false;
+}
+
+bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding)
+{
+ if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object);
+
+ bool isValueSource = false;
+ bool isPropertyInterceptor = false;
+
+ QQmlType *qmlType = 0;
+ const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(binding->value.objectIndex);
+ QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex);
+ if (typeRef) {
+ QQmlPropertyCache *cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ const QMetaObject *mo = cache->firstCppMetaObject();
+ while (mo && !qmlType) {
+ qmlType = QQmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ Q_ASSERT(qmlType);
+ }
+
+ if (qmlType) {
+ isValueSource = qmlType->propertyValueSourceCast() != -1;
+ isPropertyInterceptor = qmlType->propertyValueInterceptorCast() != -1;
+ }
+
+ if (!isValueSource && !isPropertyInterceptor) {
+ recordError(binding->valueLocation, tr("\"%1\" cannot operate on \"%2\"").arg(stringAt(targetObject->inheritedTypeNameIndex)).arg(propertyName));
+ return false;
+ }
+
+ return true;
+ }
+ if (isComponent(binding->value.objectIndex))
+ return true;
+
+ if (QQmlMetaType::isInterface(property->propType)) {
+ // Can only check at instantiation time if the created sub-object successfully casts to the
+ // target interface.
+ return true;
+ } else if (property->propType == QMetaType::QVariant) {
+ // We can convert everything to QVariant :)
+ return true;
+ } else if (property->isQList()) {
+ const int listType = enginePrivate->listType(property->propType);
+ if (!QQmlMetaType::isInterface(listType)) {
+ QQmlPropertyCache *source = propertyCaches.value(binding->value.objectIndex);
+ if (!canCoerce(listType, source)) {
+ recordError(binding->valueLocation, tr("Cannot assign object to list"));
+ return false;
+ }
+ }
+ return true;
+ } else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
+ return true;
+ } else if (QQmlValueTypeFactory::isValueType(property->propType)) {
+ recordError(binding->location, tr("Unexpected object assignment"));
+ return false;
+ } else if (property->propType == qMetaTypeId<QQmlScriptString>()) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: script expected"));
+ return false;
+ } else {
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions that might
+ // effect the properties on the type, but don't effect assignability
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
+
+ // Will be true if the assgned type inherits propertyMetaObject
+ bool isAssignable = false;
+ // Determine isAssignable value
+ if (propertyMetaObject) {
+ QQmlPropertyCache *c = propertyCaches.value(binding->value.objectIndex);
+ while (c && !isAssignable) {
+ isAssignable |= c == propertyMetaObject;
+ c = c->parent();
+ }
+ }
+
+ if (!isAssignable) {
+ recordError(binding->valueLocation, tr("Cannot assign object to property"));
+ return false;
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
new file mode 100644
index 0000000000..0a20e0dd54
--- /dev/null
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QQMLTYPECOMPILER_P_H
+#define QQMLTYPECOMPILER_P_H
+
+#include <qglobal.h>
+#include <qqmlerror.h>
+#include <qhash.h>
+#include <private/qqmlcompiler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEnginePrivate;
+class QQmlCompiledData;
+class QQmlError;
+class QQmlTypeData;
+class QQmlImports;
+
+namespace QtQml {
+struct ParsedQML;
+}
+
+namespace QV4 {
+namespace CompiledData {
+struct QmlUnit;
+struct Location;
+}
+}
+
+struct QQmlTypeCompiler
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
+public:
+ QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlCompiledData *compiledData, QQmlTypeData *typeData, QtQml::ParsedQML *parsedQML);
+
+ bool compile();
+
+ QList<QQmlError> compilationErrors() const { return errors; }
+ void recordError(const QQmlError &error);
+
+ QString stringAt(int idx) const;
+ int registerString(const QString &str);
+
+ const QV4::CompiledData::QmlUnit *qmlUnit() const;
+
+ QQmlEnginePrivate *enginePrivate() const { return engine; }
+ const QQmlImports *imports() const;
+ QHash<int, QQmlCompiledData::TypeReference *> *resolvedTypes();
+ QList<QtQml::QmlObject*> *qmlObjects();
+ int rootObjectIndex() const;
+ void setPropertyCaches(const QVector<QQmlPropertyCache *> &caches);
+ const QVector<QQmlPropertyCache *> &propertyCaches() const;
+ void setVMEMetaObjects(const QVector<QByteArray> &metaObjects);
+ QVector<QByteArray> *vmeMetaObjects() const;
+ QHash<int, int> *objectIndexToIdForRoot();
+ QHash<int, QHash<int, int> > *objectIndexToIdPerComponent();
+ QHash<int, QByteArray> *customParserData();
+ QQmlJS::MemoryPool *memoryPool();
+ const QList<CompiledFunctionOrExpression> &functions() const;
+ void setCustomParserBindings(const QVector<int> &bindings);
+
+private:
+ QList<QQmlError> errors;
+ QQmlEnginePrivate *engine;
+ QQmlCompiledData *compiledData;
+ QQmlTypeData *typeData;
+ QtQml::ParsedQML *parsedQML;
+};
+
+struct QQmlCompilePass
+{
+ virtual ~QQmlCompilePass() {}
+
+ QQmlCompilePass(QQmlTypeCompiler *typeCompiler);
+
+ QString stringAt(int idx) const { return compiler->stringAt(idx); }
+protected:
+ void recordError(const QV4::CompiledData::Location &location, const QString &description);
+
+ QQmlTypeCompiler *compiler;
+};
+
+class QQmlPropertyCacheCreator : public QQmlCompilePass
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlPropertyCacheCreator)
+public:
+ QQmlPropertyCacheCreator(QQmlTypeCompiler *typeCompiler);
+ ~QQmlPropertyCacheCreator();
+
+ bool buildMetaObjects();
+protected:
+ bool buildMetaObjectRecursively(int objectIndex, int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding);
+ bool ensureMetaObject(int objectIndex);
+ bool createMetaObject(int objectIndex, const QtQml::QmlObject *obj, QQmlPropertyCache *baseTypeCache);
+
+ QQmlEnginePrivate *enginePrivate;
+ const QList<QtQml::QmlObject*> &qmlObjects;
+ const QQmlImports *imports;
+ QHash<int, QQmlCompiledData::TypeReference*> *resolvedTypes;
+ QVector<QByteArray> vmeMetaObjects;
+ QVector<QQmlPropertyCache*> propertyCaches;
+};
+
+// ### This will go away when the codegen resolves all enums to constant expressions
+// and we replace the constant expression with a literal binding instead of using
+// a script.
+class QQmlEnumTypeResolver : public QQmlCompilePass
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlEnumTypeResolver)
+public:
+ QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler);
+
+ bool resolveEnumBindings();
+
+private:
+ bool tryQualifiedEnumAssignment(const QmlObject *obj, const QQmlPropertyCache *propertyCache,
+ const QQmlPropertyData *prop,
+ QtQml::Binding *binding);
+ int evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const;
+
+
+ const QList<QtQml::QmlObject*> &qmlObjects;
+ const QVector<QQmlPropertyCache *> propertyCaches;
+ const QQmlImports *imports;
+ QHash<int, QQmlCompiledData::TypeReference *> *resolvedTypes;
+};
+
+// Annotate properties bound to aliases with a flag
+class QQmlAliasAnnotator : public QQmlCompilePass
+{
+public:
+ QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler);
+
+ void annotateBindingsToAliases();
+private:
+ const QList<QtQml::QmlObject*> &qmlObjects;
+ const QVector<QQmlPropertyCache *> propertyCaches;
+};
+
+class QQmlComponentAndAliasResolver : public QQmlCompilePass
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlAnonymousComponentResolver)
+public:
+ QQmlComponentAndAliasResolver(QQmlTypeCompiler *typeCompiler);
+
+ bool resolve();
+
+protected:
+ void findAndRegisterImplicitComponents(const QtQml::QmlObject *obj, int objectIndex);
+ bool collectIdsAndAliases(int objectIndex);
+ bool resolveAliases();
+
+ QQmlEnginePrivate *enginePrivate;
+ QQmlJS::MemoryPool *pool;
+
+ QList<QtQml::QmlObject*> *qmlObjects;
+ const int indexOfRootObject;
+
+ // indices of the objects that are actually Component {}
+ QVector<int> componentRoots;
+ // indices of objects that are the beginning of a new component
+ // scope. This is sorted and used for binary search.
+ QVector<int> componentBoundaries;
+
+ int _componentIndex;
+ QHash<int, int> _idToObjectIndex;
+ QHash<int, int> *_objectIndexToIdInScope;
+ QList<int> _objectsWithAliases;
+
+ QHash<int, QQmlCompiledData::TypeReference*> *resolvedTypes;
+ const QVector<QQmlPropertyCache *> propertyCaches;
+ QVector<QByteArray> *vmeMetaObjectData;
+ QHash<int, int> *objectIndexToIdForRoot;
+ QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
+};
+
+class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCompilerBackend
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
+public:
+ QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector<int> &runtimeFunctionIndices);
+
+ bool validate();
+
+ // Re-implemented for QQmlCustomParser
+ virtual const QQmlImports &imports() const;
+ virtual QQmlJS::AST::Node *astForBinding(int scriptIndex) const;
+ virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *parser);
+
+private:
+ bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding);
+ bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
+ bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding);
+
+ bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
+
+ bool canCoerce(int to, QQmlPropertyCache *fromMo);
+
+ QQmlEnginePrivate *enginePrivate;
+ const QV4::CompiledData::QmlUnit *qmlUnit;
+ const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
+ const QVector<QQmlPropertyCache *> &propertyCaches;
+ const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
+ QHash<int, QByteArray> *customParserData;
+ QVector<int> customParserBindings;
+ const QVector<int> &runtimeFunctionIndices;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLTYPECOMPILER_P_H
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index a920f1b419..6685336b5f 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -60,6 +60,7 @@
#undef CONST
#endif
+using namespace QV4;
using namespace QQmlJS;
using namespace AST;
@@ -426,7 +427,7 @@ Codegen::Codegen(bool strict)
void Codegen::generateFromProgram(const QString &fileName,
const QString &sourceCode,
Program *node,
- V4IR::Module *module,
+ QV4::IR::Module *module,
CompilationMode mode,
const QStringList &inheritedLocals)
{
@@ -448,7 +449,7 @@ void Codegen::generateFromProgram(const QString &fileName,
void Codegen::generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,
AST::FunctionExpression *ast,
- V4IR::Module *module)
+ QV4::IR::Module *module)
{
_module = module;
_module->setFileName(fileName);
@@ -479,7 +480,7 @@ void Codegen::leaveEnvironment()
_env = _env->parent;
}
-void Codegen::enterLoop(Statement *node, V4IR::BasicBlock *startBlock, V4IR::BasicBlock *breakBlock, V4IR::BasicBlock *continueBlock)
+void Codegen::enterLoop(Statement *node, IR::BasicBlock *startBlock, IR::BasicBlock *breakBlock, IR::BasicBlock *continueBlock)
{
if (startBlock)
startBlock->markAsGroupStart();
@@ -496,7 +497,7 @@ void Codegen::leaveLoop()
delete current;
}
-V4IR::Expr *Codegen::member(V4IR::Expr *base, const QString *name)
+IR::Expr *Codegen::member(IR::Expr *base, const QString *name)
{
if (hasError)
return 0;
@@ -510,7 +511,7 @@ V4IR::Expr *Codegen::member(V4IR::Expr *base, const QString *name)
}
}
-V4IR::Expr *Codegen::subscript(V4IR::Expr *base, V4IR::Expr *index)
+IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index)
{
if (hasError)
return 0;
@@ -531,7 +532,7 @@ V4IR::Expr *Codegen::subscript(V4IR::Expr *base, V4IR::Expr *index)
return _block->SUBSCRIPT(base->asTemp(), index->asTemp());
}
-V4IR::Expr *Codegen::argument(V4IR::Expr *expr)
+IR::Expr *Codegen::argument(IR::Expr *expr)
{
if (expr && ! expr->asTemp()) {
const unsigned t = _block->newTemp();
@@ -542,7 +543,7 @@ V4IR::Expr *Codegen::argument(V4IR::Expr *expr)
}
// keeps references alive, converts other expressions to temps
-V4IR::Expr *Codegen::reference(V4IR::Expr *expr)
+IR::Expr *Codegen::reference(IR::Expr *expr)
{
if (hasError)
return 0;
@@ -555,29 +556,29 @@ V4IR::Expr *Codegen::reference(V4IR::Expr *expr)
return expr;
}
-V4IR::Expr *Codegen::unop(V4IR::AluOp op, V4IR::Expr *expr)
+IR::Expr *Codegen::unop(IR::AluOp op, IR::Expr *expr)
{
if (hasError)
return 0;
- Q_ASSERT(op != V4IR::OpIncrement);
- Q_ASSERT(op != V4IR::OpDecrement);
+ Q_ASSERT(op != IR::OpIncrement);
+ Q_ASSERT(op != IR::OpDecrement);
- if (V4IR::Const *c = expr->asConst()) {
- if (c->type == V4IR::NumberType) {
+ if (IR::Const *c = expr->asConst()) {
+ if (c->type == IR::NumberType) {
switch (op) {
- case V4IR::OpNot:
- return _block->CONST(V4IR::BoolType, !c->value);
- case V4IR::OpUMinus:
- return _block->CONST(V4IR::NumberType, -c->value);
- case V4IR::OpUPlus:
+ case IR::OpNot:
+ return _block->CONST(IR::BoolType, !c->value);
+ case IR::OpUMinus:
+ return _block->CONST(IR::NumberType, -c->value);
+ case IR::OpUPlus:
return expr;
- case V4IR::OpCompl:
- return _block->CONST(V4IR::NumberType, ~QV4::Primitive::toInt32(c->value));
- case V4IR::OpIncrement:
- return _block->CONST(V4IR::NumberType, c->value + 1);
- case V4IR::OpDecrement:
- return _block->CONST(V4IR::NumberType, c->value - 1);
+ case IR::OpCompl:
+ return _block->CONST(IR::NumberType, ~QV4::Primitive::toInt32(c->value));
+ case IR::OpIncrement:
+ return _block->CONST(IR::NumberType, c->value + 1);
+ case IR::OpDecrement:
+ return _block->CONST(IR::NumberType, c->value - 1);
default:
break;
}
@@ -592,56 +593,56 @@ V4IR::Expr *Codegen::unop(V4IR::AluOp op, V4IR::Expr *expr)
return _block->UNOP(op, expr->asTemp());
}
-V4IR::Expr *Codegen::binop(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right)
+IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
{
if (hasError)
return 0;
- if (V4IR::Const *c1 = left->asConst()) {
- if (V4IR::Const *c2 = right->asConst()) {
- if (c1->type == V4IR::NumberType && c2->type == V4IR::NumberType) {
+ if (IR::Const *c1 = left->asConst()) {
+ if (IR::Const *c2 = right->asConst()) {
+ if (c1->type == IR::NumberType && c2->type == IR::NumberType) {
switch (op) {
- case V4IR::OpAdd: return _block->CONST(V4IR::NumberType, c1->value + c2->value);
- case V4IR::OpAnd: return _block->CONST(V4IR::BoolType, c1->value ? c2->value : 0);
- case V4IR::OpBitAnd: return _block->CONST(V4IR::NumberType, int(c1->value) & int(c2->value));
- case V4IR::OpBitOr: return _block->CONST(V4IR::NumberType, int(c1->value) | int(c2->value));
- case V4IR::OpBitXor: return _block->CONST(V4IR::NumberType, int(c1->value) ^ int(c2->value));
- case V4IR::OpDiv: return _block->CONST(V4IR::NumberType, c1->value / c2->value);
- case V4IR::OpEqual: return _block->CONST(V4IR::BoolType, c1->value == c2->value);
- case V4IR::OpNotEqual: return _block->CONST(V4IR::BoolType, c1->value != c2->value);
- case V4IR::OpStrictEqual: return _block->CONST(V4IR::BoolType, c1->value == c2->value);
- case V4IR::OpStrictNotEqual: return _block->CONST(V4IR::BoolType, c1->value != c2->value);
- case V4IR::OpGe: return _block->CONST(V4IR::BoolType, c1->value >= c2->value);
- case V4IR::OpGt: return _block->CONST(V4IR::BoolType, c1->value > c2->value);
- case V4IR::OpLe: return _block->CONST(V4IR::BoolType, c1->value <= c2->value);
- case V4IR::OpLt: return _block->CONST(V4IR::BoolType, c1->value < c2->value);
- case V4IR::OpLShift: return _block->CONST(V4IR::NumberType, QV4::Primitive::toInt32(c1->value) << (QV4::Primitive::toUInt32(c2->value) & 0x1f));
- case V4IR::OpMod: return _block->CONST(V4IR::NumberType, std::fmod(c1->value, c2->value));
- case V4IR::OpMul: return _block->CONST(V4IR::NumberType, c1->value * c2->value);
- case V4IR::OpOr: return _block->CONST(V4IR::NumberType, c1->value ? c1->value : c2->value);
- case V4IR::OpRShift: return _block->CONST(V4IR::NumberType, QV4::Primitive::toInt32(c1->value) >> (QV4::Primitive::toUInt32(c2->value) & 0x1f));
- case V4IR::OpSub: return _block->CONST(V4IR::NumberType, c1->value - c2->value);
- case V4IR::OpURShift: return _block->CONST(V4IR::NumberType,QV4::Primitive::toUInt32(c1->value) >> (QV4::Primitive::toUInt32(c2->value) & 0x1f));
-
- case V4IR::OpInstanceof:
- case V4IR::OpIn:
+ case IR::OpAdd: return _block->CONST(IR::NumberType, c1->value + c2->value);
+ case IR::OpAnd: return _block->CONST(IR::BoolType, c1->value ? c2->value : 0);
+ case IR::OpBitAnd: return _block->CONST(IR::NumberType, int(c1->value) & int(c2->value));
+ case IR::OpBitOr: return _block->CONST(IR::NumberType, int(c1->value) | int(c2->value));
+ case IR::OpBitXor: return _block->CONST(IR::NumberType, int(c1->value) ^ int(c2->value));
+ case IR::OpDiv: return _block->CONST(IR::NumberType, c1->value / c2->value);
+ case IR::OpEqual: return _block->CONST(IR::BoolType, c1->value == c2->value);
+ case IR::OpNotEqual: return _block->CONST(IR::BoolType, c1->value != c2->value);
+ case IR::OpStrictEqual: return _block->CONST(IR::BoolType, c1->value == c2->value);
+ case IR::OpStrictNotEqual: return _block->CONST(IR::BoolType, c1->value != c2->value);
+ case IR::OpGe: return _block->CONST(IR::BoolType, c1->value >= c2->value);
+ case IR::OpGt: return _block->CONST(IR::BoolType, c1->value > c2->value);
+ case IR::OpLe: return _block->CONST(IR::BoolType, c1->value <= c2->value);
+ case IR::OpLt: return _block->CONST(IR::BoolType, c1->value < c2->value);
+ case IR::OpLShift: return _block->CONST(IR::NumberType, QV4::Primitive::toInt32(c1->value) << (QV4::Primitive::toUInt32(c2->value) & 0x1f));
+ case IR::OpMod: return _block->CONST(IR::NumberType, std::fmod(c1->value, c2->value));
+ case IR::OpMul: return _block->CONST(IR::NumberType, c1->value * c2->value);
+ case IR::OpOr: return _block->CONST(IR::NumberType, c1->value ? c1->value : c2->value);
+ case IR::OpRShift: return _block->CONST(IR::NumberType, QV4::Primitive::toInt32(c1->value) >> (QV4::Primitive::toUInt32(c2->value) & 0x1f));
+ case IR::OpSub: return _block->CONST(IR::NumberType, c1->value - c2->value);
+ case IR::OpURShift: return _block->CONST(IR::NumberType,QV4::Primitive::toUInt32(c1->value) >> (QV4::Primitive::toUInt32(c2->value) & 0x1f));
+
+ case IR::OpInstanceof:
+ case IR::OpIn:
break;
- case V4IR::OpIfTrue: // unary ops
- case V4IR::OpNot:
- case V4IR::OpUMinus:
- case V4IR::OpUPlus:
- case V4IR::OpCompl:
- case V4IR::OpIncrement:
- case V4IR::OpDecrement:
- case V4IR::OpInvalid:
+ case IR::OpIfTrue: // unary ops
+ case IR::OpNot:
+ case IR::OpUMinus:
+ case IR::OpUPlus:
+ case IR::OpCompl:
+ case IR::OpIncrement:
+ case IR::OpDecrement:
+ case IR::OpInvalid:
break;
}
}
}
- } else if (op == V4IR::OpAdd) {
- if (V4IR::String *s1 = left->asString()) {
- if (V4IR::String *s2 = right->asString()) {
+ } else if (op == IR::OpAdd) {
+ if (IR::String *s1 = left->asString()) {
+ if (IR::String *s2 = right->asString()) {
return _block->STRING(_function->newString(*s1->value + *s2->value));
}
}
@@ -665,7 +666,7 @@ V4IR::Expr *Codegen::binop(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right)
return _block->BINOP(op, left, right);
}
-V4IR::Expr *Codegen::call(V4IR::Expr *base, V4IR::ExprList *args)
+IR::Expr *Codegen::call(IR::Expr *base, IR::ExprList *args)
{
if (hasError)
return 0;
@@ -673,14 +674,14 @@ V4IR::Expr *Codegen::call(V4IR::Expr *base, V4IR::ExprList *args)
return _block->CALL(base, args);
}
-void Codegen::move(V4IR::Expr *target, V4IR::Expr *source, V4IR::AluOp op)
+void Codegen::move(IR::Expr *target, IR::Expr *source, IR::AluOp op)
{
if (hasError)
return;
Q_ASSERT(target->isLValue());
- if (op != V4IR::OpInvalid) {
+ if (op != IR::OpInvalid) {
move(target, binop(op, target, source));
return;
}
@@ -699,7 +700,7 @@ void Codegen::move(V4IR::Expr *target, V4IR::Expr *source, V4IR::AluOp op)
_block->MOVE(target, source);
}
-void Codegen::cjump(V4IR::Expr *cond, V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse)
+void Codegen::cjump(IR::Expr *cond, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
{
if (hasError)
return;
@@ -751,7 +752,7 @@ void Codegen::statement(ExpressionNode *ast)
}
}
-void Codegen::condition(ExpressionNode *ast, V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse)
+void Codegen::condition(ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
{
if (ast) {
Result r(iftrue, iffalse);
@@ -832,7 +833,7 @@ void Codegen::sourceElements(SourceElements *ast)
void Codegen::variableDeclaration(VariableDeclaration *ast)
{
- V4IR::Expr *initializer = 0;
+ IR::Expr *initializer = 0;
if (!ast->expression)
return;
Result expr = expression(ast->expression);
@@ -1044,22 +1045,22 @@ bool Codegen::visit(ArrayLiteral *ast)
if (hasError)
return false;
- V4IR::ExprList *args = 0;
- V4IR::ExprList *current = 0;
+ IR::ExprList *args = 0;
+ IR::ExprList *current = 0;
for (ElementList *it = ast->elements; it; it = it->next) {
for (Elision *elision = it->elision; elision; elision = elision->next) {
- V4IR::ExprList *arg = _function->New<V4IR::ExprList>();
+ IR::ExprList *arg = _function->New<IR::ExprList>();
if (!current) {
args = arg;
} else {
current->next = arg;
}
current = arg;
- current->expr = _block->CONST(V4IR::MissingType, 0);
+ current->expr = _block->CONST(IR::MissingType, 0);
}
Result expr = expression(it->expression);
- V4IR::ExprList *arg = _function->New<V4IR::ExprList>();
+ IR::ExprList *arg = _function->New<IR::ExprList>();
if (!current) {
args = arg;
} else {
@@ -1067,7 +1068,7 @@ bool Codegen::visit(ArrayLiteral *ast)
}
current = arg;
- V4IR::Expr *exp = *expr;
+ IR::Expr *exp = *expr;
if (exp->asTemp() || exp->asConst()) {
current->expr = exp;
} else {
@@ -1077,18 +1078,18 @@ bool Codegen::visit(ArrayLiteral *ast)
}
}
for (Elision *elision = ast->elision; elision; elision = elision->next) {
- V4IR::ExprList *arg = _function->New<V4IR::ExprList>();
+ IR::ExprList *arg = _function->New<IR::ExprList>();
if (!current) {
args = arg;
} else {
current->next = arg;
}
current = arg;
- current->expr = _block->CONST(V4IR::MissingType, 0);
+ current->expr = _block->CONST(IR::MissingType, 0);
}
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), _block->CALL(_block->NAME(V4IR::Name::builtin_define_array, 0, 0), args));
+ move(_block->TEMP(t), _block->CALL(_block->NAME(IR::Name::builtin_define_array, 0, 0), args));
_expr.code = _block->TEMP(t);
return false;
}
@@ -1104,21 +1105,21 @@ bool Codegen::visit(ArrayMemberExpression *ast)
return false;
}
-static V4IR::AluOp baseOp(int op)
+static IR::AluOp baseOp(int op)
{
switch ((QSOperator::Op) op) {
- case QSOperator::InplaceAnd: return V4IR::OpBitAnd;
- case QSOperator::InplaceSub: return V4IR::OpSub;
- case QSOperator::InplaceDiv: return V4IR::OpDiv;
- case QSOperator::InplaceAdd: return V4IR::OpAdd;
- case QSOperator::InplaceLeftShift: return V4IR::OpLShift;
- case QSOperator::InplaceMod: return V4IR::OpMod;
- case QSOperator::InplaceMul: return V4IR::OpMul;
- case QSOperator::InplaceOr: return V4IR::OpBitOr;
- case QSOperator::InplaceRightShift: return V4IR::OpRShift;
- case QSOperator::InplaceURightShift: return V4IR::OpURShift;
- case QSOperator::InplaceXor: return V4IR::OpBitXor;
- default: return V4IR::OpInvalid;
+ case QSOperator::InplaceAnd: return IR::OpBitAnd;
+ case QSOperator::InplaceSub: return IR::OpSub;
+ case QSOperator::InplaceDiv: return IR::OpDiv;
+ case QSOperator::InplaceAdd: return IR::OpAdd;
+ case QSOperator::InplaceLeftShift: return IR::OpLShift;
+ case QSOperator::InplaceMod: return IR::OpMod;
+ case QSOperator::InplaceMul: return IR::OpMul;
+ case QSOperator::InplaceOr: return IR::OpBitOr;
+ case QSOperator::InplaceRightShift: return IR::OpRShift;
+ case QSOperator::InplaceURightShift: return IR::OpURShift;
+ case QSOperator::InplaceXor: return IR::OpBitXor;
+ default: return IR::OpInvalid;
}
}
@@ -1129,13 +1130,13 @@ bool Codegen::visit(BinaryExpression *ast)
if (ast->op == QSOperator::And) {
if (_expr.accept(cx)) {
- V4IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
condition(ast->left, iftrue, _expr.iffalse);
_block = iftrue;
condition(ast->right, _expr.iftrue, _expr.iffalse);
} else {
- V4IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
const unsigned r = _block->newTemp();
@@ -1151,13 +1152,13 @@ bool Codegen::visit(BinaryExpression *ast)
return false;
} else if (ast->op == QSOperator::Or) {
if (_expr.accept(cx)) {
- V4IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
condition(ast->left, _expr.iftrue, iffalse);
_block = iffalse;
condition(ast->right, _expr.iftrue, _expr.iffalse);
} else {
- V4IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
const unsigned r = _block->newTemp();
move(_block->TEMP(r), *expression(ast->left));
@@ -1172,7 +1173,7 @@ bool Codegen::visit(BinaryExpression *ast)
return false;
}
- V4IR::Expr* left = *expression(ast->left);
+ IR::Expr* left = *expression(ast->left);
switch (ast->op) {
case QSOperator::Or:
@@ -1182,7 +1183,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::Assign: {
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
- V4IR::Expr* right = *expression(ast->right);
+ IR::Expr* right = *expression(ast->right);
if (!left->isLValue()) {
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
return false;
@@ -1212,7 +1213,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::InplaceXor: {
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
- V4IR::Expr* right = *expression(ast->right);
+ IR::Expr* right = *expression(ast->right);
if (!left->isLValue()) {
throwSyntaxError(ast->operatorToken, QStringLiteral("left-hand side of inplace operator is not an lvalue"));
return false;
@@ -1245,12 +1246,12 @@ bool Codegen::visit(BinaryExpression *ast)
left = _block->TEMP(t);
}
- V4IR::Expr* right = *expression(ast->right);
+ IR::Expr* right = *expression(ast->right);
if (_expr.accept(cx)) {
- cjump(binop(V4IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
+ cjump(binop(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
} else {
- V4IR::Expr *e = binop(V4IR::binaryOperator(ast->op), left, right);
+ IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right);
if (e->asConst() || e->asString())
_expr.code = e;
else {
@@ -1279,9 +1280,9 @@ bool Codegen::visit(BinaryExpression *ast)
left = _block->TEMP(t);
}
- V4IR::Expr* right = *expression(ast->right);
+ IR::Expr* right = *expression(ast->right);
- V4IR::Expr *e = binop(V4IR::binaryOperator(ast->op), left, right);
+ IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right);
if (e->asConst() || e->asString())
_expr.code = e;
else {
@@ -1303,11 +1304,11 @@ bool Codegen::visit(CallExpression *ast)
return false;
Result base = expression(ast->base);
- V4IR::ExprList *args = 0, **args_it = &args;
+ IR::ExprList *args = 0, **args_it = &args;
for (ArgumentList *it = ast->arguments; it; it = it->next) {
Result arg = expression(it->expression);
- V4IR::Expr *actual = argument(*arg);
- *args_it = _function->New<V4IR::ExprList>();
+ IR::Expr *actual = argument(*arg);
+ *args_it = _function->New<IR::ExprList>();
(*args_it)->init(actual);
args_it = &(*args_it)->next;
}
@@ -1320,9 +1321,9 @@ bool Codegen::visit(ConditionalExpression *ast)
if (hasError)
return true;
- V4IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
const unsigned t = _block->newTemp();
@@ -1348,16 +1349,16 @@ bool Codegen::visit(DeleteExpression *ast)
if (hasError)
return false;
- V4IR::Expr* expr = *expression(ast->expression);
+ IR::Expr* expr = *expression(ast->expression);
// Temporaries cannot be deleted
- V4IR::Temp *t = expr->asTemp();
+ IR::Temp *t = expr->asTemp();
if (t && t->index < static_cast<unsigned>(_env->members.size())) {
// Trying to delete a function argument might throw.
if (_function->isStrict) {
throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode."));
return false;
}
- _expr.code = _block->CONST(V4IR::BoolType, 0);
+ _expr.code = _block->CONST(IR::BoolType, 0);
return false;
}
if (_function->isStrict && expr->asName()) {
@@ -1367,7 +1368,7 @@ bool Codegen::visit(DeleteExpression *ast)
// [[11.4.1]] Return true if it's not a reference
if (expr->asConst() || expr->asString()) {
- _expr.code = _block->CONST(V4IR::BoolType, 1);
+ _expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
@@ -1375,17 +1376,17 @@ bool Codegen::visit(DeleteExpression *ast)
// perform the call to allow for side effects.
if (expr->asCall()) {
_block->EXP(expr);
- _expr.code = _block->CONST(V4IR::BoolType, 1);
+ _expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
if (expr->asTemp() && expr->asTemp()->index >= static_cast<unsigned>(_env->members.size())) {
- _expr.code = _block->CONST(V4IR::BoolType, 1);
+ _expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
- V4IR::ExprList *args = _function->New<V4IR::ExprList>();
+ IR::ExprList *args = _function->New<IR::ExprList>();
args->init(reference(expr));
- _expr.code = call(_block->NAME(V4IR::Name::builtin_delete, ast->deleteToken.startLine, ast->deleteToken.startColumn), args);
+ _expr.code = call(_block->NAME(IR::Name::builtin_delete, ast->deleteToken.startLine, ast->deleteToken.startColumn), args);
return false;
}
@@ -1397,7 +1398,7 @@ bool Codegen::visit(FalseLiteral *)
if (_expr.accept(cx)) {
_block->JUMP(_expr.iffalse);
} else {
- _expr.code = _block->CONST(V4IR::BoolType, 0);
+ _expr.code = _block->CONST(IR::BoolType, 0);
}
return false;
}
@@ -1422,14 +1423,14 @@ bool Codegen::visit(FunctionExpression *ast)
return false;
}
-V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
+IR::Expr *Codegen::identifier(const QString &name, int line, int col)
{
if (hasError)
return 0;
uint scope = 0;
Environment *e = _env;
- V4IR::Function *f = _function;
+ IR::Function *f = _function;
while (f && e->parent) {
if (f->insideWithOrCatch || (f->isNamedExpression && f->name == name))
@@ -1438,7 +1439,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
int index = e->findMember(name);
Q_ASSERT (index < e->members.size());
if (index != -1) {
- V4IR::Temp *t = _block->LOCAL(index, scope);
+ IR::Temp *t = _block->LOCAL(index, scope);
if (name == QStringLiteral("arguments") || name == QStringLiteral("eval"))
t->isArgumentsOrEval = true;
return t;
@@ -1456,7 +1457,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
}
// This hook allows implementing QML lookup semantics
- if (V4IR::Expr *fallback = fallbackNameLookup(name, line, col))
+ if (IR::Expr *fallback = fallbackNameLookup(name, line, col))
return fallback;
if (!e->parent && (!f || !f->insideWithOrCatch) && _env->compilationMode != EvalCode && e->compilationMode != QmlBinding)
@@ -1467,7 +1468,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
}
-V4IR::Expr *Codegen::fallbackNameLookup(const QString &name, int line, int col)
+IR::Expr *Codegen::fallbackNameLookup(const QString &name, int line, int col)
{
Q_UNUSED(name)
Q_UNUSED(line)
@@ -1499,7 +1500,7 @@ bool Codegen::visit(NewExpression *ast)
return false;
Result base = expression(ast->expression);
- V4IR::Expr *expr = *base;
+ IR::Expr *expr = *base;
if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
@@ -1515,18 +1516,18 @@ bool Codegen::visit(NewMemberExpression *ast)
return false;
Result base = expression(ast->base);
- V4IR::Expr *expr = *base;
+ IR::Expr *expr = *base;
if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
}
- V4IR::ExprList *args = 0, **args_it = &args;
+ IR::ExprList *args = 0, **args_it = &args;
for (ArgumentList *it = ast->arguments; it; it = it->next) {
Result arg = expression(it->expression);
- V4IR::Expr *actual = argument(*arg);
- *args_it = _function->New<V4IR::ExprList>();
+ IR::Expr *actual = argument(*arg);
+ *args_it = _function->New<IR::ExprList>();
(*args_it)->init(actual);
args_it = &(*args_it)->next;
}
@@ -1543,7 +1544,7 @@ bool Codegen::visit(NotExpression *ast)
Result expr = expression(ast->expression);
const unsigned r = _block->newTemp();
- move(_block->TEMP(r), unop(V4IR::OpNot, *expr));
+ move(_block->TEMP(r), unop(IR::OpNot, *expr));
_expr.code = _block->TEMP(r);
return false;
}
@@ -1554,7 +1555,7 @@ bool Codegen::visit(NullExpression *)
return false;
if (_expr.accept(cx)) _block->JUMP(_expr.iffalse);
- else _expr.code = _block->CONST(V4IR::NullType, 0);
+ else _expr.code = _block->CONST(IR::NullType, 0);
return false;
}
@@ -1568,7 +1569,7 @@ bool Codegen::visit(NumericLiteral *ast)
if (ast->value) _block->JUMP(_expr.iftrue);
else _block->JUMP(_expr.iffalse);
} else {
- _expr.code = _block->CONST(V4IR::NumberType, ast->value);
+ _expr.code = _block->CONST(IR::NumberType, ast->value);
}
return false;
}
@@ -1580,7 +1581,7 @@ struct ObjectPropertyValue {
, setter(-1)
{}
- V4IR::Expr *value;
+ IR::Expr *value;
int getter; // index in _module->functions or -1 if not set
int setter;
@@ -1627,10 +1628,10 @@ bool Codegen::visit(ObjectLiteral *ast)
}
}
- V4IR::ExprList *args = 0;
+ IR::ExprList *args = 0;
if (!valueMap.isEmpty()) {
- V4IR::ExprList *current;
+ IR::ExprList *current;
for (QMap<QString, ObjectPropertyValue>::iterator it = valueMap.begin(); it != valueMap.end(); ) {
if (QV4::String::toArrayIndex(it.key()) != UINT_MAX) {
++it;
@@ -1638,40 +1639,40 @@ bool Codegen::visit(ObjectLiteral *ast)
}
if (!args) {
- args = _function->New<V4IR::ExprList>();
+ args = _function->New<IR::ExprList>();
current = args;
} else {
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
}
current->expr = _block->NAME(it.key(), 0, 0);
if (it->value) {
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
- current->expr = _block->CONST(V4IR::BoolType, true);
+ current->expr = _block->CONST(IR::BoolType, true);
unsigned value = _block->newTemp();
move(_block->TEMP(value), it->value);
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
current->expr = _block->TEMP(value);
} else {
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
- current->expr = _block->CONST(V4IR::BoolType, false);
+ current->expr = _block->CONST(IR::BoolType, false);
unsigned getter = _block->newTemp();
unsigned setter = _block->newTemp();
- move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(V4IR::UndefinedType, 0));
- move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(V4IR::UndefinedType, 0));
+ move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(IR::UndefinedType, 0));
+ move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(IR::UndefinedType, 0));
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
current->expr = _block->TEMP(getter);
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
current->expr = _block->TEMP(setter);
}
@@ -1681,7 +1682,7 @@ bool Codegen::visit(ObjectLiteral *ast)
}
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), _block->CALL(_block->NAME(V4IR::Name::builtin_define_object_literal,
+ move(_block->TEMP(t), _block->CALL(_block->NAME(IR::Name::builtin_define_object_literal,
ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), args));
// What's left are array entries
@@ -1690,13 +1691,13 @@ bool Codegen::visit(ObjectLiteral *ast)
unsigned getter = 0;
unsigned setter = 0;
for (QMap<QString, ObjectPropertyValue>::const_iterator it = valueMap.constBegin(); it != valueMap.constEnd(); ++it) {
- V4IR::ExprList *args = _function->New<V4IR::ExprList>();
- V4IR::ExprList *current = args;
+ IR::ExprList *args = _function->New<IR::ExprList>();
+ IR::ExprList *current = args;
current->expr = _block->TEMP(t);
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
current->expr = _block->NAME(it.key(), 0, 0);
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
if (it->value) {
@@ -1705,22 +1706,22 @@ bool Codegen::visit(ObjectLiteral *ast)
move(_block->TEMP(value), it->value);
// __qmljs_builtin_define_property(Value object, String *name, Value val, ExecutionContext *ctx)
current->expr = _block->TEMP(value);
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_define_property, 0, 0), args));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_define_property, 0, 0), args));
} else {
if (!getter) {
getter = _block->newTemp();
setter = _block->newTemp();
}
- move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(V4IR::UndefinedType, 0));
- move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(V4IR::UndefinedType, 0));
+ move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(IR::UndefinedType, 0));
+ move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(IR::UndefinedType, 0));
// __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx);
current->expr = _block->TEMP(getter);
- current->next = _function->New<V4IR::ExprList>();
+ current->next = _function->New<IR::ExprList>();
current = current->next;
current->expr = _block->TEMP(setter);
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_define_getter_setter, 0, 0), args));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_define_getter_setter, 0, 0), args));
}
}
}
@@ -1743,10 +1744,10 @@ bool Codegen::visit(PostDecrementExpression *ast)
return false;
const unsigned oldValue = _block->newTemp();
- move(_block->TEMP(oldValue), unop(V4IR::OpUPlus, *expr));
+ move(_block->TEMP(oldValue), unop(IR::OpUPlus, *expr));
const unsigned newValue = _block->newTemp();
- move(_block->TEMP(newValue), binop(V4IR::OpSub, _block->TEMP(oldValue), _block->CONST(V4IR::NumberType, 1)));
+ move(_block->TEMP(newValue), binop(IR::OpSub, _block->TEMP(oldValue), _block->CONST(IR::NumberType, 1)));
move(*expr, _block->TEMP(newValue));
if (!_expr.accept(nx))
@@ -1769,10 +1770,10 @@ bool Codegen::visit(PostIncrementExpression *ast)
return false;
const unsigned oldValue = _block->newTemp();
- move(_block->TEMP(oldValue), unop(V4IR::OpUPlus, *expr));
+ move(_block->TEMP(oldValue), unop(IR::OpUPlus, *expr));
const unsigned newValue = _block->newTemp();
- move(_block->TEMP(newValue), binop(V4IR::OpAdd, _block->TEMP(oldValue), _block->CONST(V4IR::NumberType, 1)));
+ move(_block->TEMP(newValue), binop(IR::OpAdd, _block->TEMP(oldValue), _block->CONST(IR::NumberType, 1)));
move(*expr, _block->TEMP(newValue));
if (!_expr.accept(nx))
@@ -1794,7 +1795,7 @@ bool Codegen::visit(PreDecrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(*expr, ast->decrementToken))
return false;
- V4IR::Expr *op = binop(V4IR::OpSub, *expr, _block->CONST(V4IR::NumberType, 1));
+ IR::Expr *op = binop(IR::OpSub, *expr, _block->CONST(IR::NumberType, 1));
if (_expr.accept(nx)) {
move(*expr, op);
} else {
@@ -1819,7 +1820,7 @@ bool Codegen::visit(PreIncrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(*expr, ast->incrementToken))
return false;
- V4IR::Expr *op = binop(V4IR::OpAdd, unop(V4IR::OpUPlus, *expr), _block->CONST(V4IR::NumberType, 1));
+ IR::Expr *op = binop(IR::OpAdd, unop(IR::OpUPlus, *expr), _block->CONST(IR::NumberType, 1));
if (_expr.accept(nx)) {
move(*expr, op);
} else {
@@ -1865,7 +1866,7 @@ bool Codegen::visit(TildeExpression *ast)
Result expr = expression(ast->expression);
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), unop(V4IR::OpCompl, *expr));
+ move(_block->TEMP(t), unop(IR::OpCompl, *expr));
_expr.code = _block->TEMP(t);
return false;
}
@@ -1878,7 +1879,7 @@ bool Codegen::visit(TrueLiteral *)
if (_expr.accept(cx)) {
_block->JUMP(_expr.iftrue);
} else {
- _expr.code = _block->CONST(V4IR::BoolType, 1);
+ _expr.code = _block->CONST(IR::BoolType, 1);
}
return false;
}
@@ -1889,9 +1890,9 @@ bool Codegen::visit(TypeOfExpression *ast)
return false;
Result expr = expression(ast->expression);
- V4IR::ExprList *args = _function->New<V4IR::ExprList>();
+ IR::ExprList *args = _function->New<IR::ExprList>();
args->init(reference(*expr));
- _expr.code = call(_block->NAME(V4IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
+ _expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
return false;
}
@@ -1902,7 +1903,7 @@ bool Codegen::visit(UnaryMinusExpression *ast)
Result expr = expression(ast->expression);
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), unop(V4IR::OpUMinus, *expr));
+ move(_block->TEMP(t), unop(IR::OpUMinus, *expr));
_expr.code = _block->TEMP(t);
return false;
}
@@ -1914,7 +1915,7 @@ bool Codegen::visit(UnaryPlusExpression *ast)
Result expr = expression(ast->expression);
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), unop(V4IR::OpUPlus, *expr));
+ move(_block->TEMP(t), unop(IR::OpUPlus, *expr));
_expr.code = _block->TEMP(t);
return false;
}
@@ -1925,7 +1926,7 @@ bool Codegen::visit(VoidExpression *ast)
return false;
statement(ast->expression);
- _expr.code = _block->CONST(V4IR::UndefinedType, 0);
+ _expr.code = _block->CONST(IR::UndefinedType, 0);
return false;
}
@@ -1947,17 +1948,17 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
{
Loop *loop = 0;
qSwap(_loop, loop);
- QStack<V4IR::BasicBlock *> exceptionHandlers;
+ QStack<IR::BasicBlock *> exceptionHandlers;
qSwap(_exceptionHandlers, exceptionHandlers);
ScopeAndFinally *scopeAndFinally = 0;
enterEnvironment(ast);
- V4IR::Function *function = _module->newFunction(name, _function);
+ IR::Function *function = _module->newFunction(name, _function);
int functionIndex = _module->functions.count() - 1;
- V4IR::BasicBlock *entryBlock = function->newBasicBlock(groupStartBlock(), 0);
- V4IR::BasicBlock *exitBlock = function->newBasicBlock(groupStartBlock(), 0, V4IR::Function::DontInsertBlock);
+ IR::BasicBlock *entryBlock = function->newBasicBlock(groupStartBlock(), 0);
+ IR::BasicBlock *exitBlock = function->newBasicBlock(groupStartBlock(), 0, IR::Function::DontInsertBlock);
function->hasDirectEval = _env->hasDirectEval || _env->compilationMode == EvalCode;
function->usesArgumentsObject = _env->parent && (_env->usesArgumentsObject == Environment::ArgumentsObjectUsed);
function->usesThis = _env->usesThis;
@@ -1979,7 +1980,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
const QString &local = it.key();
function->LOCAL(local);
(*it).index = t;
- entryBlock->MOVE(entryBlock->LOCAL(t, 0), entryBlock->CONST(V4IR::UndefinedType, 0));
+ entryBlock->MOVE(entryBlock->LOCAL(t, 0), entryBlock->CONST(IR::UndefinedType, 0));
++t;
}
} else {
@@ -1993,27 +1994,27 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
}
}
- V4IR::ExprList *args = 0;
+ IR::ExprList *args = 0;
for (Environment::MemberMap::const_iterator it = _env->members.constBegin(); it != _env->members.constEnd(); ++it) {
const QString &local = it.key();
- V4IR::ExprList *next = function->New<V4IR::ExprList>();
+ IR::ExprList *next = function->New<IR::ExprList>();
next->expr = entryBlock->NAME(local, 0, 0);
next->next = args;
args = next;
}
if (args) {
- V4IR::ExprList *next = function->New<V4IR::ExprList>();
- next->expr = entryBlock->CONST(V4IR::BoolType, false); // ### Investigate removal of bool deletable
+ IR::ExprList *next = function->New<IR::ExprList>();
+ next->expr = entryBlock->CONST(IR::BoolType, false); // ### Investigate removal of bool deletable
next->next = args;
args = next;
- entryBlock->EXP(entryBlock->CALL(entryBlock->NAME(V4IR::Name::builtin_declare_vars, 0, 0), args));
+ entryBlock->EXP(entryBlock->CALL(entryBlock->NAME(IR::Name::builtin_declare_vars, 0, 0), args));
}
}
unsigned returnAddress = entryBlock->newTemp();
- entryBlock->MOVE(entryBlock->TEMP(returnAddress), entryBlock->CONST(V4IR::UndefinedType, 0));
+ entryBlock->MOVE(entryBlock->TEMP(returnAddress), entryBlock->CONST(IR::UndefinedType, 0));
exitBlock->RET(exitBlock->TEMP(returnAddress));
qSwap(_function, function);
@@ -2041,12 +2042,12 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
}
if (_function->usesArgumentsObject) {
move(identifier(QStringLiteral("arguments"), ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn),
- _block->CALL(_block->NAME(V4IR::Name::builtin_setup_argument_object,
+ _block->CALL(_block->NAME(IR::Name::builtin_setup_argument_object,
ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), 0));
}
if (_function->usesThis && !_function->isStrict) {
// make sure we convert this to an object
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_convert_this_to_object,
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_convert_this_to_object,
ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), 0));
}
@@ -2198,9 +2199,9 @@ bool Codegen::visit(DoWhileStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *loopbody = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *loopcond = _function->newBasicBlock(loopbody, exceptionHandler());
- V4IR::BasicBlock *loopend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *loopbody = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *loopcond = _function->newBasicBlock(loopbody, exceptionHandler());
+ IR::BasicBlock *loopend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
enterLoop(ast, loopbody, loopend, loopcond);
@@ -2248,19 +2249,19 @@ bool Codegen::visit(ForEachStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *foreachin = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *foreachbody = _function->newBasicBlock(foreachin, exceptionHandler());
- V4IR::BasicBlock *foreachend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *foreachin = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *foreachbody = _function->newBasicBlock(foreachin, exceptionHandler());
+ IR::BasicBlock *foreachend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
enterLoop(ast, foreachin, foreachend, foreachin);
int objectToIterateOn = _block->newTemp();
move(_block->TEMP(objectToIterateOn), *expression(ast->expression));
- V4IR::ExprList *args = _function->New<V4IR::ExprList>();
+ IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(objectToIterateOn));
int iterator = _block->newTemp();
- move(_block->TEMP(iterator), _block->CALL(_block->NAME(V4IR::Name::builtin_foreach_iterator_object, 0, 0), args));
+ move(_block->TEMP(iterator), _block->CALL(_block->NAME(IR::Name::builtin_foreach_iterator_object, 0, 0), args));
_block->JUMP(foreachin);
@@ -2272,12 +2273,12 @@ bool Codegen::visit(ForEachStatement *ast)
_block = foreachin;
- args = _function->New<V4IR::ExprList>();
+ args = _function->New<IR::ExprList>();
args->init(_block->TEMP(iterator));
- move(_block->TEMP(temp), _block->CALL(_block->NAME(V4IR::Name::builtin_foreach_next_property_name, 0, 0), args));
+ move(_block->TEMP(temp), _block->CALL(_block->NAME(IR::Name::builtin_foreach_next_property_name, 0, 0), args));
int null = _block->newTemp();
- move(_block->TEMP(null), _block->CONST(V4IR::NullType, 0));
- cjump(_block->BINOP(V4IR::OpStrictNotEqual, _block->TEMP(temp), _block->TEMP(null)), foreachbody, foreachend);
+ move(_block->TEMP(null), _block->CONST(IR::NullType, 0));
+ cjump(_block->BINOP(IR::OpStrictNotEqual, _block->TEMP(temp), _block->TEMP(null)), foreachbody, foreachend);
_block = foreachend;
leaveLoop();
@@ -2289,10 +2290,10 @@ bool Codegen::visit(ForStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *forcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *forbody = _function->newBasicBlock(forcond, exceptionHandler());
- V4IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
- V4IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *forcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *forbody = _function->newBasicBlock(forcond, exceptionHandler());
+ IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
+ IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
statement(ast->initialiser);
_block->JUMP(forcond);
@@ -2325,9 +2326,9 @@ bool Codegen::visit(IfStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *iffalse = ast->ko ? _function->newBasicBlock(groupStartBlock(), exceptionHandler()) : 0;
- V4IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = ast->ko ? _function->newBasicBlock(groupStartBlock(), exceptionHandler()) : 0;
+ IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
condition(ast->expression, iftrue, ast->ko ? iffalse : endif);
@@ -2372,7 +2373,7 @@ bool Codegen::visit(LabelledStatement *ast)
AST::cast<AST::LocalForEachStatement *>(ast->statement)) {
statement(ast->statement); // labelledStatement will be associated with the ast->statement's loop.
} else {
- V4IR::BasicBlock *breakBlock = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *breakBlock = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
enterLoop(ast->statement, 0, breakBlock, /*continueBlock*/ 0);
statement(ast->statement);
_block->JUMP(breakBlock);
@@ -2388,9 +2389,9 @@ bool Codegen::visit(LocalForEachStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *foreachin = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *foreachbody = _function->newBasicBlock(foreachin, exceptionHandler());
- V4IR::BasicBlock *foreachend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *foreachin = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *foreachbody = _function->newBasicBlock(foreachin, exceptionHandler());
+ IR::BasicBlock *foreachend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
enterLoop(ast, foreachin, foreachend, foreachin);
@@ -2398,9 +2399,9 @@ bool Codegen::visit(LocalForEachStatement *ast)
int iterator = _block->newTemp();
move(_block->TEMP(iterator), *expression(ast->expression));
- V4IR::ExprList *args = _function->New<V4IR::ExprList>();
+ IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(iterator));
- move(_block->TEMP(iterator), _block->CALL(_block->NAME(V4IR::Name::builtin_foreach_iterator_object, 0, 0), args));
+ move(_block->TEMP(iterator), _block->CALL(_block->NAME(IR::Name::builtin_foreach_iterator_object, 0, 0), args));
_block->JUMP(foreachin);
@@ -2412,12 +2413,12 @@ bool Codegen::visit(LocalForEachStatement *ast)
_block = foreachin;
- args = _function->New<V4IR::ExprList>();
+ args = _function->New<IR::ExprList>();
args->init(_block->TEMP(iterator));
- move(_block->TEMP(temp), _block->CALL(_block->NAME(V4IR::Name::builtin_foreach_next_property_name, 0, 0), args));
+ move(_block->TEMP(temp), _block->CALL(_block->NAME(IR::Name::builtin_foreach_next_property_name, 0, 0), args));
int null = _block->newTemp();
- move(_block->TEMP(null), _block->CONST(V4IR::NullType, 0));
- cjump(_block->BINOP(V4IR::OpStrictNotEqual, _block->TEMP(temp), _block->TEMP(null)), foreachbody, foreachend);
+ move(_block->TEMP(null), _block->CONST(IR::NullType, 0));
+ cjump(_block->BINOP(IR::OpStrictNotEqual, _block->TEMP(temp), _block->TEMP(null)), foreachbody, foreachend);
_block = foreachend;
leaveLoop();
@@ -2429,10 +2430,10 @@ bool Codegen::visit(LocalForStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *forcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *forbody = _function->newBasicBlock(forcond, exceptionHandler());
- V4IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
- V4IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *forcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *forbody = _function->newBasicBlock(forcond, exceptionHandler());
+ IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
+ IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
variableDeclarationList(ast->declarations);
_block->JUMP(forcond);
@@ -2484,15 +2485,15 @@ bool Codegen::visit(SwitchStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *switchend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *switchend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
if (ast->block) {
Result lhs = expression(ast->expression);
- V4IR::BasicBlock *switchcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *switchcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
_block->JUMP(switchcond);
- V4IR::BasicBlock *previousBlock = 0;
+ IR::BasicBlock *previousBlock = 0;
- QHash<Node *, V4IR::BasicBlock *> blockMap;
+ QHash<Node *, IR::BasicBlock *> blockMap;
enterLoop(ast, 0, switchend, 0);
@@ -2547,18 +2548,18 @@ bool Codegen::visit(SwitchStatement *ast)
for (CaseClauses *it = ast->block->clauses; it; it = it->next) {
CaseClause *clause = it->clause;
Result rhs = expression(clause->expression);
- V4IR::BasicBlock *iftrue = blockMap[clause];
- V4IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- cjump(binop(V4IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse);
+ IR::BasicBlock *iftrue = blockMap[clause];
+ IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse);
_block = iffalse;
}
for (CaseClauses *it = ast->block->moreClauses; it; it = it->next) {
CaseClause *clause = it->clause;
Result rhs = expression(clause->expression);
- V4IR::BasicBlock *iftrue = blockMap[clause];
- V4IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- cjump(binop(V4IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse);
+ IR::BasicBlock *iftrue = blockMap[clause];
+ IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse);
_block = iffalse;
}
@@ -2580,9 +2581,9 @@ bool Codegen::visit(ThrowStatement *ast)
Result expr = expression(ast->expression);
move(_block->TEMP(_returnAddress), *expr);
- V4IR::ExprList *throwArgs = _function->New<V4IR::ExprList>();
+ IR::ExprList *throwArgs = _function->New<IR::ExprList>();
throwArgs->expr = _block->TEMP(_returnAddress);
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_throw, /*line*/0, /*column*/0), throwArgs));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_throw, /*line*/0, /*column*/0), throwArgs));
return false;
}
@@ -2599,23 +2600,23 @@ bool Codegen::visit(TryStatement *ast)
return false;
}
- V4IR::BasicBlock *surroundingExceptionHandler = exceptionHandler();
+ IR::BasicBlock *surroundingExceptionHandler = exceptionHandler();
// We always need a finally body to clean up the exception handler
// exceptions thrown in finally get catched by the surrounding catch block
- V4IR::BasicBlock *finallyBody = 0;
- V4IR::BasicBlock *catchBody = 0;
- V4IR::BasicBlock *catchExceptionHandler = 0;
- V4IR::BasicBlock *end = _function->newBasicBlock(groupStartBlock(), surroundingExceptionHandler, V4IR::Function::DontInsertBlock);
+ IR::BasicBlock *finallyBody = 0;
+ IR::BasicBlock *catchBody = 0;
+ IR::BasicBlock *catchExceptionHandler = 0;
+ IR::BasicBlock *end = _function->newBasicBlock(groupStartBlock(), surroundingExceptionHandler, IR::Function::DontInsertBlock);
if (ast->finallyExpression)
- finallyBody = _function->newBasicBlock(groupStartBlock(), surroundingExceptionHandler, V4IR::Function::DontInsertBlock);
+ finallyBody = _function->newBasicBlock(groupStartBlock(), surroundingExceptionHandler, IR::Function::DontInsertBlock);
if (ast->catchExpression) {
// exception handler for the catch body
- catchExceptionHandler = _function->newBasicBlock(groupStartBlock(), 0, V4IR::Function::DontInsertBlock);
+ catchExceptionHandler = _function->newBasicBlock(groupStartBlock(), 0, IR::Function::DontInsertBlock);
pushExceptionHandler(catchExceptionHandler);
- catchBody = _function->newBasicBlock(groupStartBlock(), catchExceptionHandler, V4IR::Function::DontInsertBlock);
+ catchBody = _function->newBasicBlock(groupStartBlock(), catchExceptionHandler, IR::Function::DontInsertBlock);
popExceptionHandler();
pushExceptionHandler(catchBody);
} else {
@@ -2623,7 +2624,7 @@ bool Codegen::visit(TryStatement *ast)
pushExceptionHandler(finallyBody);
}
- V4IR::BasicBlock *tryBody = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *tryBody = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
_block->JUMP(tryBody);
ScopeAndFinally tcf(_scopeAndFinally, ast->finallyExpression);
@@ -2641,26 +2642,26 @@ bool Codegen::visit(TryStatement *ast)
_block = catchBody;
++_function->insideWithOrCatch;
- V4IR::ExprList *catchArgs = _function->New<V4IR::ExprList>();
+ IR::ExprList *catchArgs = _function->New<IR::ExprList>();
catchArgs->init(_block->STRING(_function->newString(ast->catchExpression->name.toString())));
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_push_catch_scope, 0, 0), catchArgs));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_catch_scope, 0, 0), catchArgs));
{
ScopeAndFinally scope(_scopeAndFinally, ScopeAndFinally::CatchScope);
_scopeAndFinally = &scope;
statement(ast->catchExpression->statement);
_scopeAndFinally = scope.parent;
}
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_pop_scope, 0, 0), 0));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
--_function->insideWithOrCatch;
_block->JUMP(finallyBody ? finallyBody : end);
popExceptionHandler();
_function->insertBasicBlock(catchExceptionHandler);
- catchExceptionHandler->EXP(catchExceptionHandler->CALL(catchExceptionHandler->NAME(V4IR::Name::builtin_pop_scope, 0, 0), 0));
+ catchExceptionHandler->EXP(catchExceptionHandler->CALL(catchExceptionHandler->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
if (finallyBody || surroundingExceptionHandler)
catchExceptionHandler->JUMP(finallyBody ? finallyBody : surroundingExceptionHandler);
else
- catchExceptionHandler->EXP(catchExceptionHandler->CALL(catchExceptionHandler->NAME(V4IR::Name::builtin_rethrow, 0, 0), 0));
+ catchExceptionHandler->EXP(catchExceptionHandler->CALL(catchExceptionHandler->NAME(IR::Name::builtin_rethrow, 0, 0), 0));
}
_scopeAndFinally = tcf.parent;
@@ -2670,14 +2671,14 @@ bool Codegen::visit(TryStatement *ast)
_block = finallyBody;
int hasException = _block->newTemp();
- move(_block->TEMP(hasException), _block->CALL(_block->NAME(V4IR::Name::builtin_unwind_exception, /*line*/0, /*column*/0), 0));
+ move(_block->TEMP(hasException), _block->CALL(_block->NAME(IR::Name::builtin_unwind_exception, /*line*/0, /*column*/0), 0));
if (ast->finallyExpression && ast->finallyExpression->statement)
statement(ast->finallyExpression->statement);
- V4IR::ExprList *arg = _function->New<V4IR::ExprList>();
+ IR::ExprList *arg = _function->New<IR::ExprList>();
arg->expr = _block->TEMP(hasException);
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_throw, /*line*/0, /*column*/0), arg));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_throw, /*line*/0, /*column*/0), arg));
_block->JUMP(end);
}
@@ -2697,7 +2698,7 @@ void Codegen::unwindException(Codegen::ScopeAndFinally *outest)
case ScopeAndFinally::WithScope:
// fall through
case ScopeAndFinally::CatchScope:
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_pop_scope, 0, 0)));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0)));
_scopeAndFinally = _scopeAndFinally->parent;
--_function->insideWithOrCatch;
break;
@@ -2728,9 +2729,9 @@ bool Codegen::visit(WhileStatement *ast)
if (hasError)
return true;
- V4IR::BasicBlock *whilecond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- V4IR::BasicBlock *whilebody = _function->newBasicBlock(whilecond, exceptionHandler());
- V4IR::BasicBlock *whileend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *whilecond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *whilebody = _function->newBasicBlock(whilecond, exceptionHandler());
+ IR::BasicBlock *whileend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
enterLoop(ast, whilecond, whileend, whilecond);
@@ -2756,24 +2757,24 @@ bool Codegen::visit(WithStatement *ast)
_function->hasWith = true;
// need an exception handler for with to cleanup the with scope
- V4IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(V4IR::Name::builtin_pop_scope, 0, 0), 0));
+ IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
if (!exceptionHandler())
- withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(V4IR::Name::builtin_rethrow, 0, 0), 0));
+ withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(IR::Name::builtin_rethrow, 0, 0), 0));
else
withExceptionHandler->JUMP(exceptionHandler());
pushExceptionHandler(withExceptionHandler);
- V4IR::BasicBlock *withBlock = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *withBlock = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
_block->JUMP(withBlock);
_block = withBlock;
int withObject = _block->newTemp();
_block->MOVE(_block->TEMP(withObject), *expression(ast->expression));
- V4IR::ExprList *args = _function->New<V4IR::ExprList>();
+ IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(withObject));
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_push_with_scope, 0, 0), args));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_with_scope, 0, 0), args));
++_function->insideWithOrCatch;
{
@@ -2783,10 +2784,10 @@ bool Codegen::visit(WithStatement *ast)
_scopeAndFinally = scope.parent;
}
--_function->insideWithOrCatch;
- _block->EXP(_block->CALL(_block->NAME(V4IR::Name::builtin_pop_scope, 0, 0), 0));
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
popExceptionHandler();
- V4IR::BasicBlock *next = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *next = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
_block->JUMP(next);
_block = next;
@@ -2829,14 +2830,14 @@ bool Codegen::visit(UiSourceElement *)
return false;
}
-bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(V4IR::Expr *expr, const SourceLocation& loc)
+bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(IR::Expr *expr, const SourceLocation& loc)
{
if (!_env->isStrict)
return false;
- if (V4IR::Name *n = expr->asName()) {
+ if (IR::Name *n = expr->asName()) {
if (*n->id != QLatin1String("eval") && *n->id != QLatin1String("arguments"))
return false;
- } else if (V4IR::Temp *t = expr->asTemp()) {
+ } else if (IR::Temp *t = expr->asTemp()) {
if (!t->isArgumentsOrEval)
return false;
} else {
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 32f1f1bfd4..37055171b1 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -81,20 +81,20 @@ public:
void generateFromProgram(const QString &fileName,
const QString &sourceCode,
AST::Program *ast,
- V4IR::Module *module,
+ QV4::IR::Module *module,
CompilationMode mode = GlobalCode,
const QStringList &inheritedLocals = QStringList());
void generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,
AST::FunctionExpression *ast,
- V4IR::Module *module);
+ QV4::IR::Module *module);
protected:
enum Format { ex, cx, nx };
struct Result {
- V4IR::Expr *code;
- V4IR::BasicBlock *iftrue;
- V4IR::BasicBlock *iffalse;
+ QV4::IR::Expr *code;
+ QV4::IR::BasicBlock *iftrue;
+ QV4::IR::BasicBlock *iffalse;
Format format;
Format requested;
@@ -105,15 +105,15 @@ protected:
, format(ex)
, requested(requested) {}
- explicit Result(V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse)
+ explicit Result(QV4::IR::BasicBlock *iftrue, QV4::IR::BasicBlock *iffalse)
: code(0)
, iftrue(iftrue)
, iffalse(iffalse)
, format(ex)
, requested(cx) {}
- inline V4IR::Expr *operator*() const { Q_ASSERT(format == ex); return code; }
- inline V4IR::Expr *operator->() const { Q_ASSERT(format == ex); return code; }
+ inline QV4::IR::Expr *operator*() const { Q_ASSERT(format == ex); return code; }
+ inline QV4::IR::Expr *operator->() const { Q_ASSERT(format == ex); return code; }
bool accept(Format f)
{
@@ -254,35 +254,35 @@ protected:
struct Loop {
AST::LabelledStatement *labelledStatement;
AST::Statement *node;
- V4IR::BasicBlock *groupStartBlock;
- V4IR::BasicBlock *breakBlock;
- V4IR::BasicBlock *continueBlock;
+ QV4::IR::BasicBlock *groupStartBlock;
+ QV4::IR::BasicBlock *breakBlock;
+ QV4::IR::BasicBlock *continueBlock;
Loop *parent;
ScopeAndFinally *scopeAndFinally;
- Loop(AST::Statement *node, V4IR::BasicBlock *groupStartBlock, V4IR::BasicBlock *breakBlock, V4IR::BasicBlock *continueBlock, Loop *parent)
+ Loop(AST::Statement *node, QV4::IR::BasicBlock *groupStartBlock, QV4::IR::BasicBlock *breakBlock, QV4::IR::BasicBlock *continueBlock, Loop *parent)
: labelledStatement(0), node(node), groupStartBlock(groupStartBlock), breakBlock(breakBlock), continueBlock(continueBlock), parent(parent) {}
};
void enterEnvironment(AST::Node *node);
void leaveEnvironment();
- void enterLoop(AST::Statement *node, V4IR::BasicBlock *startBlock, V4IR::BasicBlock *breakBlock, V4IR::BasicBlock *continueBlock);
+ void enterLoop(AST::Statement *node, QV4::IR::BasicBlock *startBlock, QV4::IR::BasicBlock *breakBlock, QV4::IR::BasicBlock *continueBlock);
void leaveLoop();
- V4IR::BasicBlock *groupStartBlock() const
+ QV4::IR::BasicBlock *groupStartBlock() const
{
for (Loop *it = _loop; it; it = it->parent)
if (it->groupStartBlock)
return it->groupStartBlock;
return 0;
}
- V4IR::BasicBlock *exceptionHandler() const
+ QV4::IR::BasicBlock *exceptionHandler() const
{
if (_exceptionHandlers.isEmpty())
return 0;
return _exceptionHandlers.top();
}
- void pushExceptionHandler(V4IR::BasicBlock *handler)
+ void pushExceptionHandler(QV4::IR::BasicBlock *handler)
{
handler->isExceptionHandler = true;
_exceptionHandlers.push(handler);
@@ -293,15 +293,15 @@ protected:
_exceptionHandlers.pop();
}
- V4IR::Expr *member(V4IR::Expr *base, const QString *name);
- V4IR::Expr *subscript(V4IR::Expr *base, V4IR::Expr *index);
- V4IR::Expr *argument(V4IR::Expr *expr);
- V4IR::Expr *reference(V4IR::Expr *expr);
- V4IR::Expr *unop(V4IR::AluOp op, V4IR::Expr *expr);
- V4IR::Expr *binop(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right);
- V4IR::Expr *call(V4IR::Expr *base, V4IR::ExprList *args);
- void move(V4IR::Expr *target, V4IR::Expr *source, V4IR::AluOp op = V4IR::OpInvalid);
- void cjump(V4IR::Expr *cond, V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse);
+ QV4::IR::Expr *member(QV4::IR::Expr *base, const QString *name);
+ QV4::IR::Expr *subscript(QV4::IR::Expr *base, QV4::IR::Expr *index);
+ QV4::IR::Expr *argument(QV4::IR::Expr *expr);
+ QV4::IR::Expr *reference(QV4::IR::Expr *expr);
+ QV4::IR::Expr *unop(QV4::IR::AluOp op, QV4::IR::Expr *expr);
+ QV4::IR::Expr *binop(QV4::IR::AluOp op, QV4::IR::Expr *left, QV4::IR::Expr *right);
+ QV4::IR::Expr *call(QV4::IR::Expr *base, QV4::IR::ExprList *args);
+ void move(QV4::IR::Expr *target, QV4::IR::Expr *source, QV4::IR::AluOp op = QV4::IR::OpInvalid);
+ void cjump(QV4::IR::Expr *cond, QV4::IR::BasicBlock *iftrue, QV4::IR::BasicBlock *iffalse);
// Returns index in _module->functions
int defineFunction(const QString &name, AST::Node *ast,
@@ -313,7 +313,7 @@ protected:
void statement(AST::Statement *ast);
void statement(AST::ExpressionNode *ast);
- void condition(AST::ExpressionNode *ast, V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse);
+ void condition(AST::ExpressionNode *ast, QV4::IR::BasicBlock *iftrue, QV4::IR::BasicBlock *iffalse);
Result expression(AST::ExpressionNode *ast);
QString propertyName(AST::PropertyName *ast);
Result sourceElement(AST::SourceElement *ast);
@@ -327,9 +327,9 @@ protected:
void variableDeclaration(AST::VariableDeclaration *ast);
void variableDeclarationList(AST::VariableDeclarationList *ast);
- V4IR::Expr *identifier(const QString &name, int line = 0, int col = 0);
+ QV4::IR::Expr *identifier(const QString &name, int line = 0, int col = 0);
// Hook provided to implement QML lookup semantics
- virtual V4IR::Expr *fallbackNameLookup(const QString &name, int line, int col);
+ virtual QV4::IR::Expr *fallbackNameLookup(const QString &name, int line, int col);
virtual void beginFunctionBodyHook() {}
// nodes
@@ -436,7 +436,7 @@ protected:
virtual bool visit(AST::UiScriptBinding *ast);
virtual bool visit(AST::UiSourceElement *ast);
- bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(V4IR::Expr* expr, const AST::SourceLocation &loc);
+ bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(QV4::IR::Expr* expr, const AST::SourceLocation &loc);
virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail);
@@ -447,10 +447,10 @@ protected:
Result _expr;
QString _property;
UiMember _uiMember;
- V4IR::Module *_module;
- V4IR::Function *_function;
- V4IR::BasicBlock *_block;
- V4IR::BasicBlock *_exitBlock;
+ QV4::IR::Module *_module;
+ QV4::IR::Function *_function;
+ QV4::IR::BasicBlock *_block;
+ QV4::IR::BasicBlock *_exitBlock;
unsigned _returnAddress;
Environment *_env;
Loop *_loop;
@@ -458,7 +458,7 @@ protected:
ScopeAndFinally *_scopeAndFinally;
QHash<AST::Node *, Environment *> _envMap;
QHash<AST::FunctionExpression *, int> _functionMap;
- QStack<V4IR::BasicBlock *> _exceptionHandlers;
+ QStack<QV4::IR::BasicBlock *> _exceptionHandlers;
bool _strictMode;
bool _fileNameIsUrl;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index ce0c7abf9e..acedcc05f7 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -67,24 +67,24 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
assert(!runtimeStrings);
assert(data);
- runtimeStrings = (QV4::SafeString *)malloc(data->stringTableSize * sizeof(QV4::SafeString));
+ runtimeStrings = (QV4::StringValue *)malloc(data->stringTableSize * sizeof(QV4::StringValue));
// memset the strings to 0 in case a GC run happens while we're within the loop below
- memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::SafeString));
+ memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::StringValue));
for (uint i = 0; i < data->stringTableSize; ++i)
runtimeStrings[i] = engine->newIdentifier(data->stringAt(i));
- runtimeRegularExpressions = new QV4::SafeValue[data->regexpTableSize];
+ 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::SafeValue));
+ memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value));
for (uint i = 0; i < data->regexpTableSize; ++i) {
const CompiledData::RegExp *re = data->regexpAt(i);
int flags = 0;
if (re->flags & CompiledData::RegExp::RegExp_Global)
- flags |= QQmlJS::V4IR::RegExp::RegExp_Global;
+ flags |= IR::RegExp::RegExp_Global;
if (re->flags & CompiledData::RegExp::RegExp_IgnoreCase)
- flags |= QQmlJS::V4IR::RegExp::RegExp_IgnoreCase;
+ flags |= IR::RegExp::RegExp_IgnoreCase;
if (re->flags & CompiledData::RegExp::RegExp_Multiline)
- flags |= QQmlJS::V4IR::RegExp::RegExp_Multiline;
+ flags |= IR::RegExp::RegExp_Multiline;
runtimeRegularExpressions[i] = engine->newRegExpObject(data->stringAt(re->stringIndex), flags);
}
@@ -95,18 +95,25 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
for (uint i = 0; i < data->lookupTableSize; ++i) {
QV4::Lookup *l = runtimeLookups + i;
- if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Getter)
+ Lookup::Type type = Lookup::Type(compiledLookups[i].type_and_flags);
+ if (type == CompiledData::Lookup::Type_Getter)
l->getter = QV4::Lookup::getterGeneric;
- else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Setter)
+ else if (type == CompiledData::Lookup::Type_Setter)
l->setter = QV4::Lookup::setterGeneric;
- else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_GlobalGetter)
+ else if (type == CompiledData::Lookup::Type_GlobalGetter)
l->globalGetter = QV4::Lookup::globalGetterGeneric;
+ else if (type == CompiledData::Lookup::Type_IndexedGetter)
+ l->indexedGetter = QV4::Lookup::indexedGetterGeneric;
+ else if (type == CompiledData::Lookup::Type_IndexedSetter)
+ l->indexedSetter = QV4::Lookup::indexedSetterGeneric;
for (int j = 0; j < QV4::Lookup::Size; ++j)
l->classList[j] = 0;
l->level = -1;
l->index = UINT_MAX;
l->name = runtimeStrings[compiledLookups[i].nameIndex].asString();
+ if (type == CompiledData::Lookup::Type_IndexedGetter || type == CompiledData::Lookup::Type_IndexedSetter)
+ l->engine = engine;
}
}
@@ -193,6 +200,57 @@ QString Binding::valueAsString(const Unit *unit) const
return QString();
}
+//reverse of Lexer::singleEscape()
+static QString escapedString(const QString &string)
+{
+ QString tmp = QLatin1String("\"");
+ for (int i = 0; i < string.length(); ++i) {
+ const QChar &c = string.at(i);
+ switch (c.unicode()) {
+ case 0x08:
+ tmp += QLatin1String("\\b");
+ break;
+ case 0x09:
+ tmp += QLatin1String("\\t");
+ break;
+ case 0x0A:
+ tmp += QLatin1String("\\n");
+ break;
+ case 0x0B:
+ tmp += QLatin1String("\\v");
+ break;
+ case 0x0C:
+ tmp += QLatin1String("\\f");
+ break;
+ case 0x0D:
+ tmp += QLatin1String("\\r");
+ break;
+ case 0x22:
+ tmp += QLatin1String("\\\"");
+ break;
+ case 0x27:
+ tmp += QLatin1String("\\\'");
+ break;
+ case 0x5C:
+ tmp += QLatin1String("\\\\");
+ break;
+ default:
+ tmp += c;
+ break;
+ }
+ }
+ tmp += QLatin1Char('\"');
+ return tmp;
+}
+
+QString Binding::valueAsScriptString(const Unit *unit) const
+{
+ if (type == Type_String)
+ return escapedString(unit->stringAt(stringIndex));
+ else
+ return valueAsString(unit);
+}
+
}
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 90f27d5f57..675282fb8c 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -45,18 +45,15 @@
#include <QVector>
#include <QStringList>
#include <QHash>
-#include <private/qv4value_def_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4executableallocator_p.h>
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
-namespace V4IR {
+namespace QV4 {
+namespace IR {
struct Function;
}
-}
-
-namespace QV4 {
struct Function;
struct ExecutionContext;
@@ -70,17 +67,32 @@ struct RegExp;
struct Location
{
- int line;
- int column;
+ qint32 line;
+ qint32 column;
+ inline bool operator<(const Location &other) const {
+ return line < other.line ||
+ (line == other.line && column < other.column);
+ }
+};
+
+struct TypeReference
+{
+ TypeReference(const Location &loc)
+ : location(loc)
+ , needsCreation(false)
+ {}
+ Location location; // first use
+ bool needsCreation; // whether the type needs to be creatable or not
};
// map from name index to location of first use
-struct TypeReferenceMap : QHash<int, Location>
+struct TypeReferenceMap : QHash<int, TypeReference>
{
- void add(int nameIndex, const Location &loc) {
- if (contains(nameIndex))
- return;
- insert(nameIndex, loc);
+ TypeReference &add(int nameIndex, const Location &loc) {
+ Iterator it = find(nameIndex);
+ if (it != end())
+ return *it;
+ return *insert(nameIndex, loc);
}
};
@@ -102,7 +114,9 @@ struct Lookup
enum Type {
Type_Getter = 0x0,
Type_Setter = 0x1,
- Type_GlobalGetter = 2
+ Type_GlobalGetter = 2,
+ Type_IndexedGetter = 3,
+ Type_IndexedSetter = 4
};
quint32 type_and_flags;
@@ -188,8 +202,8 @@ struct Unit
const RegExp *regexpAt(int index) const {
return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
}
- const QV4::SafeValue *constants() const {
- return reinterpret_cast<const QV4::SafeValue*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
+ const QV4::Value *constants() const {
+ return reinterpret_cast<const QV4::Value*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
}
const JSClassMember *jsClassAt(int idx, int *nMembers) const {
@@ -264,7 +278,7 @@ struct Function
// Qml data structures
-struct Binding
+struct Q_QML_EXPORT Binding
{
quint32 propertyNameIndex;
@@ -280,7 +294,13 @@ struct Binding
};
enum Flags {
- IsSignalHandlerExpression = 0x1
+ IsSignalHandlerExpression = 0x1,
+ IsSignalHandlerObject = 0x2,
+ IsOnAssignment = 0x4,
+ InitializerForReadOnlyDeclaration = 0x8,
+ IsResolvedEnum = 0x10,
+ IsListItem = 0x20,
+ IsBindingToAlias = 0x40
};
quint32 flags : 16;
@@ -294,8 +314,57 @@ struct Binding
quint32 stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
Location location;
+ Location valueLocation;
+
+ bool isValueBinding() const
+ {
+ if (type == Type_AttachedProperty
+ || type == Type_GroupProperty)
+ return false;
+ if (flags & IsSignalHandlerExpression
+ || flags & IsSignalHandlerObject)
+ return false;
+ return true;
+ }
+
+ bool isValueBindingNoAlias() const { return isValueBinding() && !(flags & IsBindingToAlias); }
+ bool isValueBindingToAlias() const { return isValueBinding() && (flags & IsBindingToAlias); }
+
+ bool isSignalHandler() const
+ {
+ if (flags & IsSignalHandlerExpression || flags & IsSignalHandlerObject) {
+ Q_ASSERT(!isValueBinding());
+ Q_ASSERT(!isAttachedProperty());
+ Q_ASSERT(!isGroupProperty());
+ return true;
+ }
+ return false;
+ }
+
+ bool isAttachedProperty() const
+ {
+ if (type == Type_AttachedProperty) {
+ Q_ASSERT(!isValueBinding());
+ Q_ASSERT(!isSignalHandler());
+ Q_ASSERT(!isGroupProperty());
+ return true;
+ }
+ return false;
+ }
+
+ bool isGroupProperty() const
+ {
+ if (type == Type_GroupProperty) {
+ Q_ASSERT(!isValueBinding());
+ Q_ASSERT(!isSignalHandler());
+ Q_ASSERT(!isAttachedProperty());
+ return true;
+ }
+ return false;
+ }
QString valueAsString(const Unit *unit) const;
+ QString valueAsScriptString(const Unit *unit) const;
double valueAsNumber() const
{
if (type == Type_Number)
@@ -369,7 +438,7 @@ struct Object
// it will be the name of the attached type.
quint32 inheritedTypeNameIndex;
quint32 idIndex;
- quint32 indexOfDefaultProperty;
+ qint32 indexOfDefaultProperty; // -1 means no default property declared in this object
quint32 nFunctions;
quint32 offsetToFunctions;
quint32 nProperties;
@@ -491,9 +560,9 @@ struct Q_QML_EXPORT CompilationUnit
QString fileName() const { return data->stringAt(data->sourceFileIndex); }
- QV4::SafeString *runtimeStrings; // Array
+ QV4::StringValue *runtimeStrings; // Array
QV4::Lookup *runtimeLookups;
- QV4::SafeValue *runtimeRegularExpressions;
+ QV4::Value *runtimeRegularExpressions;
QV4::InternalClass **runtimeClasses;
QVector<QV4::Function *> runtimeFunctions;
// QVector<QV4::Function *> runtimeFunctionsSortedByAddress;
@@ -516,6 +585,8 @@ protected:
}
+Q_DECLARE_TYPEINFO(QV4::CompiledData::JSClassMember, Q_PRIMITIVE_TYPE);
+
QT_END_NAMESPACE
#endif
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 9041b04837..7be902f1c1 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -45,7 +45,7 @@
#include <qv4engine_p.h>
#include <private/qqmlpropertycache_p.h>
-QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QQmlJS::V4IR::Module *module, int headerSize)
+QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QV4::IR::Module *module, int headerSize)
: irModule(module)
, stringDataSize(0)
, jsClassDataSize(0)
@@ -53,6 +53,8 @@ QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QQmlJS::V4IR::Module *module, in
if (headerSize == -1)
headerSize = sizeof(QV4::CompiledData::Unit);
this->headerSize = headerSize;
+ // Make sure the empty string always gets index 0
+ registerString(QString());
}
int QV4::Compiler::JSUnitGenerator::registerString(const QString &str)
@@ -72,6 +74,24 @@ int QV4::Compiler::JSUnitGenerator::getStringId(const QString &string) const
return stringToId.value(string);
}
+uint QV4::Compiler::JSUnitGenerator::registerIndexedGetterLookup()
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_IndexedGetter;
+ l.nameIndex = 0;
+ lookups << l;
+ return lookups.size() - 1;
+}
+
+uint QV4::Compiler::JSUnitGenerator::registerIndexedSetterLookup()
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_IndexedSetter;
+ l.nameIndex = 0;
+ lookups << l;
+ return lookups.size() - 1;
+}
+
uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
{
CompiledData::Lookup l;
@@ -81,6 +101,7 @@ uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
return lookups.size() - 1;
}
+
uint QV4::Compiler::JSUnitGenerator::registerSetterLookup(const QString &name)
{
CompiledData::Lookup l;
@@ -99,17 +120,17 @@ uint QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(const QString &n
return lookups.size() - 1;
}
-int QV4::Compiler::JSUnitGenerator::registerRegExp(QQmlJS::V4IR::RegExp *regexp)
+int QV4::Compiler::JSUnitGenerator::registerRegExp(QV4::IR::RegExp *regexp)
{
CompiledData::RegExp re;
re.stringIndex = registerString(*regexp->value);
re.flags = 0;
- if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_Global)
+ if (regexp->flags & QV4::IR::RegExp::RegExp_Global)
re.flags |= CompiledData::RegExp::RegExp_Global;
- if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_IgnoreCase)
+ if (regexp->flags & QV4::IR::RegExp::RegExp_IgnoreCase)
re.flags |= CompiledData::RegExp::RegExp_IgnoreCase;
- if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_Multiline)
+ if (regexp->flags & QV4::IR::RegExp::RegExp_Multiline)
re.flags |= CompiledData::RegExp::RegExp_Multiline;
regexps.append(re);
@@ -125,22 +146,22 @@ int QV4::Compiler::JSUnitGenerator::registerConstant(QV4::ReturnedValue v)
return constants.size() - 1;
}
-void QV4::Compiler::JSUnitGenerator::registerLineNumberMapping(QQmlJS::V4IR::Function *function, const QVector<uint> &mappings)
+void QV4::Compiler::JSUnitGenerator::registerLineNumberMapping(QV4::IR::Function *function, const QVector<uint> &mappings)
{
lineNumberMappingsPerFunction.insert(function, mappings);
}
-int QV4::Compiler::JSUnitGenerator::registerJSClass(QQmlJS::V4IR::ExprList *args)
+int QV4::Compiler::JSUnitGenerator::registerJSClass(QV4::IR::ExprList *args)
{
// ### re-use existing class definitions.
QList<CompiledData::JSClassMember> members;
- QQmlJS::V4IR::ExprList *it = args;
+ QV4::IR::ExprList *it = args;
while (it) {
CompiledData::JSClassMember member;
- QQmlJS::V4IR::Name *name = it->expr->asName();
+ QV4::IR::Name *name = it->expr->asName();
it = it->next;
const bool isData = it->expr->asConst()->value;
@@ -164,7 +185,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(QQmlJS::V4IR::ExprList *args
QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *totalUnitSize)
{
registerString(irModule->fileName);
- foreach (QQmlJS::V4IR::Function *f, irModule->functions) {
+ foreach (QV4::IR::Function *f, irModule->functions) {
registerString(*f->name);
for (int i = 0; i < f->formals.size(); ++i)
registerString(*f->formals.at(i));
@@ -177,11 +198,11 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total
uint functionDataSize = 0;
for (int i = 0; i < irModule->functions.size(); ++i) {
- QQmlJS::V4IR::Function *f = irModule->functions.at(i);
+ QV4::IR::Function *f = irModule->functions.at(i);
functionOffsets.insert(f, functionDataSize + unitSize + stringDataSize);
int lineNumberMappingCount = 0;
- QHash<QQmlJS::V4IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(f);
+ QHash<QV4::IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(f);
if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd())
lineNumberMappingCount = lineNumberMapping->count() / 2;
@@ -242,7 +263,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total
char *f = data + unitSize + stringDataSize;
for (int i = 0; i < irModule->functions.size(); ++i) {
- QQmlJS::V4IR::Function *function = irModule->functions.at(i);
+ QV4::IR::Function *function = irModule->functions.at(i);
if (function == irModule->rootFunction)
unit->indexOfRootFunction = i;
@@ -281,7 +302,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total
return unit;
}
-int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction)
+int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QV4::IR::Function *irFunction)
{
QV4::CompiledData::Function *function = (QV4::CompiledData::Function *)f;
@@ -309,7 +330,7 @@ int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4
currentOffset += function->nLocals * sizeof(quint32);
function->nLineNumberMappingEntries = 0;
- QHash<QQmlJS::V4IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(irFunction);
+ QHash<QV4::IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(irFunction);
if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd()) {
function->nLineNumberMappingEntries = lineNumberMapping->count() / 2;
}
@@ -372,14 +393,14 @@ int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4
*writtenDeps++ = id;
writtenDeps = (quint32 *)(f + function->dependingContextPropertiesOffset);
- for (QQmlJS::V4IR::PropertyDependencyMap::ConstIterator property = irFunction->contextObjectPropertyDependencies.constBegin(), end = irFunction->contextObjectPropertyDependencies.constEnd();
+ for (QV4::IR::PropertyDependencyMap::ConstIterator property = irFunction->contextObjectPropertyDependencies.constBegin(), end = irFunction->contextObjectPropertyDependencies.constEnd();
property != end; ++property) {
*writtenDeps++ = property.key(); // property index
*writtenDeps++ = property.value(); // notify index
}
writtenDeps = (quint32 *)(f + function->dependingScopePropertiesOffset);
- for (QQmlJS::V4IR::PropertyDependencyMap::ConstIterator property = irFunction->scopeObjectPropertyDependencies.constBegin(), end = irFunction->scopeObjectPropertyDependencies.constEnd();
+ for (QV4::IR::PropertyDependencyMap::ConstIterator property = irFunction->scopeObjectPropertyDependencies.constBegin(), end = irFunction->scopeObjectPropertyDependencies.constEnd();
property != end; ++property) {
*writtenDeps++ = property.key(); // property index
*writtenDeps++ = property.value(); // notify index
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 1596fcb622..29cf82e2bc 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -60,9 +60,9 @@ struct JSClassMember;
namespace Compiler {
struct Q_QML_EXPORT JSUnitGenerator {
- JSUnitGenerator(QQmlJS::V4IR::Module *module, int headerSize = -1);
+ JSUnitGenerator(IR::Module *module, int headerSize = -1);
- QQmlJS::V4IR::Module *irModule;
+ IR::Module *irModule;
int registerString(const QString &str);
int getStringId(const QString &string) const;
@@ -70,27 +70,29 @@ struct Q_QML_EXPORT JSUnitGenerator {
uint registerGetterLookup(const QString &name);
uint registerSetterLookup(const QString &name);
uint registerGlobalGetterLookup(const QString &name);
+ uint registerIndexedGetterLookup();
+ uint registerIndexedSetterLookup();
- int registerRegExp(QQmlJS::V4IR::RegExp *regexp);
+ int registerRegExp(IR::RegExp *regexp);
int registerConstant(ReturnedValue v);
- void registerLineNumberMapping(QQmlJS::V4IR::Function *function, const QVector<uint> &mappings);
+ void registerLineNumberMapping(IR::Function *function, const QVector<uint> &mappings);
- int registerJSClass(QQmlJS::V4IR::ExprList *args);
+ int registerJSClass(IR::ExprList *args);
QV4::CompiledData::Unit *generateUnit(int *totalUnitSize = 0);
// Returns bytes written
- int writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction);
+ int writeFunction(char *f, int index, IR::Function *irFunction);
QHash<QString, int> stringToId;
QStringList strings;
uint stringDataSize;
- QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
+ QHash<IR::Function *, uint> functionOffsets;
QList<CompiledData::Lookup> lookups;
QVector<CompiledData::RegExp> regexps;
QVector<ReturnedValue> constants;
- QHash<QQmlJS::V4IR::Function *, QVector<uint> > lineNumberMappingsPerFunction;
+ QHash<IR::Function *, QVector<uint> > lineNumberMappingsPerFunction;
QList<QList<CompiledData::JSClassMember> > jsClasses;
uint jsClassDataSize;
uint headerSize;
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index ec68ede72d..5a36a969c0 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -41,8 +41,8 @@
#include "qv4instr_moth_p.h"
-using namespace QQmlJS;
-using namespace QQmlJS::Moth;
+using namespace QV4;
+using namespace QV4::Moth;
int Instr::size(Type type)
{
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 5b5667abb4..bca878d648 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -43,7 +43,7 @@
#define QV4INSTR_MOTH_P_H
#include <QtCore/qglobal.h>
-#include <private/qv4value_def_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4function_p.h>
#include <private/qv4runtime_p.h>
@@ -51,16 +51,20 @@ QT_BEGIN_NAMESPACE
#define FOR_EACH_MOTH_INSTR(F) \
F(Ret, ret) \
+ F(Debug, debug) \
F(LoadRuntimeString, loadRuntimeString) \
F(LoadRegExp, loadRegExp) \
F(LoadClosure, loadClosure) \
F(Move, move) \
+ F(MoveConst, moveConst) \
F(SwapTemps, swapTemps) \
F(LoadName, loadName) \
F(GetGlobalLookup, getGlobalLookup) \
F(StoreName, storeName) \
F(LoadElement, loadElement) \
+ F(LoadElementLookup, loadElementLookup) \
F(StoreElement, storeElement) \
+ F(StoreElementLookup, storeElementLookup) \
F(LoadProperty, loadProperty) \
F(GetLookup, getLookup) \
F(StoreProperty, storeProperty) \
@@ -103,7 +107,8 @@ QT_BEGIN_NAMESPACE
F(CreateActivationProperty, createActivationProperty) \
F(ConstructGlobalLookup, constructGlobalLookup) \
F(Jump, jump) \
- F(CJump, cjump) \
+ F(JumpEq, jumpEq) \
+ F(JumpNe, jumpNe) \
F(UNot, unot) \
F(UNotBool, unotBool) \
F(UPlus, uplus) \
@@ -117,15 +122,16 @@ QT_BEGIN_NAMESPACE
F(BitAnd, bitAnd) \
F(BitOr, bitOr) \
F(BitXor, bitXor) \
+ F(Shr, shr) \
+ F(Shl, shl) \
F(BitAndConst, bitAndConst) \
F(BitOrConst, bitOrConst) \
F(BitXorConst, bitXorConst) \
+ F(ShrConst, shrConst) \
+ F(ShlConst, shlConst) \
F(Mul, mul) \
F(Sub, sub) \
F(BinopContext, binopContext) \
- F(AddNumberParams, addNumberParams) \
- F(MulNumberParams, mulNumberParams) \
- F(SubNumberParams, subNumberParams) \
F(LoadThis, loadThis) \
F(LoadQmlIdArray, loadQmlIdArray) \
F(LoadQmlImportedScripts, loadQmlImportedScripts) \
@@ -137,21 +143,19 @@ QT_BEGIN_NAMESPACE
# define MOTH_THREADED_INTERPRETER
#endif
-#define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QQmlJS::Moth::Instr) - 1)
+#define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1)
#ifdef MOTH_THREADED_INTERPRETER
-# define MOTH_INSTR_HEADER void *code; \
- unsigned int breakPoint : 1;
+# define MOTH_INSTR_HEADER void *code;
#else
-# define MOTH_INSTR_HEADER quint8 instructionType; \
- unsigned int breakPoint : 1;
+# define MOTH_INSTR_HEADER quint32 instructionType;
#endif
#define MOTH_INSTR_ENUM(I, FMT) I,
-#define MOTH_INSTR_SIZE(I, FMT) ((sizeof(QQmlJS::Moth::Instr::instr_##FMT) + MOTH_INSTR_ALIGN_MASK) & ~MOTH_INSTR_ALIGN_MASK)
+#define MOTH_INSTR_SIZE(I, FMT) ((sizeof(QV4::Moth::Instr::instr_##FMT) + MOTH_INSTR_ALIGN_MASK) & ~MOTH_INSTR_ALIGN_MASK)
-namespace QQmlJS {
+namespace QV4 {
namespace Moth {
struct Param {
@@ -231,7 +235,11 @@ union Instr
struct instr_ret {
MOTH_INSTR_HEADER
Param result;
- };
+ };
+ struct instr_debug {
+ MOTH_INSTR_HEADER
+ quint32 breakPoint;
+ };
struct instr_loadRuntimeString {
MOTH_INSTR_HEADER
int stringId;
@@ -247,6 +255,11 @@ union Instr
Param source;
Param result;
};
+ struct instr_moveConst {
+ MOTH_INSTR_HEADER
+ QV4::ReturnedValue source;
+ Param result;
+ };
struct instr_swapTemps {
MOTH_INSTR_HEADER
Param left;
@@ -322,12 +335,26 @@ union Instr
Param index;
Param result;
};
+ struct instr_loadElementLookup {
+ MOTH_INSTR_HEADER
+ uint lookup;
+ Param base;
+ Param index;
+ Param result;
+ };
struct instr_storeElement {
MOTH_INSTR_HEADER
Param base;
Param index;
Param source;
};
+ struct instr_storeElementLookup {
+ MOTH_INSTR_HEADER
+ uint lookup;
+ Param base;
+ Param index;
+ Param source;
+ };
struct instr_push {
MOTH_INSTR_HEADER
quint32 value;
@@ -525,13 +552,17 @@ union Instr
};
struct instr_jump {
MOTH_INSTR_HEADER
- ptrdiff_t offset;
+ ptrdiff_t offset;
+ };
+ struct instr_jumpEq {
+ MOTH_INSTR_HEADER
+ ptrdiff_t offset;
+ Param condition;
};
- struct instr_cjump {
+ struct instr_jumpNe {
MOTH_INSTR_HEADER
ptrdiff_t offset;
Param condition;
- bool invert;
};
struct instr_unot {
MOTH_INSTR_HEADER
@@ -604,57 +635,63 @@ union Instr
Param rhs;
Param result;
};
- struct instr_bitAndConst {
+ struct instr_shr {
MOTH_INSTR_HEADER
Param lhs;
- int rhs;
+ Param rhs;
Param result;
};
- struct instr_bitOrConst {
+ struct instr_shl {
+ MOTH_INSTR_HEADER
+ Param lhs;
+ Param rhs;
+ Param result;
+ };
+ struct instr_bitAndConst {
MOTH_INSTR_HEADER
Param lhs;
int rhs;
Param result;
};
- struct instr_bitXorConst {
+ struct instr_bitOrConst {
MOTH_INSTR_HEADER
Param lhs;
int rhs;
Param result;
};
- struct instr_mul {
+ struct instr_bitXorConst {
MOTH_INSTR_HEADER
Param lhs;
- Param rhs;
+ int rhs;
Param result;
};
- struct instr_sub {
+ struct instr_shrConst {
MOTH_INSTR_HEADER
Param lhs;
- Param rhs;
+ int rhs;
Param result;
};
- struct instr_binopContext {
+ struct instr_shlConst {
MOTH_INSTR_HEADER
- QV4::BinOpContext alu;
Param lhs;
- Param rhs;
+ int rhs;
Param result;
};
- struct instr_addNumberParams {
+ struct instr_mul {
MOTH_INSTR_HEADER
Param lhs;
Param rhs;
Param result;
};
- struct instr_mulNumberParams {
+ struct instr_sub {
MOTH_INSTR_HEADER
Param lhs;
Param rhs;
Param result;
};
- struct instr_subNumberParams {
+ struct instr_binopContext {
MOTH_INSTR_HEADER
+ QV4::BinOpContext alu;
Param lhs;
Param rhs;
Param result;
@@ -687,16 +724,20 @@ union Instr
instr_common common;
instr_ret ret;
+ instr_debug debug;
instr_loadRuntimeString loadRuntimeString;
instr_loadRegExp loadRegExp;
instr_move move;
+ instr_moveConst moveConst;
instr_swapTemps swapTemps;
instr_loadClosure loadClosure;
instr_loadName loadName;
instr_getGlobalLookup getGlobalLookup;
instr_storeName storeName;
instr_loadElement loadElement;
+ instr_loadElementLookup loadElementLookup;
instr_storeElement storeElement;
+ instr_storeElementLookup storeElementLookup;
instr_loadProperty loadProperty;
instr_getLookup getLookup;
instr_loadQObjectProperty loadQObjectProperty;
@@ -739,7 +780,8 @@ union Instr
instr_createActivationProperty createActivationProperty;
instr_constructGlobalLookup constructGlobalLookup;
instr_jump jump;
- instr_cjump cjump;
+ instr_jumpEq jumpEq;
+ instr_jumpNe jumpNe;
instr_unot unot;
instr_unotBool unotBool;
instr_uplus uplus;
@@ -753,15 +795,16 @@ union Instr
instr_bitAnd bitAnd;
instr_bitOr bitOr;
instr_bitXor bitXor;
+ instr_shr shr;
+ instr_shl shl;
instr_bitAndConst bitAndConst;
instr_bitOrConst bitOrConst;
instr_bitXorConst bitXorConst;
+ instr_shrConst shrConst;
+ instr_shlConst shlConst;
instr_mul mul;
instr_sub sub;
instr_binopContext binopContext;
- instr_addNumberParams addNumberParams;
- instr_mulNumberParams mulNumberParams;
- instr_subNumberParams subNumberParams;
instr_loadThis loadThis;
instr_loadQmlIdArray loadQmlIdArray;
instr_loadQmlImportedScripts loadQmlImportedScripts;
@@ -782,7 +825,11 @@ struct InstrMeta {
typedef Instr::instr_##FMT DataType; \
static const DataType &data(const Instr &instr) { return instr.FMT; } \
static void setData(Instr &instr, const DataType &v) { instr.FMT = v; } \
- };
+ static void setDataNoCommon(Instr &instr, const DataType &v) \
+ { memcpy(reinterpret_cast<char *>(&instr.FMT) + sizeof(Instr::instr_common), \
+ reinterpret_cast<const char *>(&v) + sizeof(Instr::instr_common), \
+ Size - sizeof(Instr::instr_common)); } \
+ };
FOR_EACH_MOTH_INSTR(MOTH_INSTR_META_TEMPLATE);
#undef MOTH_INSTR_META_TEMPLATE
@@ -792,7 +839,7 @@ class InstrData : public InstrMeta<InstrType>::DataType
};
} // namespace Moth
-} // namespace QQmlJS
+} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
deleted file mode 100644
index 0fcd770584..0000000000
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ /dev/null
@@ -1,2648 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4isel_masm_p.h"
-#include "qv4runtime_p.h"
-#include "qv4object_p.h"
-#include "qv4functionobject_p.h"
-#include "qv4regexpobject_p.h"
-#include "qv4lookup_p.h"
-#include "qv4function_p.h"
-#include "qv4ssa_p.h"
-#include "qv4regalloc_p.h"
-
-#include <assembler/LinkBuffer.h>
-#include <WTFStubs.h>
-
-#include <iostream>
-#include <cassert>
-
-#if ENABLE(ASSEMBLER)
-
-#if USE(UDIS86)
-# include <udis86.h>
-#endif
-
-using namespace QQmlJS;
-using namespace QQmlJS::MASM;
-using namespace QV4;
-
-CompilationUnit::~CompilationUnit()
-{
- foreach (Function *f, runtimeFunctions)
- engine->allFunctions.remove(reinterpret_cast<quintptr>(f->code));
-}
-
-void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
-{
- runtimeFunctions.resize(data->functionTableSize);
- runtimeFunctions.fill(0);
- for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
- const CompiledData::Function *compiledFunction = data->functionAt(i);
-
- QV4::Function *runtimeFunction = new QV4::Function(engine, this, compiledFunction,
- (ReturnedValue (*)(QV4::ExecutionContext *, const uchar *)) codeRefs[i].code().executableAddress(),
- codeSizes[i]);
- runtimeFunctions[i] = runtimeFunction;
- }
-
- foreach (Function *f, runtimeFunctions)
- engine->allFunctions.insert(reinterpret_cast<quintptr>(f->code), f);
-}
-
-QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int functionIndex)
-{
- if (functionIndex < 0 || functionIndex >= codeRefs.count())
- return 0;
- JSC::ExecutableMemoryHandle *handle = codeRefs[functionIndex].executableMemory();
- if (!handle)
- return 0;
- return handle->chunk();
-}
-
-namespace {
-inline bool isPregOrConst(V4IR::Expr *e)
-{
- if (V4IR::Temp *t = e->asTemp())
- return t->kind == V4IR::Temp::PhysicalRegister;
- return e->asConst() != 0;
-}
-} // anonymous namespace
-
-/* Platform/Calling convention/Architecture specific section */
-
-#if CPU(X86_64)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- // Not used: JSC::X86Registers::rbx,
- // Not used: JSC::X86Registers::r10,
- JSC::X86Registers::r12, // LocalsRegister
- // Not used: JSC::X86Registers::r13,
- JSC::X86Registers::r14 // ContextRegister
- // Not used: JSC::X86Registers::r15,
-};
-#endif
-
-#if CPU(X86)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- JSC::X86Registers::ebx, // temporary register
- JSC::X86Registers::esi, // ContextRegister
- JSC::X86Registers::edi // LocalsRegister
-};
-#endif
-
-#if CPU(ARM)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- // ### FIXME: remove unused registers.
- JSC::ARMRegisters::r12,
- JSC::ARMRegisters::r10,
- JSC::ARMRegisters::r9,
- JSC::ARMRegisters::r8,
- JSC::ARMRegisters::r7,
- JSC::ARMRegisters::r6,
- JSC::ARMRegisters::r5,
- JSC::ARMRegisters::r4
-};
-#endif
-
-const int Assembler::calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
-
-/* End of platform/calling convention/architecture specific section */
-
-
-const Assembler::VoidType Assembler::Void;
-
-Assembler::Assembler(InstructionSelection *isel, V4IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
- int maxArgCountForBuiltins)
- : _stackLayout(function, maxArgCountForBuiltins)
- , _constTable(this)
- , _function(function)
- , _nextBlock(0)
- , _executableAllocator(executableAllocator)
- , _isel(isel)
-{
-}
-
-void Assembler::registerBlock(V4IR::BasicBlock* block, V4IR::BasicBlock *nextBlock)
-{
- _addrs[block] = label();
- catchBlock = block->catchBlock;
- _nextBlock = nextBlock;
-}
-
-void Assembler::jumpToBlock(V4IR::BasicBlock* current, V4IR::BasicBlock *target)
-{
- Q_UNUSED(current);
-
- if (target != _nextBlock)
- _patches[target].append(jump());
-}
-
-void Assembler::addPatch(V4IR::BasicBlock* targetBlock, Jump targetJump)
-{
- _patches[targetBlock].append(targetJump);
-}
-
-void Assembler::addPatch(DataLabelPtr patch, Label target)
-{
- DataLabelPatch p;
- p.dataLabel = patch;
- p.target = target;
- _dataLabelPatches.append(p);
-}
-
-void Assembler::addPatch(DataLabelPtr patch, V4IR::BasicBlock *target)
-{
- _labelPatches[target].append(patch);
-}
-
-void Assembler::generateCJumpOnNonZero(RegisterID reg, V4IR::BasicBlock *currentBlock,
- V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock)
-{
- generateCJumpOnCompare(NotEqual, reg, TrustedImm32(0), currentBlock, trueBlock, falseBlock);
-}
-
-void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left,TrustedImm32 right,
- V4IR::BasicBlock *currentBlock, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- if (trueBlock == _nextBlock) {
- Jump target = branch32(invert(cond), left, right);
- addPatch(falseBlock, target);
- } else {
- Jump target = branch32(cond, left, right);
- addPatch(trueBlock, target);
- jumpToBlock(currentBlock, falseBlock);
- }
-}
-
-void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left, RegisterID right,
- V4IR::BasicBlock *currentBlock, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- if (trueBlock == _nextBlock) {
- Jump target = branch32(invert(cond), left, right);
- addPatch(falseBlock, target);
- } else {
- Jump target = branch32(cond, left, right);
- addPatch(trueBlock, target);
- jumpToBlock(currentBlock, falseBlock);
- }
-}
-
-Assembler::Pointer Assembler::loadTempAddress(RegisterID baseReg, V4IR::Temp *t)
-{
- int32_t offset = 0;
- int scope = t->scope;
- RegisterID context = ContextRegister;
- if (scope) {
- loadPtr(Address(ContextRegister, qOffsetOf(ExecutionContext, outer)), baseReg);
- --scope;
- context = baseReg;
- while (scope) {
- loadPtr(Address(context, qOffsetOf(ExecutionContext, outer)), context);
- --scope;
- }
- }
- switch (t->kind) {
- case V4IR::Temp::Formal:
- case V4IR::Temp::ScopedFormal: {
- loadPtr(Address(context, qOffsetOf(ExecutionContext, callData)), baseReg);
- offset = sizeof(CallData) + (t->index - 1) * sizeof(SafeValue);
- } break;
- case V4IR::Temp::Local:
- case V4IR::Temp::ScopedLocal: {
- loadPtr(Address(context, qOffsetOf(CallContext, locals)), baseReg);
- offset = t->index * sizeof(SafeValue);
- } break;
- case V4IR::Temp::StackSlot: {
- return stackSlotPointer(t);
- } break;
- default:
- Q_UNREACHABLE();
- }
- return Pointer(baseReg, offset);
-}
-
-Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &string)
-{
- loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, compilationUnit)), Assembler::ScratchRegister);
- loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
- const int id = _isel->registerString(string);
- return Pointer(reg, id * sizeof(QV4::SafeString));
-}
-
-void Assembler::loadStringRef(RegisterID reg, const QString &string)
-{
- loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, compilationUnit)), reg);
- loadPtr(Address(reg, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
- const int id = _isel->registerString(string);
- addPtr(TrustedImmPtr(id * sizeof(QV4::SafeString)), reg);
-}
-
-template <typename Result, typename Source>
-void Assembler::copyValue(Result result, Source source)
-{
-#ifdef VALUE_FITS_IN_REGISTER
- // Use ReturnValueRegister as "scratch" register because loadArgument
- // and storeArgument are functions that may need a scratch register themselves.
- loadArgumentInRegister(source, ReturnValueRegister, 0);
- storeReturnValue(result);
-#else
- loadDouble(source, FPGpr0);
- storeDouble(FPGpr0, result);
-#endif
-}
-
-template <typename Result>
-void Assembler::copyValue(Result result, V4IR::Expr* source)
-{
- if (source->type == V4IR::BoolType) {
- RegisterID reg = toInt32Register(source, ScratchRegister);
- storeBool(reg, result);
- } else if (source->type == V4IR::SInt32Type) {
- RegisterID reg = toInt32Register(source, ScratchRegister);
- storeInt32(reg, result);
- } else if (source->type == V4IR::UInt32Type) {
- RegisterID reg = toUInt32Register(source, ScratchRegister);
- storeUInt32(reg, result);
- } else if (source->type == V4IR::DoubleType) {
- storeDouble(toDoubleRegister(source), result);
- } else if (V4IR::Temp *temp = source->asTemp()) {
-#ifdef VALUE_FITS_IN_REGISTER
- Q_UNUSED(temp);
-
- // Use ReturnValueRegister as "scratch" register because loadArgument
- // and storeArgument are functions that may need a scratch register themselves.
- loadArgumentInRegister(source, ReturnValueRegister, 0);
- storeReturnValue(result);
-#else
- loadDouble(temp, FPGpr0);
- storeDouble(FPGpr0, result);
-#endif
- } else if (V4IR::Const *c = source->asConst()) {
- QV4::Primitive v = convertToValue(c);
- storeValue(v, result);
- } else {
- Q_UNREACHABLE();
- }
-}
-
-void Assembler::storeValue(QV4::Primitive value, V4IR::Temp* destination)
-{
- Address addr = loadTempAddress(ScratchRegister, destination);
- storeValue(value, addr);
-}
-
-void Assembler::enterStandardStackFrame()
-{
- platformEnterStandardStackFrame();
-
- // ### FIXME: Handle through calleeSavedRegisters mechanism
- // or eliminate StackFrameRegister altogether.
- push(StackFrameRegister);
- move(StackPointerRegister, StackFrameRegister);
-
- int frameSize = _stackLayout.calculateStackFrameSize();
-
- subPtr(TrustedImm32(frameSize), StackPointerRegister);
-
- for (int i = 0; i < calleeSavedRegisterCount; ++i)
- storePtr(calleeSavedRegisters[i], Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
-
-}
-
-void Assembler::leaveStandardStackFrame()
-{
- // restore the callee saved registers
- for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
- loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i]);
-
- int frameSize = _stackLayout.calculateStackFrameSize();
- // Work around bug in ARMv7Assembler.h where add32(imm, sp, sp) doesn't
- // work well for large immediates.
-#if CPU(ARM_THUMB2)
- move(TrustedImm32(frameSize), JSC::ARMRegisters::r3);
- add32(JSC::ARMRegisters::r3, StackPointerRegister);
-#else
- addPtr(TrustedImm32(frameSize), StackPointerRegister);
-#endif
-
- pop(StackFrameRegister);
- platformLeaveStandardStackFrame();
-}
-
-
-
-#define OP(op) \
- { isel_stringIfy(op), op, 0, 0, 0 }
-#define OPCONTEXT(op) \
- { isel_stringIfy(op), 0, op, 0, 0 }
-
-#define INLINE_OP(op, memOp, immOp) \
- { isel_stringIfy(op), op, 0, memOp, immOp }
-#define INLINE_OPCONTEXT(op, memOp, immOp) \
- { isel_stringIfy(op), 0, op, memOp, immOp }
-
-#define NULL_OP \
- { 0, 0, 0, 0, 0 }
-
-const Assembler::BinaryOperationInfo Assembler::binaryOperations[QQmlJS::V4IR::LastAluOp + 1] = {
- NULL_OP, // OpInvalid
- NULL_OP, // OpIfTrue
- NULL_OP, // OpNot
- NULL_OP, // OpUMinus
- NULL_OP, // OpUPlus
- NULL_OP, // OpCompl
- NULL_OP, // OpIncrement
- NULL_OP, // OpDecrement
-
- INLINE_OP(__qmljs_bit_and, &Assembler::inline_and32, &Assembler::inline_and32), // OpBitAnd
- INLINE_OP(__qmljs_bit_or, &Assembler::inline_or32, &Assembler::inline_or32), // OpBitOr
- INLINE_OP(__qmljs_bit_xor, &Assembler::inline_xor32, &Assembler::inline_xor32), // OpBitXor
-
- INLINE_OPCONTEXT(__qmljs_add, &Assembler::inline_add32, &Assembler::inline_add32), // OpAdd
- INLINE_OP(__qmljs_sub, &Assembler::inline_sub32, &Assembler::inline_sub32), // OpSub
- INLINE_OP(__qmljs_mul, &Assembler::inline_mul32, &Assembler::inline_mul32), // OpMul
-
- OP(__qmljs_div), // OpDiv
- OP(__qmljs_mod), // OpMod
-
- INLINE_OP(__qmljs_shl, &Assembler::inline_shl32, &Assembler::inline_shl32), // OpLShift
- INLINE_OP(__qmljs_shr, &Assembler::inline_shr32, &Assembler::inline_shr32), // OpRShift
- INLINE_OP(__qmljs_ushr, &Assembler::inline_ushr32, &Assembler::inline_ushr32), // OpURShift
-
- OP(__qmljs_gt), // OpGt
- OP(__qmljs_lt), // OpLt
- OP(__qmljs_ge), // OpGe
- OP(__qmljs_le), // OpLe
- OP(__qmljs_eq), // OpEqual
- OP(__qmljs_ne), // OpNotEqual
- OP(__qmljs_se), // OpStrictEqual
- OP(__qmljs_sne), // OpStrictNotEqual
-
- OPCONTEXT(__qmljs_instanceof), // OpInstanceof
- OPCONTEXT(__qmljs_in), // OpIn
-
- NULL_OP, // OpAnd
- NULL_OP // OpOr
-};
-
-#if OS(LINUX) || OS(MAC_OS_X)
-static void printDisassembledOutputWithCalls(const char* output, const QHash<void*, const char*>& functions)
-{
- QByteArray processedOutput(output);
- for (QHash<void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
- it != end; ++it) {
- QByteArray ptrString = QByteArray::number(quintptr(it.key()), 16);
- ptrString.prepend("0x");
- processedOutput = processedOutput.replace(ptrString, it.value());
- }
- fprintf(stderr, "%s\n", processedOutput.constData());
-}
-#endif
-
-JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
-{
- Label endOfCode = label();
-
- {
- QHashIterator<V4IR::BasicBlock *, QVector<Jump> > it(_patches);
- while (it.hasNext()) {
- it.next();
- V4IR::BasicBlock *block = it.key();
- Label target = _addrs.value(block);
- assert(target.isSet());
- foreach (Jump jump, it.value())
- jump.linkTo(target, this);
- }
- }
-
- JSC::JSGlobalData dummy(_executableAllocator);
- JSC::LinkBuffer linkBuffer(dummy, this, 0);
-
- QHash<void*, const char*> functions;
- foreach (CallToLink ctl, _callsToLink) {
- linkBuffer.link(ctl.call, ctl.externalFunction);
- functions[ctl.externalFunction.value()] = ctl.functionName;
- }
-
- foreach (const DataLabelPatch &p, _dataLabelPatches)
- linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target));
-
- // link exception handlers
- foreach(Jump jump, exceptionPropagationJumps)
- linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel));
-
- {
- QHashIterator<V4IR::BasicBlock *, QVector<DataLabelPtr> > it(_labelPatches);
- while (it.hasNext()) {
- it.next();
- V4IR::BasicBlock *block = it.key();
- Label target = _addrs.value(block);
- assert(target.isSet());
- foreach (DataLabelPtr label, it.value())
- linkBuffer.patch(label, linkBuffer.locationOf(target));
- }
- }
- _constTable.finalize(linkBuffer, _isel);
-
- *codeSize = linkBuffer.offsetOf(endOfCode);
-
- JSC::MacroAssemblerCodeRef codeRef;
-
- static bool showCode = !qgetenv("QV4_SHOW_ASM").isNull();
- if (showCode) {
-#if OS(LINUX) && !defined(Q_OS_ANDROID)
- char* disasmOutput = 0;
- size_t disasmLength = 0;
- FILE* disasmStream = open_memstream(&disasmOutput, &disasmLength);
- WTF::setDataFile(disasmStream);
-#elif OS(MAC_OS_X)
- struct MemStream {
- QByteArray buf;
- static int write(void *cookie, const char *buf, int len) {
- MemStream *stream = reinterpret_cast<MemStream *>(cookie);
- stream->buf.append(buf, len);
- return len;
- }
- };
- MemStream memStream;
-
- FILE* disasmStream = fwopen(&memStream, MemStream::write);
- WTF::setDataFile(disasmStream);
-#endif
-
- QByteArray name = _function->name->toUtf8();
- if (name.isEmpty()) {
- name = QByteArray::number(quintptr(_function), 16);
- name.prepend("IR::Function(0x");
- name.append(")");
- }
- codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
-
- WTF::setDataFile(stderr);
-#if (OS(LINUX) && !defined(Q_OS_ANDROID)) || OS(MAC_OS_X)
- fclose(disasmStream);
-# if OS(MAC_OS_X)
- char *disasmOutput = memStream.buf.data();
-# endif
-# if CPU(X86) || CPU(X86_64) || CPU(ARM)
- QHash<void*, String*> idents;
- printDisassembledOutputWithCalls(disasmOutput, functions);
-# endif
-# if OS(LINUX)
- free(disasmOutput);
-# endif
-#endif
- } else {
- codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
- }
-
- return codeRef;
-}
-
-InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, Compiler::JSUnitGenerator *jsGenerator)
- : EvalInstructionSelection(execAllocator, module, jsGenerator)
- , _block(0)
- , _as(0)
- , qmlEngine(qmlEngine)
-{
- compilationUnit = new CompilationUnit;
- compilationUnit->codeRefs.resize(module->functions.size());
- compilationUnit->codeSizes.resize(module->functions.size());
-}
-
-InstructionSelection::~InstructionSelection()
-{
- delete _as;
-}
-
-void InstructionSelection::run(int functionIndex)
-{
- V4IR::Function *function = irModule->functions[functionIndex];
- QVector<Lookup> lookups;
- qSwap(_function, function);
-
- V4IR::Optimizer opt(_function);
- opt.run(qmlEngine);
-
-#if (CPU(X86_64) && (OS(MAC_OS_X) || OS(LINUX))) || (CPU(X86) && OS(LINUX))
- static const bool withRegisterAllocator = qgetenv("QV4_NO_REGALLOC").isEmpty();
- if (opt.isInSSA() && withRegisterAllocator) {
-#if CPU(X86) && OS(LINUX) // x86 with linux
- static const QVector<int> intRegisters = QVector<int>()
- << JSC::X86Registers::edx
- << JSC::X86Registers::ebx;
-#else // x86_64 with linux or with macos
- static const QVector<int> intRegisters = QVector<int>()
- << JSC::X86Registers::edi
- << JSC::X86Registers::esi
- << JSC::X86Registers::edx
- << JSC::X86Registers::r9
- << JSC::X86Registers::r8
- << JSC::X86Registers::r13
- << JSC::X86Registers::r15;
-#endif
- static const QVector<int> fpRegisters = QVector<int>()
- << JSC::X86Registers::xmm2
- << JSC::X86Registers::xmm3
- << JSC::X86Registers::xmm4
- << JSC::X86Registers::xmm5
- << JSC::X86Registers::xmm6
- << JSC::X86Registers::xmm7;
- RegisterAllocator(intRegisters, fpRegisters).run(_function, opt);
- } else
-#endif
- {
- if (opt.isInSSA())
- // No register allocator available for this platform, or env. var was set, so:
- opt.convertOutOfSSA();
- ConvertTemps().toStackSlots(_function);
- }
- V4IR::Optimizer::showMeTheCode(_function);
- QSet<V4IR::Jump *> removableJumps = opt.calculateOptionalJumps();
- qSwap(_removableJumps, removableJumps);
-
- Assembler* oldAssembler = _as;
- _as = new Assembler(this, _function, executableAllocator, 6); // 6 == max argc for calls to built-ins with an argument array
-
- _as->enterStandardStackFrame();
-
-#ifdef ARGUMENTS_IN_REGISTERS
- _as->move(_as->registerForArgument(0), Assembler::ContextRegister);
-#else
- _as->loadPtr(addressForArgument(0), Assembler::ContextRegister);
-#endif
-
- const int locals = _as->stackLayout().calculateJSStackFrameSize();
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, engine)), Assembler::ScratchRegister);
- _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
- _as->addPtr(Assembler::TrustedImm32(sizeof(QV4::SafeValue)*locals), Assembler::LocalsRegister);
- _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
-
- int lastLine = -1;
- for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
- V4IR::BasicBlock *nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
- _block = _function->basicBlocks[i];
- _as->registerBlock(_block, nextBlock);
-
- foreach (V4IR::Stmt *s, _block->statements) {
- if (s->location.isValid()) {
- if (int(s->location.startLine) != lastLine) {
- Assembler::Address lineAddr(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, lineNumber));
- _as->store32(Assembler::TrustedImm32(s->location.startLine), lineAddr);
- lastLine = s->location.startLine;
- }
- }
- s->accept(this);
- }
- }
-
- if (!_as->exceptionReturnLabel.isSet())
- visitRet(0);
-
- JSC::MacroAssemblerCodeRef codeRef =_as->link(&compilationUnit->codeSizes[functionIndex]);
- compilationUnit->codeRefs[functionIndex] = codeRef;
-
- qSwap(_function, function);
- delete _as;
- _as = oldAssembler;
- qSwap(_removableJumps, removableJumps);
-}
-
-void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
-{
- compilationUnit->constantValues.append(*values);
- values->clear();
-
- QVector<QV4::Primitive> &finalValues = compilationUnit->constantValues.last();
- finalValues.squeeze();
- return finalValues.data();
-}
-
-QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
-{
- return compilationUnit;
-}
-
-void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
-{
- prepareCallData(args, 0);
-
- if (useFastLookups && func->global) {
- uint index = registerGlobalGetterLookup(*func->id);
- generateFunctionCall(result, __qmljs_call_global_lookup,
- Assembler::ContextRegister,
- Assembler::TrustedImm32(index),
- baseAddressForCallData());
- } else {
- generateFunctionCall(result, __qmljs_call_activation_property,
- Assembler::ContextRegister,
- Assembler::PointerToString(*func->id),
- baseAddressForCallData());
- }
-}
-
-void InstructionSelection::callBuiltinTypeofMember(V4IR::Expr *base, const QString &name,
- V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_builtin_typeof_member, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToString(name));
-}
-
-void InstructionSelection::callBuiltinTypeofSubscript(V4IR::Expr *base, V4IR::Expr *index,
- V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_builtin_typeof_element,
- Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToValue(index));
-}
-
-void InstructionSelection::callBuiltinTypeofName(const QString &name, V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_builtin_typeof_name, Assembler::ContextRegister,
- Assembler::PointerToString(name));
-}
-
-void InstructionSelection::callBuiltinTypeofValue(V4IR::Expr *value, V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_builtin_typeof, Assembler::ContextRegister,
- Assembler::PointerToValue(value));
-}
-
-void InstructionSelection::callBuiltinDeleteMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_delete_member, Assembler::ContextRegister,
- Assembler::Reference(base), Assembler::PointerToString(name));
-}
-
-void InstructionSelection::callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Expr *index,
- V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_delete_subscript, Assembler::ContextRegister,
- Assembler::Reference(base), Assembler::PointerToValue(index));
-}
-
-void InstructionSelection::callBuiltinDeleteName(const QString &name, V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_delete_name, Assembler::ContextRegister,
- Assembler::PointerToString(name));
-}
-
-void InstructionSelection::callBuiltinDeleteValue(V4IR::Temp *result)
-{
- _as->storeValue(Primitive::fromBoolean(false), result);
-}
-
-void InstructionSelection::callBuiltinThrow(V4IR::Expr *arg)
-{
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_throw, Assembler::ContextRegister,
- Assembler::PointerToValue(arg));
-}
-
-void InstructionSelection::callBuiltinReThrow()
-{
- _as->jumpToExceptionHandler();
-}
-
-void InstructionSelection::callBuiltinUnwindException(V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_builtin_unwind_exception, Assembler::ContextRegister);
-
-}
-
-void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName)
-{
- Assembler::Pointer s = _as->loadStringAddress(Assembler::ScratchRegister, exceptionName);
- generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_push_catch_scope, Assembler::ContextRegister, s);
-}
-
-void InstructionSelection::callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result)
-{
- Q_ASSERT(arg);
- Q_ASSERT(result);
-
- generateFunctionCall(result, __qmljs_foreach_iterator_object, Assembler::ContextRegister, Assembler::Reference(arg));
-}
-
-void InstructionSelection::callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result)
-{
- Q_ASSERT(arg);
- Q_ASSERT(result);
-
- generateFunctionCall(result, __qmljs_foreach_next_property_name, Assembler::Reference(arg));
-}
-
-void InstructionSelection::callBuiltinPushWithScope(V4IR::Temp *arg)
-{
- Q_ASSERT(arg);
-
- generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_push_with_scope, Assembler::Reference(arg), Assembler::ContextRegister);
-}
-
-void InstructionSelection::callBuiltinPopScope()
-{
- generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_pop_scope, Assembler::ContextRegister);
-}
-
-void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name)
-{
- generateFunctionCall(Assembler::Void, __qmljs_builtin_declare_var, Assembler::ContextRegister,
- Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
-}
-
-void InstructionSelection::callBuiltinDefineGetterSetter(V4IR::Temp *object, const QString &name, V4IR::Temp *getter, V4IR::Temp *setter)
-{
- Q_ASSERT(object);
- Q_ASSERT(getter);
- Q_ASSERT(setter);
- generateFunctionCall(Assembler::Void, __qmljs_builtin_define_getter_setter, Assembler::ContextRegister,
- Assembler::Reference(object), Assembler::PointerToString(name), Assembler::PointerToValue(getter), Assembler::PointerToValue(setter));
-}
-
-void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const QString &name,
- V4IR::Expr *value)
-{
- Q_ASSERT(object);
- Q_ASSERT(value->asTemp() || value->asConst());
-
- generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property,
- Assembler::ContextRegister, Assembler::Reference(object),
- Assembler::PointerToString(name),
- Assembler::PointerToValue(value));
-}
-
-void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args)
-{
- Q_ASSERT(result);
-
- int length = prepareVariableArguments(args);
- generateFunctionCall(result, __qmljs_builtin_define_array, Assembler::ContextRegister,
- baseAddressForCallArguments(), Assembler::TrustedImm32(length));
-}
-
-void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args)
-{
- Q_ASSERT(result);
-
- int argc = 0;
-
- const int classId = registerJSClass(args);
-
- V4IR::ExprList *it = args;
- while (it) {
- it = it->next;
-
- bool isData = it->expr->asConst()->value;
- it = it->next;
-
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
-
- if (!isData) {
- it = it->next;
- _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
- }
-
- it = it->next;
- }
-
- generateFunctionCall(result, __qmljs_builtin_define_object_literal, Assembler::ContextRegister,
- baseAddressForCallArguments(), Assembler::TrustedImm32(classId));
-}
-
-void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result)
-{
- generateFunctionCall(result, __qmljs_builtin_setup_arguments_object, Assembler::ContextRegister);
-}
-
-void InstructionSelection::callBuiltinConvertThisToObject()
-{
- generateFunctionCall(Assembler::Void, __qmljs_builtin_convert_this_to_object, Assembler::ContextRegister);
-}
-
-void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
-{
- Q_ASSERT(value);
-
- prepareCallData(args, 0);
- generateFunctionCall(result, __qmljs_call_value, Assembler::ContextRegister,
- Assembler::Reference(value),
- baseAddressForCallData());
-}
-
-void InstructionSelection::loadThisObject(V4IR::Temp *temp)
-{
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, callData)), Assembler::ScratchRegister);
-#if defined(VALUE_FITS_IN_REGISTER)
- _as->load64(Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)),
- Assembler::ReturnValueRegister);
- _as->storeReturnValue(temp);
-#else
- _as->copyValue(temp, Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)));
-#endif
-}
-
-void InstructionSelection::loadQmlIdArray(V4IR::Temp *temp)
-{
- generateFunctionCall(temp, __qmljs_get_id_array, Assembler::ContextRegister);
-}
-
-void InstructionSelection::loadQmlImportedScripts(V4IR::Temp *temp)
-{
- generateFunctionCall(temp, __qmljs_get_imported_scripts, Assembler::ContextRegister);
-}
-
-void InstructionSelection::loadQmlContextObject(V4IR::Temp *temp)
-{
- generateFunctionCall(temp, __qmljs_get_context_object, Assembler::ContextRegister);
-}
-
-void InstructionSelection::loadQmlScopeObject(V4IR::Temp *temp)
-{
- generateFunctionCall(temp, __qmljs_get_scope_object, Assembler::ContextRegister);
-}
-
-void InstructionSelection::loadQmlSingleton(const QString &name, V4IR::Temp *temp)
-{
- generateFunctionCall(temp, __qmljs_get_qml_singleton, Assembler::ContextRegister, Assembler::PointerToString(name));
-}
-
-void InstructionSelection::loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp)
-{
- if (targetTemp->kind == V4IR::Temp::PhysicalRegister) {
- if (targetTemp->type == V4IR::DoubleType) {
- Q_ASSERT(sourceConst->type == V4IR::DoubleType);
- _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
- } else if (targetTemp->type == V4IR::SInt32Type) {
- Q_ASSERT(sourceConst->type == V4IR::SInt32Type);
- _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
- } else if (targetTemp->type == V4IR::UInt32Type) {
- Q_ASSERT(sourceConst->type == V4IR::UInt32Type);
- _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
- } else if (targetTemp->type == V4IR::BoolType) {
- Q_ASSERT(sourceConst->type == V4IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
- (Assembler::RegisterID) targetTemp->index);
- } else {
- Q_UNREACHABLE();
- }
- } else {
- _as->storeValue(convertToValue(sourceConst), targetTemp);
- }
-}
-
-void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp)
-{
- Pointer srcAddr = _as->loadStringAddress(Assembler::ReturnValueRegister, str);
- _as->loadPtr(srcAddr, Assembler::ReturnValueRegister);
- Pointer destAddr = _as->loadTempAddress(Assembler::ScratchRegister, targetTemp);
-#if QT_POINTER_SIZE == 8
- _as->store64(Assembler::ReturnValueRegister, destAddr);
-#else
- _as->store32(Assembler::ReturnValueRegister, destAddr);
- destAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type), destAddr);
-#endif
-}
-
-void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
-{
- int id = registerRegExp(sourceRegexp);
- generateFunctionCall(targetTemp, __qmljs_lookup_runtime_regexp, Assembler::ContextRegister, Assembler::TrustedImm32(id));
-}
-
-void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
-{
- if (useFastLookups && name->global) {
- uint index = registerGlobalGetterLookup(*name->id);
- generateLookupCall(temp, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
- return;
- }
- generateFunctionCall(temp, __qmljs_get_activation_property, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
-}
-
-void InstructionSelection::setActivationProperty(V4IR::Expr *source, const QString &targetName)
-{
- // ### should use a lookup call here
- generateFunctionCall(Assembler::Void, __qmljs_set_activation_property,
- Assembler::ContextRegister, Assembler::PointerToString(targetName), Assembler::PointerToValue(source));
-}
-
-void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *target)
-{
- int id = closure->value;
- generateFunctionCall(target, __qmljs_init_closure, Assembler::ContextRegister, Assembler::TrustedImm32(id));
-}
-
-void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target)
-{
- if (useFastLookups) {
- uint index = registerGetterLookup(name);
- generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), Assembler::PointerToValue(base), Assembler::Void);
- } else {
- generateFunctionCall(target, __qmljs_get_property, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToString(name));
- }
-}
-
-void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target)
-{
- if (attachedPropertiesId != 0)
- generateFunctionCall(target, __qmljs_get_attached_property, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
- else
- generateFunctionCall(target, __qmljs_get_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
- Assembler::TrustedImm32(captureRequired));
-}
-
-void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBase,
- const QString &targetName)
-{
- if (useFastLookups) {
- uint index = registerSetterLookup(targetName);
- generateLookupCall(Assembler::Void, index, qOffsetOf(QV4::Lookup, setter),
- Assembler::PointerToValue(targetBase),
- Assembler::PointerToValue(source));
- } else {
- generateFunctionCall(Assembler::Void, __qmljs_set_property, Assembler::ContextRegister,
- Assembler::PointerToValue(targetBase), Assembler::PointerToString(targetName),
- Assembler::PointerToValue(source));
- }
-}
-
-void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex)
-{
- generateFunctionCall(Assembler::Void, __qmljs_set_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(targetBase),
- Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
-}
-
-void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
-{
-#if QT_POINTER_SIZE == 8
- V4IR::Temp *tbase = base->asTemp();
- V4IR::Temp *tindex = index->asTemp();
- if (tbase && tindex &&
- tbase->kind != V4IR::Temp::PhysicalRegister) {
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
- _as->load64(addr, Assembler::ScratchRegister);
- _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsManaged_Shift), Assembler::ReturnValueRegister);
- Assembler::Jump notManaged = _as->branch64(Assembler::NotEqual, Assembler::ReturnValueRegister, Assembler::TrustedImm64(0));
- // check whether we have an object with a simple array
- Assembler::Address managedType(Assembler::ScratchRegister, qOffsetOf(QV4::Managed, flags));
- _as->load8(managedType, Assembler::ReturnValueRegister);
- _as->and32(Assembler::TrustedImm32(QV4::Managed::SimpleArray), Assembler::ReturnValueRegister);
- Assembler::Jump notSimple = _as->branch32(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0));
-
- bool needNegativeCheck = false;
- Assembler::Jump fallback, fallback2;
- if (tindex->kind == V4IR::Temp::PhysicalRegister) {
- if (tindex->type == V4IR::SInt32Type) {
- fallback = _as->branch32(Assembler::LessThan, (Assembler::RegisterID)tindex->index, Assembler::TrustedImm32(0));
- _as->move((Assembler::RegisterID) tindex->index, Assembler::ScratchRegister);
- needNegativeCheck = true;
- } else {
- // double, convert and check if it's a int
- fallback2 = _as->branchTruncateDoubleToUint32((Assembler::FPRegisterID) tindex->index, Assembler::ScratchRegister);
- _as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr0);
- fallback = _as->branchDouble(Assembler::DoubleNotEqual, Assembler::FPGpr0, (Assembler::FPRegisterID) tindex->index);
- }
- } else {
- Assembler::Pointer indexAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, tindex);
- _as->load64(indexAddr, Assembler::ScratchRegister);
- _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ReturnValueRegister);
- Assembler::Jump isInteger = _as->branch64(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm64(1));
-
- // other type, convert to double and check if it's a int
- // this check is ok to do even if the type is something else than a double, as
- // that would result in a NaN
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ReturnValueRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
- fallback2 = _as->branchTruncateDoubleToUint32(Assembler::FPGpr0, Assembler::ScratchRegister);
- _as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr1);
- fallback = _as->branchDouble(Assembler::DoubleNotEqualOrUnordered, Assembler::FPGpr0, Assembler::FPGpr1);
-
- isInteger.link(_as);
- _as->or32(Assembler::TrustedImm32(0), Assembler::ScratchRegister);
- needNegativeCheck = true;
- }
-
- // get data, ScratchRegister holds index
- addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
- _as->load64(addr, Assembler::ReturnValueRegister);
- Address arrayDataLen(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayDataLen));
- Assembler::Jump outOfRange;
- if (needNegativeCheck)
- outOfRange = _as->branch32(Assembler::LessThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
- Assembler::Jump outOfRange2 = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, arrayDataLen);
- Address arrayData(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData));
- _as->load64(arrayData, Assembler::ReturnValueRegister);
- Q_ASSERT(sizeof(Property) == (1<<4));
- _as->lshift64(Assembler::TrustedImm32(4), Assembler::ScratchRegister);
- _as->add64(Assembler::ReturnValueRegister, Assembler::ScratchRegister);
- Address value(Assembler::ScratchRegister, qOffsetOf(Property, value));
- _as->load64(value, Assembler::ReturnValueRegister);
-
- // check that the value is not empty
- _as->move(Assembler::ReturnValueRegister, Assembler::ScratchRegister);
- _as->urshift64(Assembler::TrustedImm32(32), Assembler::ScratchRegister);
- Assembler::Jump emptyValue = _as->branch32(Assembler::Equal, Assembler::TrustedImm32(QV4::Value::Empty_Type), Assembler::ScratchRegister);
- _as->storeReturnValue(target);
-
- Assembler::Jump done = _as->jump();
-
- emptyValue.link(_as);
- if (outOfRange.isSet())
- outOfRange.link(_as);
- outOfRange2.link(_as);
- if (fallback.isSet())
- fallback.link(_as);
- if (fallback2.isSet())
- fallback2.link(_as);
- notSimple.link(_as);
- notManaged.link(_as);
-
- generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToValue(index));
-
- done.link(_as);
- return;
- }
-#endif
-
- generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToValue(index));
-}
-
-void InstructionSelection::setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex)
-{
- generateFunctionCall(Assembler::Void, __qmljs_set_element, Assembler::ContextRegister,
- Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
- Assembler::PointerToValue(source));
-}
-
-void InstructionSelection::copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
-{
- if (*sourceTemp == *targetTemp)
- return;
-
- if (sourceTemp->kind == V4IR::Temp::PhysicalRegister) {
- if (targetTemp->kind == V4IR::Temp::PhysicalRegister) {
- if (sourceTemp->type == V4IR::DoubleType)
- _as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
- (Assembler::FPRegisterID) targetTemp->index);
- else
- _as->move((Assembler::RegisterID) sourceTemp->index,
- (Assembler::RegisterID) targetTemp->index);
- return;
- } else {
- switch (sourceTemp->type) {
- case V4IR::DoubleType:
- _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, targetTemp);
- break;
- case V4IR::SInt32Type:
- _as->storeInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
- break;
- case V4IR::UInt32Type:
- _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
- break;
- case V4IR::BoolType:
- _as->storeBool((Assembler::RegisterID) sourceTemp->index, targetTemp);
- break;
- default:
- Q_ASSERT(!"Unreachable");
- break;
- }
- return;
- }
- } else if (targetTemp->kind == V4IR::Temp::PhysicalRegister) {
- switch (targetTemp->type) {
- case V4IR::DoubleType:
- Q_ASSERT(sourceTemp->type == V4IR::DoubleType);
- _as->toDoubleRegister(sourceTemp, (Assembler::FPRegisterID) targetTemp->index);
- return;
- case V4IR::BoolType:
- Q_ASSERT(sourceTemp->type == V4IR::BoolType);
- _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
- return;
- case V4IR::SInt32Type:
- Q_ASSERT(sourceTemp->type == V4IR::SInt32Type);
- _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
- return;
- case V4IR::UInt32Type:
- Q_ASSERT(sourceTemp->type == V4IR::UInt32Type);
- _as->toUInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
- return;
- default:
- Q_ASSERT(!"Unreachable");
- break;
- }
- }
-
- // The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
- _as->memcopyValue(_as->loadTempAddress(Assembler::ReturnValueRegister, targetTemp), sourceTemp,
- Assembler::ScratchRegister);
-}
-
-void InstructionSelection::swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
-{
- if (sourceTemp->kind == V4IR::Temp::PhysicalRegister) {
- if (targetTemp->kind == V4IR::Temp::PhysicalRegister) {
- Q_ASSERT(sourceTemp->type == targetTemp->type);
-
- if (sourceTemp->type == V4IR::DoubleType) {
- _as->moveDouble((Assembler::FPRegisterID) targetTemp->index, Assembler::FPGpr0);
- _as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
- (Assembler::FPRegisterID) targetTemp->index);
- _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) sourceTemp->index);
- } else {
- _as->swap((Assembler::RegisterID) sourceTemp->index,
- (Assembler::RegisterID) targetTemp->index);
- }
- return;
- }
- } else if (sourceTemp->kind == V4IR::Temp::StackSlot) {
- if (targetTemp->kind == V4IR::Temp::StackSlot) {
- // Note: a swap for two stack-slots can involve different types.
-#if CPU(X86_64)
- _as->load64(_as->stackSlotPointer(targetTemp), Assembler::ReturnValueRegister);
- _as->load64(_as->stackSlotPointer(sourceTemp), Assembler::ScratchRegister);
- _as->store64(Assembler::ScratchRegister, _as->stackSlotPointer(targetTemp));
- _as->store64(Assembler::ReturnValueRegister, _as->stackSlotPointer(sourceTemp));
-#else
- Assembler::FPRegisterID tReg = _as->toDoubleRegister(targetTemp);
- Assembler::Pointer sAddr = _as->stackSlotPointer(sourceTemp);
- Assembler::Pointer tAddr = _as->stackSlotPointer(targetTemp);
- _as->load32(sAddr, Assembler::ScratchRegister);
- _as->store32(Assembler::ScratchRegister, tAddr);
- sAddr.offset += 4;
- tAddr.offset += 4;
- _as->load32(sAddr, Assembler::ScratchRegister);
- _as->store32(Assembler::ScratchRegister, tAddr);
- _as->storeDouble(tReg, _as->stackSlotPointer(sourceTemp));
-#endif
- return;
- }
- }
-
- V4IR::Temp *stackTemp = sourceTemp->kind == V4IR::Temp::StackSlot ? sourceTemp : targetTemp;
- V4IR::Temp *registerTemp = sourceTemp->kind == V4IR::Temp::PhysicalRegister ? sourceTemp
- : targetTemp;
- Assembler::Pointer addr = _as->stackSlotPointer(stackTemp);
- if (registerTemp->type == V4IR::DoubleType) {
- _as->loadDouble(addr, Assembler::FPGpr0);
- _as->storeDouble((Assembler::FPRegisterID) registerTemp->index, addr);
- _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) registerTemp->index);
- } else if (registerTemp->type == V4IR::UInt32Type) {
- _as->toUInt32Register(addr, Assembler::ScratchRegister);
- _as->storeUInt32((Assembler::RegisterID) registerTemp->index, addr);
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
- } else {
- _as->load32(addr, Assembler::ScratchRegister);
- _as->store32((Assembler::RegisterID) registerTemp->index, addr);
- addr.offset += 4;
- quint32 tag;
- switch (registerTemp->type) {
- case V4IR::BoolType:
- tag = QV4::Value::_Boolean_Type;
- break;
- case V4IR::SInt32Type:
- tag = QV4::Value::_Integer_Type;
- break;
- default:
- tag = QV4::Value::Undefined_Type;
- Q_UNREACHABLE();
- }
- _as->store32(Assembler::TrustedImm32(tag), addr);
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
- }
-}
-
-#define setOp(op, opName, operation) \
- do { op = operation; opName = isel_stringIfy(operation); } while (0)
-#define setOpContext(op, opName, operation) \
- do { opContext = operation; opName = isel_stringIfy(operation); } while (0)
-
-void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
-{
- UnaryOpName op = 0;
- const char *opName = 0;
- switch (oper) {
- case V4IR::OpIfTrue: assert(!"unreachable"); break;
- case V4IR::OpNot:
- if (sourceTemp->type == V4IR::BoolType && targetTemp->type == V4IR::BoolType) {
- Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (targetTemp->kind == V4IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) targetTemp->index;
- _as->xor32(Assembler::TrustedImm32(0x1),
- _as->toInt32Register(sourceTemp, Assembler::ScratchRegister),
- tReg);
- if (targetTemp->kind != V4IR::Temp::PhysicalRegister)
- _as->storeBool(tReg, targetTemp);
- return;
- } else {
- setOp(op, opName, __qmljs_not); break;
- }
- case V4IR::OpUMinus: setOp(op, opName, __qmljs_uminus); break;
- case V4IR::OpUPlus: setOp(op, opName, __qmljs_uplus); break;
- case V4IR::OpCompl: setOp(op, opName, __qmljs_compl); break;
- case V4IR::OpIncrement: setOp(op, opName, __qmljs_increment); break;
- case V4IR::OpDecrement: setOp(op, opName, __qmljs_decrement); break;
- default: assert(!"unreachable"); break;
- } // switch
-
- if (op) {
- _as->generateFunctionCallImp(targetTemp, opName, op,
- Assembler::PointerToValue(sourceTemp));
- }
-}
-
-static inline Assembler::FPRegisterID getFreeFPReg(V4IR::Expr *shouldNotOverlap, unsigned hint)
-{
- if (V4IR::Temp *t = shouldNotOverlap->asTemp())
- if (t->type == V4IR::DoubleType)
- if (t->kind == V4IR::Temp::PhysicalRegister)
- if (t->index == hint)
- return Assembler::FPRegisterID(hint + 1);
- return Assembler::FPRegisterID(hint);
-}
-
-Assembler::Jump InstructionSelection::genInlineBinop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target)
-{
- Assembler::Jump done;
-
- // Try preventing a call for a few common binary operations. This is used in two cases:
- // - no register allocation was performed (not available for the platform, or the IR was
- // not transformed into SSA)
- // - type inference found that either or both operands can be of non-number type, and the
- // register allocator will have prepared for a call (meaning: all registers that do not
- // hold operands are spilled to the stack, which makes them available here)
- // Note: FPGPr0 can still not be used, because uint32->double conversion uses it as a scratch
- // register.
- switch (oper) {
- case V4IR::OpAdd: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
-
- _as->addDouble(rReg, lReg);
- _as->storeDouble(lReg, target);
- done = _as->jump();
-
- if (leftIsNoDbl.isSet())
- leftIsNoDbl.link(_as);
- if (rightIsNoDbl.isSet())
- rightIsNoDbl.link(_as);
- } break;
- case V4IR::OpMul: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
-
- _as->mulDouble(rReg, lReg);
- _as->storeDouble(lReg, target);
- done = _as->jump();
-
- if (leftIsNoDbl.isSet())
- leftIsNoDbl.link(_as);
- if (rightIsNoDbl.isSet())
- rightIsNoDbl.link(_as);
- } break;
- case V4IR::OpSub: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
-
- _as->subDouble(rReg, lReg);
- _as->storeDouble(lReg, target);
- done = _as->jump();
-
- if (leftIsNoDbl.isSet())
- leftIsNoDbl.link(_as);
- if (rightIsNoDbl.isSet())
- rightIsNoDbl.link(_as);
- } break;
- case V4IR::OpDiv: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
-
- _as->divDouble(rReg, lReg);
- _as->storeDouble(lReg, target);
- done = _as->jump();
-
- if (leftIsNoDbl.isSet())
- leftIsNoDbl.link(_as);
- if (rightIsNoDbl.isSet())
- rightIsNoDbl.link(_as);
- } break;
- default:
- break;
- }
-
- return done;
-}
-
-void InstructionSelection::binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target)
-{
- if (oper != V4IR::OpMod
- && leftSource->type == V4IR::DoubleType && rightSource->type == V4IR::DoubleType
- && isPregOrConst(leftSource) && isPregOrConst(rightSource)) {
- doubleBinop(oper, leftSource, rightSource, target);
- return;
- }
- if (leftSource->type == V4IR::SInt32Type && rightSource->type == V4IR::SInt32Type) {
- if (int32Binop(oper, leftSource, rightSource, target))
- return;
- }
-
- Assembler::Jump done;
- if (leftSource->type != V4IR::StringType && rightSource->type != V4IR::StringType)
- done = genInlineBinop(oper, leftSource, rightSource, target);
-
- // TODO: inline var===null and var!==null
- Assembler::BinaryOperationInfo info = Assembler::binaryOperation(oper);
-
- if (oper == V4IR::OpAdd &&
- (leftSource->type == V4IR::StringType || rightSource->type == V4IR::StringType)) {
- const Assembler::BinaryOperationInfo stringAdd = OPCONTEXT(__qmljs_add_string);
- info = stringAdd;
- }
-
- if (info.fallbackImplementation) {
- _as->generateFunctionCallImp(target, info.name, info.fallbackImplementation,
- Assembler::PointerToValue(leftSource),
- Assembler::PointerToValue(rightSource));
- } else if (info.contextImplementation) {
- _as->generateFunctionCallImp(target, info.name, info.contextImplementation,
- Assembler::ContextRegister,
- Assembler::PointerToValue(leftSource),
- Assembler::PointerToValue(rightSource));
- } else {
- assert(!"unreachable");
- }
-
- if (done.isSet())
- done.link(_as);
-}
-
-void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args,
- V4IR::Temp *result)
-{
- assert(base != 0);
-
- prepareCallData(args, base);
-
- if (useFastLookups) {
- uint index = registerGetterLookup(name);
- generateFunctionCall(result, __qmljs_call_property_lookup,
- Assembler::ContextRegister,
- Assembler::TrustedImm32(index),
- baseAddressForCallData());
- } else
- {
- generateFunctionCall(result, __qmljs_call_property, Assembler::ContextRegister,
- Assembler::PointerToString(name),
- baseAddressForCallData());
- }
-}
-
-void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args,
- V4IR::Temp *result)
-{
- assert(base != 0);
-
- prepareCallData(args, base);
- generateFunctionCall(result, __qmljs_call_element, Assembler::ContextRegister,
- Assembler::PointerToValue(index),
- baseAddressForCallData());
-}
-
-void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
-{
- switch (target->type) {
- case V4IR::DoubleType:
- convertTypeToDouble(source, target);
- break;
- case V4IR::BoolType:
- convertTypeToBool(source, target);
- break;
- case V4IR::SInt32Type:
- convertTypeToSInt32(source, target);
- break;
- case V4IR::UInt32Type:
- convertTypeToUInt32(source, target);
- break;
- default:
- convertTypeSlowPath(source, target);
- break;
- }
-}
-
-void InstructionSelection::convertTypeSlowPath(V4IR::Temp *source, V4IR::Temp *target)
-{
- Q_ASSERT(target->type != V4IR::BoolType);
-
- if (target->type & V4IR::NumberType)
- unop(V4IR::OpUPlus, source, target);
- else
- copyValue(source, target);
-}
-
-void InstructionSelection::convertTypeToDouble(V4IR::Temp *source, V4IR::Temp *target)
-{
- switch (source->type) {
- case V4IR::SInt32Type:
- case V4IR::BoolType:
- case V4IR::NullType:
- convertIntToDouble(source, target);
- break;
- case V4IR::UInt32Type:
- convertUIntToDouble(source, target);
- break;
- case V4IR::UndefinedType:
- _as->loadDouble(_as->loadTempAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, target);
- break;
- case V4IR::StringType:
- case V4IR::VarType: {
- // load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
- tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ScratchRegister);
-
- // check if it's an int32:
- Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
- convertIntToDouble(source, target);
- Assembler::Jump intDone = _as->jump();
-
- // not an int, check if it's NOT a double:
- isNoInt.link(_as);
-#if QT_POINTER_SIZE == 8
- _as->and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
- Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(0));
-#else
- _as->and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
- Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::NotDouble_Mask));
-#endif
-
- generateFunctionCall(target, __qmljs_value_to_double, Assembler::PointerToValue(source));
- Assembler::Jump noDoubleDone = _as->jump();
-
- // it is a double:
- isDbl.link(_as);
- Assembler::Pointer addr2 = _as->loadTempAddress(Assembler::ScratchRegister, source);
- if (target->kind == V4IR::Temp::StackSlot) {
-#if QT_POINTER_SIZE == 8
- _as->load64(addr2, Assembler::ScratchRegister);
- _as->store64(Assembler::ScratchRegister, _as->stackSlotPointer(target));
-#else
- _as->loadDouble(addr2, Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
-#endif
- } else {
- _as->loadDouble(addr2, (Assembler::FPRegisterID) target->index);
- }
-
- noDoubleDone.link(_as);
- intDone.link(_as);
- } break;
- default:
- convertTypeSlowPath(source, target);
- break;
- }
-}
-
-void InstructionSelection::convertTypeToBool(V4IR::Temp *source, V4IR::Temp *target)
-{
- switch (source->type) {
- case V4IR::SInt32Type:
- case V4IR::UInt32Type:
- convertIntToBool(source, target);
- break;
- case V4IR::DoubleType: {
- // The source is in a register if the register allocator is used. If the register
- // allocator was not used, then that means that we can use any register for to
- // load the double into.
- Assembler::FPRegisterID reg;
- if (source->kind == V4IR::Temp::PhysicalRegister)
- reg = (Assembler::FPRegisterID) source->index;
- else
- reg = _as->toDoubleRegister(source, (Assembler::FPRegisterID) 1);
- Assembler::Jump nonZero = _as->branchDoubleNonZero(reg, Assembler::FPGpr0);
-
- // it's 0, so false:
- _as->storeBool(false, target);
- Assembler::Jump done = _as->jump();
-
- // it's non-zero, so true:
- nonZero.link(_as);
- _as->storeBool(true, target);
-
- // done:
- done.link(_as);
- } break;
- case V4IR::UndefinedType:
- case V4IR::NullType:
- _as->storeBool(false, target);
- break;
- case V4IR::StringType:
- case V4IR::VarType:
- default:
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_to_boolean,
- Assembler::PointerToValue(source));
- _as->storeBool(Assembler::ReturnValueRegister, target);
- break;
- }
-}
-
-void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *target)
-{
- switch (source->type) {
- case V4IR::VarType: {
-
-#if QT_POINTER_SIZE == 8
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
- _as->load64(addr, Assembler::ScratchRegister);
- _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
-
- // check if it's a number
- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ScratchRegister);
- Assembler::Jump fallback = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
- // we have a number
- _as->urshift64(Assembler::TrustedImm32(1), Assembler::ScratchRegister);
- Assembler::Jump isInt = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
-
- // it's a double
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
- Assembler::Jump success =
- _as->branchTruncateDoubleToInt32(Assembler::FPGpr0, Assembler::ReturnValueRegister,
- Assembler::BranchIfTruncateSuccessful);
-
- // not an int:
- fallback.link(_as);
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
-
- isInt.link(_as);
- success.link(_as);
- if (target->kind == V4IR::Temp::StackSlot) {
- Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
- _as->store32(Assembler::ReturnValueRegister, targetAddr);
- targetAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
- } else {
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- }
-#else
- // load the tag:
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
- Assembler::Pointer tagAddr = addr;
- tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ReturnValueRegister);
-
- // check if it's an int32:
- Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
- if (target->kind == V4IR::Temp::StackSlot) {
- _as->load32(addr, Assembler::ScratchRegister);
- Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
- _as->store32(Assembler::ScratchRegister, targetAddr);
- targetAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
- } else {
- _as->load32(addr, (Assembler::RegisterID) target->index);
- }
- Assembler::Jump intDone = _as->jump();
-
- // not an int:
- fallback.link(_as);
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
- _as->storeInt32(Assembler::ReturnValueRegister, target);
-
- intDone.link(_as);
-#endif
-
- } break;
- case V4IR::DoubleType: {
- Assembler::Jump success =
- _as->branchTruncateDoubleToInt32(_as->toDoubleRegister(source),
- Assembler::ReturnValueRegister,
- Assembler::BranchIfTruncateSuccessful);
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_int32,
- Assembler::PointerToValue(source));
- success.link(_as);
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- } break;
- case V4IR::UInt32Type:
- _as->storeInt32(_as->toUInt32Register(source, Assembler::ReturnValueRegister), target);
- break;
- case V4IR::NullType:
- case V4IR::UndefinedType:
- _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- break;
- case V4IR::BoolType:
- _as->storeInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
- break;
- case V4IR::StringType:
- default:
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- break;
- } // switch (source->type)
-}
-
-void InstructionSelection::convertTypeToUInt32(V4IR::Temp *source, V4IR::Temp *target)
-{
- switch (source->type) {
- case V4IR::VarType: {
- // load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
- tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ScratchRegister);
-
- // check if it's an int32:
- Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
- _as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
- Assembler::Jump intDone = _as->jump();
-
- // not an int:
- isNoInt.link(_as);
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
- _as->storeInt32(Assembler::ReturnValueRegister, target);
-
- intDone.link(_as);
- } break;
- case V4IR::DoubleType: {
- Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
- Assembler::Jump success =
- _as->branchTruncateDoubleToUint32(reg, Assembler::ReturnValueRegister,
- Assembler::BranchIfTruncateSuccessful);
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_uint32,
- Assembler::PointerToValue(source));
- success.link(_as);
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
- } break;
- case V4IR::NullType:
- case V4IR::UndefinedType:
- _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
- break;
- case V4IR::StringType:
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
- Assembler::PointerToValue(source));
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
- break;
- case V4IR::SInt32Type:
- case V4IR::BoolType:
- _as->storeUInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
- break;
- default:
- break;
- } // switch (source->type)
-}
-
-void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
-{
- assert(func != 0);
- prepareCallData(args, 0);
-
- if (useFastLookups && func->global) {
- uint index = registerGlobalGetterLookup(*func->id);
- generateFunctionCall(result, __qmljs_construct_global_lookup,
- Assembler::ContextRegister,
- Assembler::TrustedImm32(index), baseAddressForCallData());
- return;
- }
-
- generateFunctionCall(result, __qmljs_construct_activation_property,
- Assembler::ContextRegister,
- Assembler::PointerToString(*func->id),
- baseAddressForCallData());
-}
-
-
-void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result)
-{
- prepareCallData(args, base);
- if (useFastLookups) {
- uint index = registerGetterLookup(name);
- generateFunctionCall(result, __qmljs_construct_property_lookup,
- Assembler::ContextRegister,
- Assembler::TrustedImm32(index),
- baseAddressForCallData());
- return;
- }
-
- generateFunctionCall(result, __qmljs_construct_property, Assembler::ContextRegister,
- Assembler::PointerToString(name),
- baseAddressForCallData());
-}
-
-void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
-{
- assert(value != 0);
-
- prepareCallData(args, 0);
- generateFunctionCall(result, __qmljs_construct_value,
- Assembler::ContextRegister,
- Assembler::Reference(value),
- baseAddressForCallData());
-}
-
-void InstructionSelection::visitJump(V4IR::Jump *s)
-{
- if (!_removableJumps.contains(s))
- _as->jumpToBlock(_block, s->target);
-}
-
-void InstructionSelection::visitCJump(V4IR::CJump *s)
-{
- if (V4IR::Temp *t = s->cond->asTemp()) {
- Assembler::RegisterID reg;
- if (t->kind == V4IR::Temp::PhysicalRegister) {
- Q_ASSERT(t->type == V4IR::BoolType);
- reg = (Assembler::RegisterID) t->index;
- } else if (t->kind == V4IR::Temp::StackSlot && t->type == V4IR::BoolType) {
- reg = Assembler::ReturnValueRegister;
- _as->toInt32Register(t, reg);
- } else {
- Address temp = _as->loadTempAddress(Assembler::ScratchRegister, t);
- Address tag = temp;
- tag.offset += qOffsetOf(QV4::Value, tag);
- Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
-
- Address data = temp;
- data.offset += qOffsetOf(QV4::Value, int_32);
- _as->load32(data, Assembler::ReturnValueRegister);
- Assembler::Jump testBoolean = _as->jump();
-
- booleanConversion.link(_as);
- reg = Assembler::ReturnValueRegister;
- generateFunctionCall(reg, __qmljs_to_boolean, Assembler::Reference(t));
-
- testBoolean.link(_as);
- }
-
- _as->generateCJumpOnNonZero(reg, _block, s->iftrue, s->iffalse);
- return;
- } else if (V4IR::Const *c = s->cond->asConst()) {
- // TODO: SSA optimization for constant condition evaluation should remove this.
- // See also visitCJump() in RegAllocInfo.
- generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_to_boolean,
- Assembler::PointerToValue(c));
- _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
- return;
- } else if (V4IR::Binop *b = s->cond->asBinop()) {
- if (b->left->type == V4IR::DoubleType && b->right->type == V4IR::DoubleType
- && visitCJumpDouble(b->op, b->left, b->right, s->iftrue, s->iffalse))
- return;
-
- if (b->op == V4IR::OpStrictEqual || b->op == V4IR::OpStrictNotEqual) {
- visitCJumpStrict(b, s->iftrue, s->iffalse);
- return;
- }
- if (b->op == V4IR::OpEqual || b->op == V4IR::OpNotEqual) {
- visitCJumpEqual(b, s->iftrue, s->iffalse);
- return;
- }
-
- CmpOp op = 0;
- CmpOpContext opContext = 0;
- const char *opName = 0;
- switch (b->op) {
- default: Q_UNREACHABLE(); assert(!"todo"); break;
- case V4IR::OpGt: setOp(op, opName, __qmljs_cmp_gt); break;
- case V4IR::OpLt: setOp(op, opName, __qmljs_cmp_lt); break;
- case V4IR::OpGe: setOp(op, opName, __qmljs_cmp_ge); break;
- case V4IR::OpLe: setOp(op, opName, __qmljs_cmp_le); break;
- case V4IR::OpEqual: setOp(op, opName, __qmljs_cmp_eq); break;
- case V4IR::OpNotEqual: setOp(op, opName, __qmljs_cmp_ne); break;
- case V4IR::OpStrictEqual: setOp(op, opName, __qmljs_cmp_se); break;
- case V4IR::OpStrictNotEqual: setOp(op, opName, __qmljs_cmp_sne); break;
- case V4IR::OpInstanceof: setOpContext(op, opName, __qmljs_cmp_instanceof); break;
- case V4IR::OpIn: setOpContext(op, opName, __qmljs_cmp_in); break;
- } // switch
-
- // TODO: in SSA optimization, do constant expression evaluation.
- // The case here is, for example:
- // if (true === true) .....
- // Of course, after folding the CJUMP to a JUMP, dead-code (dead-basic-block)
- // elimination (which isn't there either) would remove the whole else block.
- if (opContext)
- _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, opContext,
- Assembler::ContextRegister,
- Assembler::PointerToValue(b->left),
- Assembler::PointerToValue(b->right));
- else
- _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, op,
- Assembler::PointerToValue(b->left),
- Assembler::PointerToValue(b->right));
-
- _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
- return;
- }
- Q_UNREACHABLE();
-}
-
-void InstructionSelection::visitRet(V4IR::Ret *s)
-{
- if (!s) {
- // this only happens if the method doesn't have a return statement and can
- // only exit through an exception
- } else if (V4IR::Temp *t = s->expr->asTemp()) {
-#if CPU(X86) || CPU(ARM)
-
-# if CPU(X86)
- Assembler::RegisterID lowReg = JSC::X86Registers::eax;
- Assembler::RegisterID highReg = JSC::X86Registers::edx;
-# else // CPU(ARM)
- Assembler::RegisterID lowReg = JSC::ARMRegisters::r0;
- Assembler::RegisterID highReg = JSC::ARMRegisters::r1;
-# endif
-
- if (t->kind == V4IR::Temp::PhysicalRegister) {
- switch (t->type) {
- case V4IR::DoubleType:
- _as->moveDoubleToInts((Assembler::FPRegisterID) t->index, lowReg, highReg);
- break;
- case V4IR::UInt32Type: {
- Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
- Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
- _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
- _as->moveDoubleToInts(Assembler::FPGpr0, lowReg, highReg);
- Assembler::Jump done = _as->jump();
- intRange.link(_as);
- _as->move(srcReg, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), highReg);
- done.link(_as);
- } break;
- case V4IR::SInt32Type:
- _as->move((Assembler::RegisterID) t->index, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), highReg);
- break;
- case V4IR::BoolType:
- _as->move((Assembler::RegisterID) t->index, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::_Boolean_Type), highReg);
- break;
- default:
- Q_UNREACHABLE();
- }
- } else {
- Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, t);
- _as->load32(addr, lowReg);
- addr.offset += 4;
- _as->load32(addr, highReg);
- }
-#else
- if (t->kind == V4IR::Temp::PhysicalRegister) {
- if (t->type == V4IR::DoubleType) {
- _as->moveDoubleTo64((Assembler::FPRegisterID) t->index,
- Assembler::ReturnValueRegister);
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask),
- Assembler::ScratchRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- } else if (t->type == V4IR::UInt32Type) {
- Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
- Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
- _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
- _as->moveDoubleTo64(Assembler::FPGpr0, Assembler::ReturnValueRegister);
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- Assembler::Jump done = _as->jump();
- intRange.link(_as);
- _as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister);
- quint64 tag = QV4::Value::_Integer_Type;
- _as->or64(Assembler::TrustedImm64(tag << 32),
- Assembler::ReturnValueRegister);
- done.link(_as);
- } else {
- _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, Assembler::ReturnValueRegister);
- quint64 tag;
- switch (t->type) {
- case V4IR::SInt32Type:
- tag = QV4::Value::_Integer_Type;
- break;
- case V4IR::BoolType:
- tag = QV4::Value::_Boolean_Type;
- break;
- default:
- tag = QV4::Value::Undefined_Type;
- Q_UNREACHABLE();
- }
- _as->or64(Assembler::TrustedImm64(tag << 32),
- Assembler::ReturnValueRegister);
- }
- } else {
- _as->copyValue(Assembler::ReturnValueRegister, t);
- }
-#endif
- } else if (V4IR::Const *c = s->expr->asConst()) {
- QV4::Primitive retVal = convertToValue(c);
-#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
-#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
-#else
- _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
-#endif
- } else {
- Q_UNREACHABLE();
- Q_UNUSED(s);
- }
-
- _as->exceptionReturnLabel = _as->label();
-
- const int locals = _as->stackLayout().calculateJSStackFrameSize();
- _as->subPtr(Assembler::TrustedImm32(sizeof(QV4::SafeValue)*locals), Assembler::LocalsRegister);
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, engine)), Assembler::ScratchRegister);
- _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
-
- _as->leaveStandardStackFrame();
- _as->ret();
-}
-
-int InstructionSelection::prepareVariableArguments(V4IR::ExprList* args)
-{
- int argc = 0;
- for (V4IR::ExprList *it = args; it; it = it->next) {
- ++argc;
- }
-
- int i = 0;
- for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
- V4IR::Expr *arg = it->expr;
- Q_ASSERT(arg != 0);
- Pointer dst(_as->stackLayout().argumentAddressForCall(i));
- if (arg->asTemp() && arg->asTemp()->kind != V4IR::Temp::PhysicalRegister)
- _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
- else
- _as->copyValue(dst, arg);
- }
-
- return argc;
-}
-
-int InstructionSelection::prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject)
-{
- int argc = 0;
- for (V4IR::ExprList *it = args; it; it = it->next) {
- ++argc;
- }
-
- Pointer p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, tag));
- _as->store32(Assembler::TrustedImm32(QV4::Value::_Integer_Type), p);
- p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, argc));
- _as->store32(Assembler::TrustedImm32(argc), p);
- p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, thisObject));
- if (!thisObject)
- _as->storeValue(QV4::Primitive::undefinedValue(), p);
- else
- _as->copyValue(p, thisObject);
-
- int i = 0;
- for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
- V4IR::Expr *arg = it->expr;
- Q_ASSERT(arg != 0);
- Pointer dst(_as->stackLayout().argumentAddressForCall(i));
- if (arg->asTemp() && arg->asTemp()->kind != V4IR::Temp::PhysicalRegister)
- _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
- else
- _as->copyValue(dst, arg);
- }
- return argc;
-}
-
-
-QT_BEGIN_NAMESPACE
-namespace QV4 {
-bool operator==(const Primitive &v1, const Primitive &v2)
-{
- return v1.rawValue() == v2.rawValue();
-}
-} // QV4 namespace
-QT_END_NAMESPACE
-
-int Assembler::ConstantTable::add(const Primitive &v)
-{
- int idx = _values.indexOf(v);
- if (idx == -1) {
- idx = _values.size();
- _values.append(v);
- }
- return idx;
-}
-
-Assembler::ImplicitAddress Assembler::ConstantTable::loadValueAddress(V4IR::Const *c,
- RegisterID baseReg)
-{
- return loadValueAddress(convertToValue(c), baseReg);
-}
-
-Assembler::ImplicitAddress Assembler::ConstantTable::loadValueAddress(const Primitive &v,
- RegisterID baseReg)
-{
- _toPatch.append(_as->moveWithPatch(TrustedImmPtr(0), baseReg));
- ImplicitAddress addr(baseReg);
- addr.offset = add(v) * sizeof(QV4::Primitive);
- Q_ASSERT(addr.offset >= 0);
- return addr;
-}
-
-void Assembler::ConstantTable::finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel)
-{
- void *tablePtr = isel->addConstantTable(&_values);
-
- foreach (DataLabelPtr label, _toPatch)
- linkBuffer.patch(label, tablePtr);
-}
-
-// Try to load the source expression into the destination FP register. This assumes that two
-// general purpose (integer) registers are available: the ScratchRegister and the
-// ReturnValueRegister. It returns a Jump if no conversion can be performed.
-Assembler::Jump InstructionSelection::genTryDoubleConversion(V4IR::Expr *src,
- Assembler::FPRegisterID dest)
-{
- switch (src->type) {
- case V4IR::DoubleType:
- _as->moveDouble(_as->toDoubleRegister(src, dest), dest);
- return Assembler::Jump();
- case V4IR::SInt32Type:
- _as->convertInt32ToDouble(_as->toInt32Register(src, Assembler::ScratchRegister),
- dest);
- return Assembler::Jump();
- case V4IR::UInt32Type:
- _as->convertUInt32ToDouble(_as->toUInt32Register(src, Assembler::ScratchRegister),
- dest, Assembler::ReturnValueRegister);
- return Assembler::Jump();
- case V4IR::BoolType:
- // TODO?
- return _as->jump();
- default:
- break;
- }
-
- V4IR::Temp *sourceTemp = src->asTemp();
- Q_ASSERT(sourceTemp);
-
- // It's not a number type, so it cannot be in a register.
- Q_ASSERT(sourceTemp->kind != V4IR::Temp::PhysicalRegister || sourceTemp->type == V4IR::BoolType);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, sourceTemp);
- tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ScratchRegister);
-
- // check if it's an int32:
- Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
- _as->convertInt32ToDouble(_as->toInt32Register(src, Assembler::ScratchRegister), dest);
- Assembler::Jump intDone = _as->jump();
-
- // not an int, check if it's a double:
- isNoInt.link(_as);
-#if QT_POINTER_SIZE == 8
- _as->and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
- Assembler::Jump isNoDbl = _as->branch32(Assembler::Equal, Assembler::ScratchRegister,
- Assembler::TrustedImm32(0));
-#else
- _as->and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
- Assembler::Jump isNoDbl = _as->branch32(Assembler::Equal, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::NotDouble_Mask));
-#endif
- _as->toDoubleRegister(src, dest);
- intDone.link(_as);
-
- return isNoDbl;
-}
-
-void InstructionSelection::doubleBinop(V4IR::AluOp oper, V4IR::Expr *leftSource,
- V4IR::Expr *rightSource, V4IR::Temp *target)
-{
- Q_ASSERT(leftSource->asConst() == 0 || rightSource->asConst() == 0);
- Q_ASSERT(isPregOrConst(leftSource));
- Q_ASSERT(isPregOrConst(rightSource));
- Assembler::FPRegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::FPRegisterID) target->index;
- else
- targetReg = Assembler::FPGpr0;
-
- switch (oper) {
- case V4IR::OpAdd:
- _as->addDouble(_as->toDoubleRegister(leftSource), _as->toDoubleRegister(rightSource),
- targetReg);
- break;
- case V4IR::OpMul:
- _as->mulDouble(_as->toDoubleRegister(leftSource), _as->toDoubleRegister(rightSource),
- targetReg);
- break;
- case V4IR::OpSub:
-#if CPU(X86) || CPU(X86_64)
- if (V4IR::Temp *rightTemp = rightSource->asTemp()) {
- if (rightTemp->kind == V4IR::Temp::PhysicalRegister && rightTemp->index == targetReg) {
- _as->moveDouble(targetReg, Assembler::FPGpr0);
- _as->moveDouble(_as->toDoubleRegister(leftSource, targetReg), targetReg);
- _as->subDouble(Assembler::FPGpr0, targetReg);
- break;
- }
- } else if (rightSource->asConst() && targetReg == Assembler::FPGpr0) {
- Q_ASSERT(leftSource->asTemp());
- Q_ASSERT(leftSource->asTemp()->kind == V4IR::Temp::PhysicalRegister);
- _as->moveDouble(_as->toDoubleRegister(leftSource, targetReg), targetReg);
- Assembler::FPRegisterID reg = (Assembler::FPRegisterID) leftSource->asTemp()->index;
- _as->moveDouble(_as->toDoubleRegister(rightSource, reg), reg);
- _as->subDouble(reg, targetReg);
- break;
- }
-#endif
-
- _as->subDouble(_as->toDoubleRegister(leftSource), _as->toDoubleRegister(rightSource),
- targetReg);
- break;
- case V4IR::OpDiv:
-#if CPU(X86) || CPU(X86_64)
- if (V4IR::Temp *rightTemp = rightSource->asTemp()) {
- if (rightTemp->kind == V4IR::Temp::PhysicalRegister && rightTemp->index == targetReg) {
- _as->moveDouble(targetReg, Assembler::FPGpr0);
- _as->moveDouble(_as->toDoubleRegister(leftSource, targetReg), targetReg);
- _as->divDouble(Assembler::FPGpr0, targetReg);
- break;
- }
- } else if (rightSource->asConst() && targetReg == Assembler::FPGpr0) {
- Q_ASSERT(leftSource->asTemp());
- Q_ASSERT(leftSource->asTemp()->kind == V4IR::Temp::PhysicalRegister);
- _as->moveDouble(_as->toDoubleRegister(leftSource, targetReg), targetReg);
- Assembler::FPRegisterID reg = (Assembler::FPRegisterID) leftSource->asTemp()->index;
- _as->moveDouble(_as->toDoubleRegister(rightSource, reg), reg);
- _as->divDouble(reg, targetReg);
- break;
- }
-#endif
- _as->divDouble(_as->toDoubleRegister(leftSource), _as->toDoubleRegister(rightSource),
- targetReg);
- break;
- default: {
- Q_ASSERT(target->type == V4IR::BoolType);
- Assembler::Jump trueCase = branchDouble(false, oper, leftSource, rightSource);
- _as->storeBool(false, target);
- Assembler::Jump done = _as->jump();
- trueCase.link(_as);
- _as->storeBool(true, target);
- done.link(_as);
- } return;
- }
-
- if (target->kind != V4IR::Temp::PhysicalRegister)
- _as->storeDouble(Assembler::FPGpr0, target);
-}
-
-Assembler::Jump InstructionSelection::branchDouble(bool invertCondition, V4IR::AluOp op,
- V4IR::Expr *left, V4IR::Expr *right)
-{
- Q_ASSERT(isPregOrConst(left));
- Q_ASSERT(isPregOrConst(right));
- Q_ASSERT(left->asConst() == 0 || right->asConst() == 0);
-
- Assembler::DoubleCondition cond;
- switch (op) {
- case V4IR::OpGt: cond = Assembler::DoubleGreaterThan; break;
- case V4IR::OpLt: cond = Assembler::DoubleLessThan; break;
- case V4IR::OpGe: cond = Assembler::DoubleGreaterThanOrEqual; break;
- case V4IR::OpLe: cond = Assembler::DoubleLessThanOrEqual; break;
- case V4IR::OpEqual:
- case V4IR::OpStrictEqual: cond = Assembler::DoubleEqual; break;
- case V4IR::OpNotEqual:
- case V4IR::OpStrictNotEqual: cond = Assembler::DoubleNotEqualOrUnordered; break; // No, the inversion of DoubleEqual is NOT DoubleNotEqual.
- default:
- Q_UNREACHABLE();
- }
- if (invertCondition)
- cond = JSC::MacroAssembler::invert(cond);
-
- return _as->branchDouble(cond, _as->toDoubleRegister(left), _as->toDoubleRegister(right));
-}
-
-bool InstructionSelection::visitCJumpDouble(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right,
- V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse)
-{
- if (!isPregOrConst(left) || !isPregOrConst(right))
- return false;
-
- if (_as->nextBlock() == iftrue) {
- Assembler::Jump target = branchDouble(true, op, left, right);
- _as->addPatch(iffalse, target);
- } else {
- Assembler::Jump target = branchDouble(false, op, left, right);
- _as->addPatch(iftrue, target);
- _as->jumpToBlock(_block, iffalse);
- }
- return true;
-}
-
-void InstructionSelection::visitCJumpStrict(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- Q_ASSERT(binop->op == V4IR::OpStrictEqual || binop->op == V4IR::OpStrictNotEqual);
-
- if (visitCJumpStrictNullUndefined(V4IR::NullType, binop, trueBlock, falseBlock))
- return;
- if (visitCJumpStrictNullUndefined(V4IR::UndefinedType, binop, trueBlock, falseBlock))
- return;
- if (visitCJumpStrictBool(binop, trueBlock, falseBlock))
- return;
-
- V4IR::Expr *left = binop->left;
- V4IR::Expr *right = binop->right;
-
- _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "__qmljs_cmp_se", __qmljs_cmp_se,
- Assembler::PointerToValue(left), Assembler::PointerToValue(right));
- _as->generateCJumpOnCompare(binop->op == V4IR::OpStrictEqual ? Assembler::NotEqual : Assembler::Equal,
- Assembler::ReturnValueRegister, Assembler::TrustedImm32(0),
- _block, trueBlock, falseBlock);
-}
-
-// Only load the non-null temp.
-bool InstructionSelection::visitCJumpStrictNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop,
- V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- Q_ASSERT(nullOrUndef == V4IR::NullType || nullOrUndef == V4IR::UndefinedType);
-
- V4IR::Expr *varSrc = 0;
- if (binop->left->type == V4IR::VarType && binop->right->type == nullOrUndef)
- varSrc = binop->left;
- else if (binop->left->type == nullOrUndef && binop->right->type == V4IR::VarType)
- varSrc = binop->right;
- if (!varSrc)
- return false;
-
- if (varSrc->asTemp() && varSrc->asTemp()->kind == V4IR::Temp::PhysicalRegister) {
- _as->jumpToBlock(_block, falseBlock);
- return true;
- }
-
- if (V4IR::Const *c = varSrc->asConst()) {
- if (c->type == nullOrUndef)
- _as->jumpToBlock(_block, trueBlock);
- else
- _as->jumpToBlock(_block, falseBlock);
- return true;
- }
-
- V4IR::Temp *t = varSrc->asTemp();
- Q_ASSERT(t);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
- tagAddr.offset += 4;
- const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
- _as->load32(tagAddr, tagReg);
-
- Assembler::RelationalCondition cond = binop->op == V4IR::OpStrictEqual ? Assembler::Equal
- : Assembler::NotEqual;
- const Assembler::TrustedImm32 tag(nullOrUndef == V4IR::NullType ? int(QV4::Value::_Null_Type)
- : int(QV4::Value::Undefined_Type));
- _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
- return true;
-}
-
-bool InstructionSelection::visitCJumpStrictBool(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- V4IR::Expr *boolSrc = 0, *otherSrc = 0;
- if (binop->left->type == V4IR::BoolType) {
- boolSrc = binop->left;
- otherSrc = binop->right;
- } else if (binop->right->type == V4IR::BoolType) {
- boolSrc = binop->right;
- otherSrc = binop->left;
- } else {
- // neither operands are statically typed as bool, so bail out.
- return false;
- }
-
- Assembler::RelationalCondition cond = binop->op == V4IR::OpStrictEqual ? Assembler::Equal
- : Assembler::NotEqual;
-
- if (otherSrc->type == V4IR::BoolType) { // both are boolean
- Assembler::RegisterID one = _as->toBoolRegister(boolSrc, Assembler::ReturnValueRegister);
- Assembler::RegisterID two = _as->toBoolRegister(otherSrc, Assembler::ScratchRegister);
- _as->generateCJumpOnCompare(cond, one, two, _block, trueBlock, falseBlock);
- return true;
- }
-
- if (otherSrc->type != V4IR::VarType) {
- _as->jumpToBlock(_block, falseBlock);
- return true;
- }
-
- V4IR::Temp *otherTemp = otherSrc->asTemp();
- Q_ASSERT(otherTemp); // constants cannot have "var" type
- Q_ASSERT(otherTemp->kind != V4IR::Temp::PhysicalRegister);
-
- Assembler::Pointer otherAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, otherTemp);
- otherAddr.offset += 4; // tag address
-
- // check if the tag of the var operand is indicates 'boolean'
- _as->load32(otherAddr, Assembler::ScratchRegister);
- Assembler::Jump noBool = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(QV4::Value::_Boolean_Type));
- if (binop->op == V4IR::OpStrictEqual)
- _as->addPatch(falseBlock, noBool);
- else
- _as->addPatch(trueBlock, noBool);
-
- // ok, both are boolean, so let's load them and compare them.
- otherAddr.offset -= 4; // int_32 address
- _as->load32(otherAddr, Assembler::ReturnValueRegister);
- Assembler::RegisterID boolReg = _as->toBoolRegister(boolSrc, Assembler::ScratchRegister);
- _as->generateCJumpOnCompare(cond, boolReg, Assembler::ReturnValueRegister, _block, trueBlock,
- falseBlock);
- return true;
-}
-
-bool InstructionSelection::visitCJumpNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop,
- V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- Q_ASSERT(nullOrUndef == V4IR::NullType || nullOrUndef == V4IR::UndefinedType);
-
- V4IR::Expr *varSrc = 0;
- if (binop->left->type == V4IR::VarType && binop->right->type == nullOrUndef)
- varSrc = binop->left;
- else if (binop->left->type == nullOrUndef && binop->right->type == V4IR::VarType)
- varSrc = binop->right;
- if (!varSrc)
- return false;
-
- if (varSrc->asTemp() && varSrc->asTemp()->kind == V4IR::Temp::PhysicalRegister) {
- _as->jumpToBlock(_block, falseBlock);
- return true;
- }
-
- if (V4IR::Const *c = varSrc->asConst()) {
- if (c->type == nullOrUndef)
- _as->jumpToBlock(_block, trueBlock);
- else
- _as->jumpToBlock(_block, falseBlock);
- return true;
- }
-
- V4IR::Temp *t = varSrc->asTemp();
- Q_ASSERT(t);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
- tagAddr.offset += 4;
- const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
- _as->load32(tagAddr, tagReg);
-
- if (binop->op == V4IR::OpNotEqual)
- qSwap(trueBlock, falseBlock);
- Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::_Null_Type)));
- Assembler::Jump isUndefined = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Undefined_Type)));
- _as->addPatch(trueBlock, isNull);
- _as->addPatch(trueBlock, isUndefined);
- _as->jumpToBlock(_block, falseBlock);
-
- return true;
-}
-
-
-void InstructionSelection::visitCJumpEqual(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock)
-{
- Q_ASSERT(binop->op == V4IR::OpEqual || binop->op == V4IR::OpNotEqual);
-
- if (visitCJumpNullUndefined(V4IR::NullType, binop, trueBlock, falseBlock))
- return;
-
- V4IR::Expr *left = binop->left;
- V4IR::Expr *right = binop->right;
-
- _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "__qmljs_cmp_eq", __qmljs_cmp_eq,
- Assembler::PointerToValue(left), Assembler::PointerToValue(right));
- _as->generateCJumpOnCompare(binop->op == V4IR::OpEqual ? Assembler::NotEqual : Assembler::Equal,
- Assembler::ReturnValueRegister, Assembler::TrustedImm32(0),
- _block, trueBlock, falseBlock);
-}
-
-
-bool InstructionSelection::int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource,
- V4IR::Expr *rightSource, V4IR::Temp *target)
-{
- Q_ASSERT(leftSource->type == V4IR::SInt32Type);
-
- switch (oper) {
- case V4IR::OpBitAnd: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- if (rightSource->asTemp() && rightSource->asTemp()->kind == V4IR::Temp::PhysicalRegister
- && target->kind == V4IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
- _as->and32(_as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
- return true;
- }
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->and32(_as->toInt32Register(leftSource, targetReg),
- _as->toInt32Register(rightSource, Assembler::ScratchRegister),
- targetReg);
- _as->storeInt32(targetReg, target);
- } return true;
- case V4IR::OpBitOr: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- if (rightSource->asTemp() && rightSource->asTemp()->kind == V4IR::Temp::PhysicalRegister
- && target->kind == V4IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
- _as->or32(_as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
- return true;
- }
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->or32(_as->toInt32Register(leftSource, targetReg),
- _as->toInt32Register(rightSource, Assembler::ScratchRegister),
- targetReg);
- _as->storeInt32(targetReg, target);
- } return true;
- case V4IR::OpBitXor: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- if (rightSource->asTemp() && rightSource->asTemp()->kind == V4IR::Temp::PhysicalRegister
- && target->kind == V4IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
- _as->xor32(_as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
- return true;
- }
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->xor32(_as->toInt32Register(leftSource, targetReg),
- _as->toInt32Register(rightSource, Assembler::ScratchRegister),
- targetReg);
- _as->storeInt32(targetReg, target);
- } return true;
- case V4IR::OpLShift: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->move(_as->toInt32Register(rightSource, Assembler::ScratchRegister),
- Assembler::ScratchRegister);
- _as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); // TODO: for constants, do this in the IR
- _as->lshift32(_as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister,
- Assembler::ReturnValueRegister);
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- } return true;
- case V4IR::OpRShift: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->move(_as->toInt32Register(rightSource, Assembler::ScratchRegister),
- Assembler::ScratchRegister);
- _as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); // TODO: for constants, do this in the IR
- _as->rshift32(_as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister,
- Assembler::ReturnValueRegister);
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- } return true;
- case V4IR::OpURShift:
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- _as->move(_as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
- Assembler::ReturnValueRegister);
- _as->move(_as->toInt32Register(rightSource, Assembler::ScratchRegister),
- Assembler::ScratchRegister);
- _as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); // TODO: for constants, do this in the IR
- _as->urshift32(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
- return true;
- case V4IR::OpAdd: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
-
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->add32(_as->toInt32Register(leftSource, targetReg),
- _as->toInt32Register(rightSource, Assembler::ScratchRegister),
- targetReg);
- _as->storeInt32(targetReg, target);
- } return true;
- case V4IR::OpSub: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
-
- if (rightSource->asTemp() && rightSource->asTemp()->kind == V4IR::Temp::PhysicalRegister
- && target->kind == V4IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
- Assembler::RegisterID targetReg = (Assembler::RegisterID) target->index;
- _as->move(targetReg, Assembler::ScratchRegister);
- _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
- _as->sub32(Assembler::ScratchRegister, targetReg);
- _as->storeInt32(targetReg, target);
- return true;
- }
-
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
- _as->sub32(_as->toInt32Register(rightSource, Assembler::ScratchRegister), targetReg);
- _as->storeInt32(targetReg, target);
- } return true;
- case V4IR::OpMul: {
- Q_ASSERT(rightSource->type == V4IR::SInt32Type);
-
- Assembler::RegisterID targetReg;
- if (target->kind == V4IR::Temp::PhysicalRegister)
- targetReg = (Assembler::RegisterID) target->index;
- else
- targetReg = Assembler::ReturnValueRegister;
-
- _as->mul32(_as->toInt32Register(leftSource, targetReg),
- _as->toInt32Register(rightSource, Assembler::ScratchRegister),
- targetReg);
- _as->storeInt32(targetReg, target);
- } return true;
- default:
- return false;
- }
-}
-
-#endif // ENABLE(ASSEMBLER)
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index bf9af178fe..ba4f2331a1 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -47,74 +47,75 @@
#include <private/qv4function_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4compileddata_p.h>
+#include <private/qqmlengine_p.h>
#undef USE_TYPE_INFO
-using namespace QQmlJS;
-using namespace QQmlJS::Moth;
+using namespace QV4;
+using namespace QV4::Moth;
namespace {
-inline QV4::BinOp aluOpFunction(V4IR::AluOp op)
+inline QV4::BinOp aluOpFunction(IR::AluOp op)
{
switch (op) {
- case V4IR::OpInvalid:
+ case IR::OpInvalid:
return 0;
- case V4IR::OpIfTrue:
+ case IR::OpIfTrue:
return 0;
- case V4IR::OpNot:
+ case IR::OpNot:
return 0;
- case V4IR::OpUMinus:
+ case IR::OpUMinus:
return 0;
- case V4IR::OpUPlus:
+ case IR::OpUPlus:
return 0;
- case V4IR::OpCompl:
+ case IR::OpCompl:
return 0;
- case V4IR::OpBitAnd:
+ case IR::OpBitAnd:
return QV4::__qmljs_bit_and;
- case V4IR::OpBitOr:
+ case IR::OpBitOr:
return QV4::__qmljs_bit_or;
- case V4IR::OpBitXor:
+ case IR::OpBitXor:
return QV4::__qmljs_bit_xor;
- case V4IR::OpAdd:
+ case IR::OpAdd:
return 0;
- case V4IR::OpSub:
+ case IR::OpSub:
return QV4::__qmljs_sub;
- case V4IR::OpMul:
+ case IR::OpMul:
return QV4::__qmljs_mul;
- case V4IR::OpDiv:
+ case IR::OpDiv:
return QV4::__qmljs_div;
- case V4IR::OpMod:
+ case IR::OpMod:
return QV4::__qmljs_mod;
- case V4IR::OpLShift:
+ case IR::OpLShift:
return QV4::__qmljs_shl;
- case V4IR::OpRShift:
+ case IR::OpRShift:
return QV4::__qmljs_shr;
- case V4IR::OpURShift:
+ case IR::OpURShift:
return QV4::__qmljs_ushr;
- case V4IR::OpGt:
+ case IR::OpGt:
return QV4::__qmljs_gt;
- case V4IR::OpLt:
+ case IR::OpLt:
return QV4::__qmljs_lt;
- case V4IR::OpGe:
+ case IR::OpGe:
return QV4::__qmljs_ge;
- case V4IR::OpLe:
+ case IR::OpLe:
return QV4::__qmljs_le;
- case V4IR::OpEqual:
+ case IR::OpEqual:
return QV4::__qmljs_eq;
- case V4IR::OpNotEqual:
+ case IR::OpNotEqual:
return QV4::__qmljs_ne;
- case V4IR::OpStrictEqual:
+ case IR::OpStrictEqual:
return QV4::__qmljs_se;
- case V4IR::OpStrictNotEqual:
+ case IR::OpStrictNotEqual:
return QV4::__qmljs_sne;
- case V4IR::OpInstanceof:
+ case IR::OpInstanceof:
return 0;
- case V4IR::OpIn:
+ case IR::OpIn:
return 0;
- case V4IR::OpAnd:
+ case IR::OpAnd:
return 0;
- case V4IR::OpOr:
+ case IR::OpOr:
return 0;
default:
assert(!"Unknown AluOp");
@@ -122,37 +123,198 @@ inline QV4::BinOp aluOpFunction(V4IR::AluOp op)
}
};
-inline bool isNumberType(V4IR::Expr *e)
+inline bool isNumberType(IR::Expr *e)
{
switch (e->type) {
- case V4IR::SInt32Type:
- case V4IR::UInt32Type:
- case V4IR::DoubleType:
+ case IR::SInt32Type:
+ case IR::UInt32Type:
+ case IR::DoubleType:
return true;
default:
return false;
}
}
-inline bool isIntegerType(V4IR::Expr *e)
+inline bool isIntegerType(IR::Expr *e)
{
switch (e->type) {
- case V4IR::SInt32Type:
- case V4IR::UInt32Type:
+ case IR::SInt32Type:
+ case IR::UInt32Type:
return true;
default:
return false;
}
}
-inline bool isBoolType(V4IR::Expr *e)
-{
- return (e->type == V4IR::BoolType);
-}
+inline bool isBoolType(IR::Expr *e)
+{
+ return (e->type == IR::BoolType);
+}
+
+/*
+ * stack slot allocation:
+ *
+ * foreach bb do
+ * foreach stmt do
+ * if the current statement is not a phi-node:
+ * purge ranges that end before the current statement
+ * check for life ranges to activate, and if they don't have a stackslot associated then allocate one
+ * renumber temps to stack
+ * for phi nodes: check if all temps (src+dst) are assigned stack slots and marked as allocated
+ * if it's a jump:
+ * foreach phi node in the successor:
+ * allocate slots for each temp (both sources and targets) if they don't have one allocated already
+ * insert moves before the jump
+ */
+class AllocateStackSlots: protected ConvertTemps
+{
+ const QVector<IR::LifeTimeInterval> _intervals;
+ QVector<const IR::LifeTimeInterval *> _unhandled;
+ QVector<const IR::LifeTimeInterval *> _live;
+ QBitArray _slotIsInUse;
+ IR::Function *_function;
+
+public:
+ AllocateStackSlots(const QVector<IR::LifeTimeInterval> &intervals)
+ : _intervals(intervals)
+ , _slotIsInUse(intervals.size(), false)
+ , _function(0)
+ {
+ _live.reserve(8);
+ _unhandled.reserve(_intervals.size());
+ for (int i = _intervals.size() - 1; i >= 0; --i)
+ _unhandled.append(&_intervals.at(i));
+ }
+
+ void forFunction(IR::Function *function)
+ {
+ IR::Optimizer::showMeTheCode(function);
+ _function = function;
+ toStackSlots(function);
+
+// QTextStream os(stdout, QIODevice::WriteOnly);
+// os << "Frame layout:" << endl;
+// foreach (int t, _stackSlotForTemp.keys()) {
+// os << "\t" << t << " -> " << _stackSlotForTemp[t] << endl;
+// }
+ }
+
+protected:
+ virtual int allocateFreeSlot()
+ {
+ for (int i = 0, ei = _slotIsInUse.size(); i != ei; ++i) {
+ if (!_slotIsInUse[i]) {
+ if (_nextUnusedStackSlot <= i) {
+ Q_ASSERT(_nextUnusedStackSlot == i);
+ _nextUnusedStackSlot = i + 1;
+ }
+ _slotIsInUse[i] = true;
+ return i;
+ }
+ }
+
+ Q_UNREACHABLE();
+ return -1;
+ }
+
+ virtual void process(IR::Stmt *s)
+ {
+ Q_ASSERT(s->id > 0);
+
+// qDebug("L%d statement %d:", _currentBasicBlock->index, s->id);
+
+ if (IR::Phi *phi = s->asPhi()) {
+ visitPhi(phi);
+ } else {
+ // purge ranges no longer alive:
+ for (int i = 0; i < _live.size(); ) {
+ const IR::LifeTimeInterval *lti = _live.at(i);
+ if (lti->end() < s->id) {
+// qDebug() << "\t - moving temp" << lti->temp().index << "to handled, freeing slot" << _stackSlotForTemp[lti->temp().index];
+ _live.remove(i);
+ Q_ASSERT(_slotIsInUse[_stackSlotForTemp[lti->temp().index]]);
+ _slotIsInUse[_stackSlotForTemp[lti->temp().index]] = false;
+ continue;
+ } else {
+ ++i;
+ }
+ }
+
+ // active new ranges:
+ while (!_unhandled.isEmpty()) {
+ const IR::LifeTimeInterval *lti = _unhandled.last();
+ if (lti->start() > s->id)
+ break; // we're done
+ Q_ASSERT(!_stackSlotForTemp.contains(lti->temp().index));
+ _stackSlotForTemp[lti->temp().index] = allocateFreeSlot();
+// qDebug() << "\t - activating temp" << lti->temp().index << "on slot" << _stackSlotForTemp[lti->temp().index];
+ _live.append(lti);
+ _unhandled.removeLast();
+ }
+
+ s->accept(this);
+ }
+
+ if (IR::Jump *jump = s->asJump()) {
+ IR::MoveMapping moves;
+ foreach (IR::Stmt *succStmt, jump->target->statements) {
+ if (IR::Phi *phi = succStmt->asPhi()) {
+ forceActivation(*phi->targetTemp);
+ for (int i = 0, ei = phi->d->incoming.size(); i != ei; ++i) {
+ IR::Expr *e = phi->d->incoming[i];
+ if (IR::Temp *t = e->asTemp()) {
+ forceActivation(*t);
+ }
+ if (jump->target->in[i] == _currentBasicBlock)
+ moves.add(phi->d->incoming[i], phi->targetTemp);
+ }
+ } else {
+ break;
+ }
+ }
+ moves.order();
+ QList<IR::Move *> newMoves = moves.insertMoves(_currentBasicBlock, _function, true);
+ foreach (IR::Move *move, newMoves)
+ move->accept(this);
+ }
+ }
+
+ void forceActivation(const IR::Temp &t)
+ {
+ if (_stackSlotForTemp.contains(t.index))
+ return;
+
+ int i = _unhandled.size() - 1;
+ for (; i >= 0; --i) {
+ const IR::LifeTimeInterval *lti = _unhandled[i];
+ if (lti->temp() == t) {
+ _live.append(lti);
+ _unhandled.remove(i);
+ break;
+ }
+ }
+ Q_ASSERT(i >= 0); // check that we always found the entry
+
+ _stackSlotForTemp[t.index] = allocateFreeSlot();
+// qDebug() << "\t - force activating temp" << t.index << "on slot" << _stackSlotForTemp[t.index];
+ }
+ virtual void visitPhi(IR::Phi *phi)
+ {
+ Q_UNUSED(phi);
+#if !defined(QT_NO_DEBUG)
+ Q_ASSERT(_stackSlotForTemp.contains(phi->targetTemp->index));
+ Q_ASSERT(_slotIsInUse[_stackSlotForTemp[phi->targetTemp->index]]);
+ foreach (IR::Expr *e, phi->d->incoming) {
+ if (IR::Temp *t = e->asTemp())
+ Q_ASSERT(_stackSlotForTemp.contains(t->index));
+ }
+#endif // defined(QT_NO_DEBUG)
+ }
+};
} // anonymous namespace
-InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
+InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
: EvalInstructionSelection(execAllocator, module, jsGenerator)
, qmlEngine(qmlEngine)
, _block(0)
@@ -170,11 +332,11 @@ InstructionSelection::~InstructionSelection()
void InstructionSelection::run(int functionIndex)
{
- V4IR::Function *function = irModule->functions[functionIndex];
- V4IR::BasicBlock *block = 0, *nextBlock = 0;
+ IR::Function *function = irModule->functions[functionIndex];
+ IR::BasicBlock *block = 0, *nextBlock = 0;
- QHash<V4IR::BasicBlock *, QVector<ptrdiff_t> > patches;
- QHash<V4IR::BasicBlock *, ptrdiff_t> addrs;
+ QHash<IR::BasicBlock *, QVector<ptrdiff_t> > patches;
+ QHash<IR::BasicBlock *, ptrdiff_t> addrs;
int codeSize = 4096;
uchar *codeStart = new uchar[codeSize];
@@ -191,24 +353,33 @@ void InstructionSelection::run(int functionIndex)
qSwap(codeNext, _codeNext);
qSwap(codeEnd, _codeEnd);
- V4IR::Optimizer opt(_function);
+ IR::Optimizer opt(_function);
opt.run(qmlEngine);
if (opt.isInSSA()) {
- opt.convertOutOfSSA();
+ static const bool doStackSlotAllocation =
+ qgetenv("QV4_NO_INTERPRETER_STACK_SLOT_ALLOCATION").isEmpty();
+
+ if (doStackSlotAllocation) {
+ AllocateStackSlots(opt.lifeRanges()).forFunction(_function);
+ } else {
+ opt.convertOutOfSSA();
+ ConvertTemps().toStackSlots(_function);
+ }
opt.showMeTheCode(_function);
+ } else {
+ ConvertTemps().toStackSlots(_function);
}
- ConvertTemps().toStackSlots(_function);
- QSet<V4IR::Jump *> removableJumps = opt.calculateOptionalJumps();
+ QSet<IR::Jump *> removableJumps = opt.calculateOptionalJumps();
qSwap(_removableJumps, removableJumps);
- V4IR::Stmt *cs = 0;
+ IR::Stmt *cs = 0;
qSwap(_currentStatement, cs);
int locals = frameSize();
assert(locals >= 0);
- V4IR::BasicBlock *exceptionHandler = 0;
+ IR::BasicBlock *exceptionHandler = 0;
Instruction::Push push;
push.value = quint32(locals);
@@ -217,7 +388,13 @@ void InstructionSelection::run(int functionIndex)
QVector<uint> lineNumberMappings;
lineNumberMappings.reserve(_function->basicBlocks.size() * 2);
+ uint currentLine = -1;
for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
+ if (irModule->debugMode) {
+ Instruction::Debug debug;
+ debug.breakPoint = 0;
+ addInstruction(debug);
+ }
_block = _function->basicBlocks[i];
_nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
_addrs.insert(_block, _codeNext - _codeStart);
@@ -234,11 +411,18 @@ void InstructionSelection::run(int functionIndex)
exceptionHandler = _block->catchBlock;
}
- foreach (V4IR::Stmt *s, _block->statements) {
+ foreach (IR::Stmt *s, _block->statements) {
_currentStatement = s;
- if (s->location.isValid())
+ if (s->location.isValid()) {
lineNumberMappings << _codeNext - _codeStart << s->location.startLine;
+ if (irModule->debugMode && s->location.startLine != currentLine) {
+ Instruction::Debug debug;
+ debug.breakPoint = 0;
+ addInstruction(debug);
+ currentLine = s->location.startLine;
+ }
+ }
s->accept(this);
}
@@ -269,12 +453,12 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
{
compilationUnit->codeRefs.resize(irModule->functions.size());
int i = 0;
- foreach (V4IR::Function *irFunction, irModule->functions)
+ foreach (IR::Function *irFunction, irModule->functions)
compilationUnit->codeRefs[i++] = codeRefs[irFunction];
return compilationUnit;
}
-void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
+void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
{
Instruction::CallValue call;
prepareCallArgs(args, call.argc);
@@ -284,8 +468,8 @@ void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4
addInstruction(call);
}
-void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args,
- V4IR::Temp *result)
+void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
+ IR::Temp *result)
{
if (useFastLookups) {
Instruction::CallPropertyLookup call;
@@ -307,8 +491,8 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
}
}
-void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args,
- V4IR::Temp *result)
+void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
+ IR::Temp *result)
{
// call the property on the loaded base
Instruction::CallElement call;
@@ -320,18 +504,18 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
addInstruction(call);
}
-void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
+void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
{
// FIXME: do something more useful with this info
- if (target->type & V4IR::NumberType)
- unop(V4IR::OpUPlus, source, target);
+ if (target->type & IR::NumberType && !(source->type & IR::NumberType))
+ unop(IR::OpUPlus, source, target);
else
copyValue(source, target);
}
-void InstructionSelection::constructActivationProperty(V4IR::Name *func,
- V4IR::ExprList *args,
- V4IR::Temp *result)
+void InstructionSelection::constructActivationProperty(IR::Name *func,
+ IR::ExprList *args,
+ IR::Temp *result)
{
if (useFastLookups && func->global) {
Instruction::ConstructGlobalLookup call;
@@ -350,7 +534,7 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
addInstruction(create);
}
-void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result)
+void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
{
if (useFastLookups) {
Instruction::ConstructPropertyLookup call;
@@ -371,7 +555,7 @@ void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &na
addInstruction(create);
}
-void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
+void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
{
Instruction::CreateValue create;
create.func = getParam(value);
@@ -381,42 +565,42 @@ void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *arg
addInstruction(create);
}
-void InstructionSelection::loadThisObject(V4IR::Temp *temp)
+void InstructionSelection::loadThisObject(IR::Temp *temp)
{
Instruction::LoadThis load;
load.result = getResultParam(temp);
addInstruction(load);
}
-void InstructionSelection::loadQmlIdArray(V4IR::Temp *temp)
+void InstructionSelection::loadQmlIdArray(IR::Temp *temp)
{
Instruction::LoadQmlIdArray load;
load.result = getResultParam(temp);
addInstruction(load);
}
-void InstructionSelection::loadQmlImportedScripts(V4IR::Temp *temp)
+void InstructionSelection::loadQmlImportedScripts(IR::Temp *temp)
{
Instruction::LoadQmlImportedScripts load;
load.result = getResultParam(temp);
addInstruction(load);
}
-void InstructionSelection::loadQmlContextObject(V4IR::Temp *temp)
+void InstructionSelection::loadQmlContextObject(IR::Temp *temp)
{
Instruction::LoadQmlContextObject load;
load.result = getResultParam(temp);
addInstruction(load);
}
-void InstructionSelection::loadQmlScopeObject(V4IR::Temp *temp)
+void InstructionSelection::loadQmlScopeObject(IR::Temp *temp)
{
Instruction::LoadQmlScopeObject load;
load.result = getResultParam(temp);
addInstruction(load);
}
-void InstructionSelection::loadQmlSingleton(const QString &name, V4IR::Temp *temp)
+void InstructionSelection::loadQmlSingleton(const QString &name, IR::Temp *temp)
{
Instruction::LoadQmlSingleton load;
load.result = getResultParam(temp);
@@ -424,17 +608,17 @@ void InstructionSelection::loadQmlSingleton(const QString &name, V4IR::Temp *tem
addInstruction(load);
}
-void InstructionSelection::loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp)
+void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
{
assert(sourceConst);
- Instruction::Move move;
- move.source = getParam(sourceConst);
+ Instruction::MoveConst move;
+ move.source = convertToValue(sourceConst).asReturnedValue();
move.result = getResultParam(targetTemp);
addInstruction(move);
}
-void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp)
+void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
{
Instruction::LoadRuntimeString load;
load.stringId = registerString(str);
@@ -442,7 +626,7 @@ void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp
addInstruction(load);
}
-void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
+void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
{
Instruction::LoadRegExp load;
load.regExpId = registerRegExp(sourceRegexp);
@@ -450,7 +634,7 @@ void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *ta
addInstruction(load);
}
-void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Temp *temp)
{
if (useFastLookups && name->global) {
Instruction::GetGlobalLookup load;
@@ -465,7 +649,7 @@ void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::T
addInstruction(load);
}
-void InstructionSelection::setActivationProperty(V4IR::Expr *source, const QString &targetName)
+void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
{
Instruction::StoreName store;
store.source = getParam(source);
@@ -473,7 +657,7 @@ void InstructionSelection::setActivationProperty(V4IR::Expr *source, const QStri
addInstruction(store);
}
-void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *target)
+void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
{
int id = closure->value;
Instruction::LoadClosure load;
@@ -482,7 +666,7 @@ void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *targe
addInstruction(load);
}
-void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target)
+void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Temp *target)
{
if (useFastLookups) {
Instruction::GetLookup load;
@@ -499,7 +683,7 @@ void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4
addInstruction(load);
}
-void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBase,
+void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
const QString &targetName)
{
if (useFastLookups) {
@@ -517,7 +701,7 @@ void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBas
addInstruction(store);
}
-void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex)
+void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
Instruction::StoreQObjectProperty store;
store.base = getParam(targetBase);
@@ -526,7 +710,7 @@ void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *ta
addInstruction(store);
}
-void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target)
+void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target)
{
if (attachedPropertiesId != 0) {
Instruction::LoadAttachedQObjectProperty load;
@@ -544,8 +728,17 @@ void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyInde
}
}
-void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
+void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
{
+ if (useFastLookups) {
+ Instruction::LoadElementLookup load;
+ load.lookup = registerIndexedGetterLookup();
+ load.base = getParam(base);
+ load.index = getParam(index);
+ load.result = getResultParam(target);
+ addInstruction(load);
+ return;
+ }
Instruction::LoadElement load;
load.base = getParam(base);
load.index = getParam(index);
@@ -553,9 +746,18 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR:
addInstruction(load);
}
-void InstructionSelection::setElement(V4IR::Expr *source, V4IR::Expr *targetBase,
- V4IR::Expr *targetIndex)
+void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase,
+ IR::Expr *targetIndex)
{
+ if (useFastLookups) {
+ Instruction::StoreElementLookup store;
+ store.lookup = registerIndexedSetterLookup();
+ store.base = getParam(targetBase);
+ store.index = getParam(targetIndex);
+ store.source = getParam(source);
+ addInstruction(store);
+ return;
+ }
Instruction::StoreElement store;
store.base = getParam(targetBase);
store.index = getParam(targetIndex);
@@ -563,7 +765,7 @@ void InstructionSelection::setElement(V4IR::Expr *source, V4IR::Expr *targetBase
addInstruction(store);
}
-void InstructionSelection::copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
+void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
{
Instruction::Move move;
move.source = getParam(sourceTemp);
@@ -572,7 +774,7 @@ void InstructionSelection::copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetT
addInstruction(move);
}
-void InstructionSelection::swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
+void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp)
{
Instruction::SwapTemps swap;
swap.left = getParam(sourceTemp);
@@ -580,12 +782,12 @@ void InstructionSelection::swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *target
addInstruction(swap);
}
-void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
+void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp)
{
switch (oper) {
- case V4IR::OpIfTrue:
+ case IR::OpIfTrue:
Q_ASSERT(!"unreachable"); break;
- case V4IR::OpNot: {
+ case IR::OpNot: {
// ### enabling this fails in some cases, where apparently the value is not a bool at runtime
if (0 && isBoolType(sourceTemp)) {
Instruction::UNotBool unot;
@@ -600,20 +802,21 @@ void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::
addInstruction(unot);
return;
}
- case V4IR::OpUMinus: {
+ case IR::OpUMinus: {
Instruction::UMinus uminus;
uminus.source = getParam(sourceTemp);
uminus.result = getResultParam(targetTemp);
addInstruction(uminus);
return;
}
- case V4IR::OpUPlus: {
+ case IR::OpUPlus: {
if (isNumberType(sourceTemp)) {
// use a move
Instruction::Move move;
move.source = getParam(sourceTemp);
move.result = getResultParam(targetTemp);
- addInstruction(move);
+ if (move.source != move.result)
+ addInstruction(move);
return;
}
Instruction::UPlus uplus;
@@ -622,7 +825,7 @@ void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::
addInstruction(uplus);
return;
}
- case V4IR::OpCompl: {
+ case IR::OpCompl: {
// ### enabling this fails in some cases, where apparently the value is not a int at runtime
if (0 && isIntegerType(sourceTemp)) {
Instruction::UComplInt unot;
@@ -637,14 +840,14 @@ void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::
addInstruction(ucompl);
return;
}
- case V4IR::OpIncrement: {
+ case IR::OpIncrement: {
Instruction::Increment inc;
inc.source = getParam(sourceTemp);
inc.result = getResultParam(targetTemp);
addInstruction(inc);
return;
}
- case V4IR::OpDecrement: {
+ case IR::OpDecrement: {
Instruction::Decrement dec;
dec.source = getParam(sourceTemp);
dec.result = getResultParam(targetTemp);
@@ -657,45 +860,14 @@ void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::
Q_ASSERT(!"unreachable");
}
-void InstructionSelection::binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target)
+void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
{
binopHelper(oper, leftSource, rightSource, target);
}
-Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target)
+Param InstructionSelection::binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
{
- if (isNumberType(leftSource) && isNumberType(rightSource)) {
- switch (oper) {
- case V4IR::OpAdd: {
- Instruction::AddNumberParams instr;
- instr.lhs = getParam(leftSource);
- instr.rhs = getParam(rightSource);
- instr.result = getResultParam(target);
- addInstruction(instr);
- return instr.result;
- }
- case V4IR::OpMul: {
- Instruction::MulNumberParams instr;
- instr.lhs = getParam(leftSource);
- instr.rhs = getParam(rightSource);
- instr.result = getResultParam(target);
- addInstruction(instr);
- return instr.result;
- }
- case V4IR::OpSub: {
- Instruction::SubNumberParams instr;
- instr.lhs = getParam(leftSource);
- instr.rhs = getParam(rightSource);
- instr.result = getResultParam(target);
- addInstruction(instr);
- return instr.result;
- }
- default:
- break;
- }
- }
-
- if (oper == V4IR::OpAdd) {
+ if (oper == IR::OpAdd) {
Instruction::Add add;
add.lhs = getParam(leftSource);
add.rhs = getParam(rightSource);
@@ -703,7 +875,7 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
addInstruction(add);
return add.result;
}
- if (oper == V4IR::OpSub) {
+ if (oper == IR::OpSub) {
Instruction::Sub sub;
sub.lhs = getParam(leftSource);
sub.rhs = getParam(rightSource);
@@ -711,7 +883,7 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
addInstruction(sub);
return sub.result;
}
- if (oper == V4IR::OpMul) {
+ if (oper == IR::OpMul) {
Instruction::Mul mul;
mul.lhs = getParam(leftSource);
mul.rhs = getParam(rightSource);
@@ -719,10 +891,10 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
addInstruction(mul);
return mul.result;
}
- if (oper == V4IR::OpBitAnd) {
+ if (oper == IR::OpBitAnd) {
if (leftSource->asConst())
qSwap(leftSource, rightSource);
- if (V4IR::Const *c = rightSource->asConst()) {
+ if (IR::Const *c = rightSource->asConst()) {
Instruction::BitAndConst bitAnd;
bitAnd.lhs = getParam(leftSource);
bitAnd.rhs = convertToValue(c).Value::toInt32();
@@ -737,10 +909,10 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
addInstruction(bitAnd);
return bitAnd.result;
}
- if (oper == V4IR::OpBitOr) {
+ if (oper == IR::OpBitOr) {
if (leftSource->asConst())
qSwap(leftSource, rightSource);
- if (V4IR::Const *c = rightSource->asConst()) {
+ if (IR::Const *c = rightSource->asConst()) {
Instruction::BitOrConst bitOr;
bitOr.lhs = getParam(leftSource);
bitOr.rhs = convertToValue(c).Value::toInt32();
@@ -755,10 +927,10 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
addInstruction(bitOr);
return bitOr.result;
}
- if (oper == V4IR::OpBitXor) {
+ if (oper == IR::OpBitXor) {
if (leftSource->asConst())
qSwap(leftSource, rightSource);
- if (V4IR::Const *c = rightSource->asConst()) {
+ if (IR::Const *c = rightSource->asConst()) {
Instruction::BitXorConst bitXor;
bitXor.lhs = getParam(leftSource);
bitXor.rhs = convertToValue(c).Value::toInt32();
@@ -773,12 +945,44 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
addInstruction(bitXor);
return bitXor.result;
}
+ if (oper == IR::OpRShift) {
+ if (IR::Const *c = rightSource->asConst()) {
+ Instruction::ShrConst shr;
+ shr.lhs = getParam(leftSource);
+ shr.rhs = convertToValue(c).Value::toInt32() & 0x1f;
+ shr.result = getResultParam(target);
+ addInstruction(shr);
+ return shr.result;
+ }
+ Instruction::Shr shr;
+ shr.lhs = getParam(leftSource);
+ shr.rhs = getParam(rightSource);
+ shr.result = getResultParam(target);
+ addInstruction(shr);
+ return shr.result;
+ }
+ if (oper == IR::OpLShift) {
+ if (IR::Const *c = rightSource->asConst()) {
+ Instruction::ShlConst shl;
+ shl.lhs = getParam(leftSource);
+ shl.rhs = convertToValue(c).Value::toInt32() & 0x1f;
+ shl.result = getResultParam(target);
+ addInstruction(shl);
+ return shl.result;
+ }
+ Instruction::Shl shl;
+ shl.lhs = getParam(leftSource);
+ shl.rhs = getParam(rightSource);
+ shl.result = getResultParam(target);
+ addInstruction(shl);
+ return shl.result;
+ }
- if (oper == V4IR::OpInstanceof || oper == V4IR::OpIn || oper == V4IR::OpAdd) {
+ if (oper == IR::OpInstanceof || oper == IR::OpIn || oper == IR::OpAdd) {
Instruction::BinopContext binop;
- if (oper == V4IR::OpInstanceof)
+ if (oper == IR::OpInstanceof)
binop.alu = QV4::__qmljs_instanceof;
- else if (oper == V4IR::OpIn)
+ else if (oper == IR::OpIn)
binop.alu = QV4::__qmljs_in;
else
binop.alu = QV4::__qmljs_add;
@@ -800,7 +1004,7 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
}
}
-void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 *args)
+void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint32 *args)
{
int argLocation = outgoingArgumentTempStart();
argc = 0;
@@ -810,10 +1014,17 @@ void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, qui
// We need to move all the temps into the function arg array
assert(argLocation >= 0);
while (e) {
- Instruction::Move move;
- move.source = getParam(e->expr);
- move.result = Param::createTemp(argLocation);
- addInstruction(move);
+ if (IR::Const *c = e->expr->asConst()) {
+ Instruction::MoveConst move;
+ move.source = convertToValue(c).asReturnedValue();
+ move.result = Param::createTemp(argLocation);
+ addInstruction(move);
+ } else {
+ Instruction::Move move;
+ move.source = getParam(e->expr);
+ move.result = Param::createTemp(argLocation);
+ addInstruction(move);
+ }
++argLocation;
++argc;
e = e->next;
@@ -821,7 +1032,7 @@ void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, qui
}
}
-void InstructionSelection::visitJump(V4IR::Jump *s)
+void InstructionSelection::visitJump(IR::Jump *s)
{
if (s->target == _nextBlock)
return;
@@ -835,27 +1046,27 @@ void InstructionSelection::visitJump(V4IR::Jump *s)
_patches[s->target].append(loc);
}
-void InstructionSelection::visitCJump(V4IR::CJump *s)
+void InstructionSelection::visitCJump(IR::CJump *s)
{
Param condition;
- if (V4IR::Temp *t = s->cond->asTemp()) {
+ if (IR::Temp *t = s->cond->asTemp()) {
condition = getResultParam(t);
- } else if (V4IR::Binop *b = s->cond->asBinop()) {
+ } else if (IR::Binop *b = s->cond->asBinop()) {
condition = binopHelper(b->op, b->left, b->right, /*target*/0);
} else {
Q_UNIMPLEMENTED();
}
- Instruction::CJump jump;
- jump.offset = 0;
- jump.condition = condition;
-
if (s->iftrue == _nextBlock) {
- jump.invert = true;
+ Instruction::JumpNe jump;
+ jump.offset = 0;
+ jump.condition = condition;
ptrdiff_t falseLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
_patches[s->iffalse].append(falseLoc);
} else {
- jump.invert = false;
+ Instruction::JumpEq jump;
+ jump.offset = 0;
+ jump.condition = condition;
ptrdiff_t trueLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
_patches[s->iftrue].append(trueLoc);
@@ -868,14 +1079,14 @@ void InstructionSelection::visitCJump(V4IR::CJump *s)
}
}
-void InstructionSelection::visitRet(V4IR::Ret *s)
+void InstructionSelection::visitRet(IR::Ret *s)
{
Instruction::Ret ret;
ret.result = getParam(s->expr);
addInstruction(ret);
}
-void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
+void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result)
{
if (useFastLookups && func->global) {
Instruction::CallGlobalLookup call;
@@ -894,8 +1105,8 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofMember(V4IR::Expr *base, const QString &name,
- V4IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
+ IR::Temp *result)
{
Instruction::CallBuiltinTypeofMember call;
call.base = getParam(base);
@@ -904,8 +1115,8 @@ void InstructionSelection::callBuiltinTypeofMember(V4IR::Expr *base, const QStri
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofSubscript(V4IR::Expr *base, V4IR::Expr *index,
- V4IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
+ IR::Temp *result)
{
Instruction::CallBuiltinTypeofSubscript call;
call.base = getParam(base);
@@ -914,7 +1125,7 @@ void InstructionSelection::callBuiltinTypeofSubscript(V4IR::Expr *base, V4IR::Ex
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofName(const QString &name, V4IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result)
{
Instruction::CallBuiltinTypeofName call;
call.name = registerString(name);
@@ -922,7 +1133,7 @@ void InstructionSelection::callBuiltinTypeofName(const QString &name, V4IR::Temp
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofValue(V4IR::Expr *value, V4IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result)
{
Instruction::CallBuiltinTypeofValue call;
call.value = getParam(value);
@@ -930,7 +1141,7 @@ void InstructionSelection::callBuiltinTypeofValue(V4IR::Expr *value, V4IR::Temp
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
{
Instruction::CallBuiltinDeleteMember call;
call.base = getParam(base);
@@ -939,8 +1150,8 @@ void InstructionSelection::callBuiltinDeleteMember(V4IR::Temp *base, const QStri
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Expr *index,
- V4IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index,
+ IR::Temp *result)
{
Instruction::CallBuiltinDeleteSubscript call;
call.base = getParam(base);
@@ -949,7 +1160,7 @@ void InstructionSelection::callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Ex
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteName(const QString &name, V4IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result)
{
Instruction::CallBuiltinDeleteName call;
call.name = registerString(name);
@@ -957,16 +1168,15 @@ void InstructionSelection::callBuiltinDeleteName(const QString &name, V4IR::Temp
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteValue(V4IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
{
- Instruction::Move move;
- int idx = jsUnitGenerator()->registerConstant(QV4::Encode(false));
- move.source = Param::createConstant(idx);
+ Instruction::MoveConst move;
+ move.source = QV4::Encode(false);
move.result = getResultParam(result);
addInstruction(move);
}
-void InstructionSelection::callBuiltinThrow(V4IR::Expr *arg)
+void InstructionSelection::callBuiltinThrow(IR::Expr *arg)
{
Instruction::CallBuiltinThrow call;
call.arg = getParam(arg);
@@ -990,7 +1200,7 @@ void InstructionSelection::callBuiltinReThrow()
}
}
-void InstructionSelection::callBuiltinUnwindException(V4IR::Temp *result)
+void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
{
Instruction::CallBuiltinUnwindException call;
call.result = getResultParam(result);
@@ -1005,7 +1215,7 @@ void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionNam
addInstruction(call);
}
-void InstructionSelection::callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result)
+void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result)
{
Instruction::CallBuiltinForeachIteratorObject call;
call.arg = getParam(arg);
@@ -1013,7 +1223,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4I
addInstruction(call);
}
-void InstructionSelection::callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result)
+void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
{
Instruction::CallBuiltinForeachNextPropertyName call;
call.arg = getParam(arg);
@@ -1021,7 +1231,7 @@ void InstructionSelection::callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V
addInstruction(call);
}
-void InstructionSelection::callBuiltinPushWithScope(V4IR::Temp *arg)
+void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
{
Instruction::CallBuiltinPushScope call;
call.arg = getParam(arg);
@@ -1042,7 +1252,7 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineGetterSetter(V4IR::Temp *object, const QString &name, V4IR::Temp *getter, V4IR::Temp *setter)
+void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter)
{
Instruction::CallBuiltinDefineGetterSetter call;
call.object = getParam(object);
@@ -1052,8 +1262,8 @@ void InstructionSelection::callBuiltinDefineGetterSetter(V4IR::Temp *object, con
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const QString &name,
- V4IR::Expr *value)
+void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name,
+ IR::Expr *value)
{
Instruction::CallBuiltinDefineProperty call;
call.object = getParam(object);
@@ -1062,7 +1272,7 @@ void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const Q
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
prepareCallArgs(args, call.argc, &call.args);
@@ -1070,22 +1280,29 @@ void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::Expr
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args)
{
int argLocation = outgoingArgumentTempStart();
const int classId = registerJSClass(args);
- V4IR::ExprList *it = args;
+ IR::ExprList *it = args;
while (it) {
it = it->next;
bool isData = it->expr->asConst()->value;
it = it->next;
- Instruction::Move move;
- move.source = getParam(it->expr);
- move.result = Param::createTemp(argLocation);
- addInstruction(move);
+ if (IR::Const *c = it->expr->asConst()) {
+ Instruction::MoveConst move;
+ move.source = convertToValue(c).asReturnedValue();
+ move.result = Param::createTemp(argLocation);
+ addInstruction(move);
+ } else {
+ Instruction::Move move;
+ move.source = getParam(it->expr);
+ move.result = Param::createTemp(argLocation);
+ addInstruction(move);
+ }
++argLocation;
if (!isData) {
@@ -1108,7 +1325,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
addInstruction(call);
}
-void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result)
+void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result)
{
Instruction::CallBuiltinSetupArgumentsObject call;
call.result = getResultParam(result);
@@ -1116,7 +1333,7 @@ void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result)
}
-void QQmlJS::Moth::InstructionSelection::callBuiltinConvertThisToObject()
+void QV4::Moth::InstructionSelection::callBuiltinConvertThisToObject()
{
Instruction::CallBuiltinConvertThisToObject call;
addInstruction(call);
@@ -1124,12 +1341,12 @@ void QQmlJS::Moth::InstructionSelection::callBuiltinConvertThisToObject()
ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr)
{
+
#ifdef MOTH_THREADED_INTERPRETER
instr.common.code = VME::instructionJumpTable()[static_cast<int>(type)];
#else
instr.common.instructionType = type;
#endif
- instr.common.breakPoint = 0;
int instructionSize = Instr::size(type);
if (_codeEnd - _codeNext < instructionSize) {
@@ -1152,7 +1369,7 @@ ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &in
void InstructionSelection::patchJumpAddresses()
{
- typedef QHash<V4IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator PatchIt;
+ typedef QHash<IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator PatchIt;
for (PatchIt i = _patches.begin(), ei = _patches.end(); i != ei; ++i) {
Q_ASSERT(_addrs.contains(i.key()));
ptrdiff_t target = _addrs.value(i.key());
@@ -1178,19 +1395,19 @@ QByteArray InstructionSelection::squeezeCode() const
return squeezed;
}
-Param InstructionSelection::getParam(V4IR::Expr *e) {
+Param InstructionSelection::getParam(IR::Expr *e) {
assert(e);
- if (V4IR::Const *c = e->asConst()) {
+ if (IR::Const *c = e->asConst()) {
int idx = jsUnitGenerator()->registerConstant(convertToValue(c).asReturnedValue());
return Param::createConstant(idx);
- } else if (V4IR::Temp *t = e->asTemp()) {
+ } else if (IR::Temp *t = e->asTemp()) {
switch (t->kind) {
- case V4IR::Temp::Formal:
- case V4IR::Temp::ScopedFormal: return Param::createArgument(t->index, t->scope);
- case V4IR::Temp::Local: return Param::createLocal(t->index);
- case V4IR::Temp::ScopedLocal: return Param::createScopedLocal(t->index, t->scope);
- case V4IR::Temp::StackSlot:
+ case IR::Temp::Formal:
+ case IR::Temp::ScopedFormal: return Param::createArgument(t->index, t->scope);
+ case IR::Temp::Local: return Param::createLocal(t->index);
+ case IR::Temp::ScopedLocal: return Param::createScopedLocal(t->index, t->scope);
+ case IR::Temp::StackSlot:
return Param::createTemp(t->index);
default:
Q_UNREACHABLE();
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index d8a85ff249..e2ba971e26 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -46,12 +46,12 @@
#include <private/qv4isel_p.h>
#include <private/qv4isel_util_p.h>
#include <private/qv4jsir_p.h>
-#include <private/qv4value_def_p.h>
+#include <private/qv4value_p.h>
#include "qv4instr_moth_p.h"
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
+namespace QV4 {
namespace Moth {
struct CompilationUnit : public QV4::CompiledData::CompilationUnit
@@ -64,11 +64,11 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit
};
class Q_QML_EXPORT InstructionSelection:
- public V4IR::IRDecoder,
+ public IR::IRDecoder,
public EvalInstructionSelection
{
public:
- InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
~InstructionSelection();
virtual void run(int functionIndex);
@@ -76,66 +76,66 @@ public:
protected:
virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
- virtual void visitJump(V4IR::Jump *);
- virtual void visitCJump(V4IR::CJump *);
- virtual void visitRet(V4IR::Ret *);
-
- virtual void callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void callBuiltinTypeofMember(V4IR::Expr *base, const QString &name, V4IR::Temp *result);
- virtual void callBuiltinTypeofSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *result);
- virtual void callBuiltinTypeofName(const QString &name, V4IR::Temp *result);
- virtual void callBuiltinTypeofValue(V4IR::Expr *value, V4IR::Temp *result);
- virtual void callBuiltinDeleteMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result);
- virtual void callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Expr *index, V4IR::Temp *result);
- virtual void callBuiltinDeleteName(const QString &name, V4IR::Temp *result);
- virtual void callBuiltinDeleteValue(V4IR::Temp *result);
- virtual void callBuiltinThrow(V4IR::Expr *arg);
+ virtual void visitJump(IR::Jump *);
+ virtual void visitCJump(IR::CJump *);
+ virtual void visitRet(IR::Ret *);
+
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result);
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result);
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result);
+ virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result);
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result);
+ virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result);
+ virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result);
+ virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result);
+ virtual void callBuiltinDeleteValue(IR::Temp *result);
+ virtual void callBuiltinThrow(IR::Expr *arg);
virtual void callBuiltinReThrow();
- virtual void callBuiltinUnwindException(V4IR::Temp *);
+ virtual void callBuiltinUnwindException(IR::Temp *);
virtual void callBuiltinPushCatchScope(const QString &exceptionName);
- virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result);
- virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result);
- virtual void callBuiltinPushWithScope(V4IR::Temp *arg);
+ virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result);
+ virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
+ virtual void callBuiltinPushWithScope(IR::Temp *arg);
virtual void callBuiltinPopScope();
virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
- virtual void callBuiltinDefineGetterSetter(V4IR::Temp *object, const QString &name, V4IR::Temp *getter, V4IR::Temp *setter);
- virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Expr *value);
- virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args);
- virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result);
+ virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter);
+ virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Expr *value);
+ virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args);
+ virtual void callBuiltinSetupArgumentObject(IR::Temp *result);
virtual void callBuiltinConvertThisToObject();
- virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void convertType(V4IR::Temp *source, V4IR::Temp *target);
- virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void loadThisObject(V4IR::Temp *temp);
- virtual void loadQmlIdArray(V4IR::Temp *temp);
- virtual void loadQmlImportedScripts(V4IR::Temp *temp);
- virtual void loadQmlContextObject(V4IR::Temp *temp);
- virtual void loadQmlScopeObject(V4IR::Temp *temp);
- virtual void loadQmlSingleton(const QString &name, V4IR::Temp *temp);
- virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);
- virtual void loadString(const QString &str, V4IR::Temp *targetTemp);
- virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp);
- virtual void getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp);
- virtual void setActivationProperty(V4IR::Expr *source, const QString &targetName);
- virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target);
- virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
- virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
- virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target);
- virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
- virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
- virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
- virtual void swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
- virtual void unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
- virtual void binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target);
+ virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result);
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result);
+ virtual void convertType(IR::Temp *source, IR::Temp *target);
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result);
+ virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result);
+ virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
+ virtual void loadThisObject(IR::Temp *temp);
+ virtual void loadQmlIdArray(IR::Temp *temp);
+ virtual void loadQmlImportedScripts(IR::Temp *temp);
+ virtual void loadQmlContextObject(IR::Temp *temp);
+ virtual void loadQmlScopeObject(IR::Temp *temp);
+ virtual void loadQmlSingleton(const QString &name, IR::Temp *temp);
+ virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp);
+ virtual void loadString(const QString &str, IR::Temp *targetTemp);
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp);
+ virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp);
+ virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
+ virtual void initClosure(IR::Closure *closure, IR::Temp *target);
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target);
+ virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target);
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target);
+ virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
+ virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp);
+ virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp);
+ virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp);
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
private:
- Param binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target);
+ Param binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
struct Instruction {
#define MOTH_INSTR_DATA_TYPEDEF(I, FMT) typedef InstrData<Instr::I> I;
@@ -145,9 +145,9 @@ private:
Instruction();
};
- Param getParam(V4IR::Expr *e);
+ Param getParam(IR::Expr *e);
- Param getResultParam(V4IR::Temp *result)
+ Param getResultParam(IR::Temp *result)
{
if (result)
return getParam(result);
@@ -155,12 +155,12 @@ private:
return Param::createTemp(scratchTempIndex());
}
- void simpleMove(V4IR::Move *);
- void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 * = 0);
+ void simpleMove(IR::Move *);
+ void prepareCallArgs(IR::ExprList *, quint32 &, quint32 * = 0);
int scratchTempIndex() const { return _function->tempCount; }
int callDataStart() const { return scratchTempIndex() + 1; }
- int outgoingArgumentTempStart() const { return callDataStart() + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue); }
+ int outgoingArgumentTempStart() const { return callDataStart() + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value); }
int frameSize() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
template <int Instr>
@@ -171,28 +171,28 @@ private:
QQmlEnginePrivate *qmlEngine;
- V4IR::BasicBlock *_block;
- V4IR::BasicBlock *_nextBlock;
+ IR::BasicBlock *_block;
+ IR::BasicBlock *_nextBlock;
- QHash<V4IR::BasicBlock *, QVector<ptrdiff_t> > _patches;
- QHash<V4IR::BasicBlock *, ptrdiff_t> _addrs;
+ QHash<IR::BasicBlock *, QVector<ptrdiff_t> > _patches;
+ QHash<IR::BasicBlock *, ptrdiff_t> _addrs;
uchar *_codeStart;
uchar *_codeNext;
uchar *_codeEnd;
- QSet<V4IR::Jump *> _removableJumps;
- V4IR::Stmt *_currentStatement;
+ QSet<IR::Jump *> _removableJumps;
+ IR::Stmt *_currentStatement;
CompilationUnit *compilationUnit;
- QHash<V4IR::Function *, QByteArray> codeRefs;
+ QHash<IR::Function *, QByteArray> codeRefs;
};
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
+ virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
{ return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
virtual bool jitCompileRegexps() const
{ return false; }
@@ -202,12 +202,12 @@ template<int InstrT>
ptrdiff_t InstructionSelection::addInstruction(const InstrData<InstrT> &data)
{
Instr genericInstr;
- InstrMeta<InstrT>::setData(genericInstr, data);
+ InstrMeta<InstrT>::setDataNoCommon(genericInstr, data);
return addInstructionHelper(static_cast<Instr::Type>(InstrT), genericInstr);
}
} // namespace Moth
-} // namespace QQmlJS
+} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 644e06b59a..4c70c1ddd8 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -57,8 +57,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
#define qout *qout()
} // anonymous namespace
-using namespace QQmlJS;
-using namespace QQmlJS::V4IR;
+using namespace QV4;
+using namespace QV4::IR;
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
: useFastLookups(true)
@@ -93,71 +93,71 @@ QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool gener
return unit;
}
-void IRDecoder::visitMove(V4IR::Move *s)
+void IRDecoder::visitMove(IR::Move *s)
{
- if (V4IR::Name *n = s->target->asName()) {
+ if (IR::Name *n = s->target->asName()) {
if (s->source->asTemp() || s->source->asConst()) {
setActivationProperty(s->source, *n->id);
return;
}
- } else if (V4IR::Temp *t = s->target->asTemp()) {
- if (V4IR::Name *n = s->source->asName()) {
+ } else if (IR::Temp *t = s->target->asTemp()) {
+ if (IR::Name *n = s->source->asName()) {
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
loadThisObject(t);
- else if (n->builtin == V4IR::Name::builtin_qml_id_array)
+ else if (n->builtin == IR::Name::builtin_qml_id_array)
loadQmlIdArray(t);
- else if (n->builtin == V4IR::Name::builtin_qml_context_object)
+ else if (n->builtin == IR::Name::builtin_qml_context_object)
loadQmlContextObject(t);
- else if (n->builtin == V4IR::Name::builtin_qml_scope_object)
+ else if (n->builtin == IR::Name::builtin_qml_scope_object)
loadQmlScopeObject(t);
- else if (n->builtin == V4IR::Name::builtin_qml_imported_scripts_object)
+ else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
loadQmlImportedScripts(t);
else if (n->qmlSingleton)
loadQmlSingleton(*n->id, t);
else
getActivationProperty(n, t);
return;
- } else if (V4IR::Const *c = s->source->asConst()) {
+ } else if (IR::Const *c = s->source->asConst()) {
loadConst(c, t);
return;
- } else if (V4IR::Temp *t2 = s->source->asTemp()) {
+ } else if (IR::Temp *t2 = s->source->asTemp()) {
if (s->swap)
swapValues(t2, t);
else
copyValue(t2, t);
return;
- } else if (V4IR::String *str = s->source->asString()) {
+ } else if (IR::String *str = s->source->asString()) {
loadString(*str->value, t);
return;
- } else if (V4IR::RegExp *re = s->source->asRegExp()) {
+ } else if (IR::RegExp *re = s->source->asRegExp()) {
loadRegexp(re, t);
return;
- } else if (V4IR::Closure *clos = s->source->asClosure()) {
+ } else if (IR::Closure *clos = s->source->asClosure()) {
initClosure(clos, t);
return;
- } else if (V4IR::New *ctor = s->source->asNew()) {
+ } else if (IR::New *ctor = s->source->asNew()) {
if (Name *func = ctor->base->asName()) {
constructActivationProperty(func, ctor->args, t);
return;
- } else if (V4IR::Member *member = ctor->base->asMember()) {
+ } else if (IR::Member *member = ctor->base->asMember()) {
constructProperty(member->base->asTemp(), *member->name, ctor->args, t);
return;
- } else if (V4IR::Temp *value = ctor->base->asTemp()) {
+ } else if (IR::Temp *value = ctor->base->asTemp()) {
constructValue(value, ctor->args, t);
return;
}
- } else if (V4IR::Member *m = s->source->asMember()) {
+ } else if (IR::Member *m = s->source->asMember()) {
if (m->property) {
bool captureRequired = true;
- Q_ASSERT(m->kind != V4IR::Member::MemberOfEnum);
+ Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
- if (m->kind == V4IR::Member::MemberOfQmlContextObject) {
+ if (m->kind == IR::Member::MemberOfQmlContextObject) {
_function->contextObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
captureRequired = false;
- } else if (m->kind == V4IR::Member::MemberOfQmlScopeObject) {
+ } else if (m->kind == IR::Member::MemberOfQmlScopeObject) {
_function->scopeObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
captureRequired = false;
}
@@ -168,18 +168,18 @@ void IRDecoder::visitMove(V4IR::Move *s)
getProperty(m->base, *m->name, t);
return;
}
- } else if (V4IR::Subscript *ss = s->source->asSubscript()) {
+ } else if (IR::Subscript *ss = s->source->asSubscript()) {
getElement(ss->base->asTemp(), ss->index, t);
return;
- } else if (V4IR::Unop *u = s->source->asUnop()) {
- if (V4IR::Temp *e = u->expr->asTemp()) {
+ } else if (IR::Unop *u = s->source->asUnop()) {
+ if (IR::Temp *e = u->expr->asTemp()) {
unop(u->op, e, t);
return;
}
- } else if (V4IR::Binop *b = s->source->asBinop()) {
+ } else if (IR::Binop *b = s->source->asBinop()) {
binop(b->op, b->left, b->right, t);
return;
- } else if (V4IR::Call *c = s->source->asCall()) {
+ } else if (IR::Call *c = s->source->asCall()) {
if (c->base->asName()) {
callBuiltin(c, t);
return;
@@ -189,19 +189,19 @@ void IRDecoder::visitMove(V4IR::Move *s)
} else if (Subscript *ss = c->base->asSubscript()) {
callSubscript(ss->base, ss->index, c->args, t);
return;
- } else if (V4IR::Temp *value = c->base->asTemp()) {
+ } else if (IR::Temp *value = c->base->asTemp()) {
callValue(value, c->args, t);
return;
}
- } else if (V4IR::Convert *c = s->source->asConvert()) {
+ } else if (IR::Convert *c = s->source->asConvert()) {
Q_ASSERT(c->expr->asTemp());
convertType(c->expr->asTemp(), t);
return;
}
- } else if (V4IR::Member *m = s->target->asMember()) {
+ } else if (IR::Member *m = s->target->asMember()) {
if (m->base->asTemp() || m->base->asConst()) {
if (s->source->asTemp() || s->source->asConst()) {
- Q_ASSERT(m->kind != V4IR::Member::MemberOfEnum);
+ Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
if (m->property && attachedPropertiesId == 0) {
setQObjectProperty(s->source, m->base, m->property->coreIndex);
@@ -212,7 +212,7 @@ void IRDecoder::visitMove(V4IR::Move *s)
}
}
}
- } else if (V4IR::Subscript *ss = s->target->asSubscript()) {
+ } else if (IR::Subscript *ss = s->target->asSubscript()) {
if (s->source->asTemp() || s->source->asConst()) {
setElement(s->source, ss->base, ss->index);
return;
@@ -221,7 +221,7 @@ void IRDecoder::visitMove(V4IR::Move *s)
// For anything else...:
Q_UNIMPLEMENTED();
- s->dump(qout, V4IR::Stmt::MIR);
+ s->dump(qout, IR::Stmt::MIR);
qout << endl;
assert(!"TODO");
}
@@ -230,9 +230,9 @@ IRDecoder::~IRDecoder()
{
}
-void IRDecoder::visitExp(V4IR::Exp *s)
+void IRDecoder::visitExp(IR::Exp *s)
{
- if (V4IR::Call *c = s->expr->asCall()) {
+ if (IR::Call *c = s->expr->asCall()) {
// These are calls where the result is ignored.
if (c->base->asName()) {
callBuiltin(c, 0);
@@ -251,24 +251,24 @@ void IRDecoder::visitExp(V4IR::Exp *s)
}
}
-void IRDecoder::callBuiltin(V4IR::Call *call, V4IR::Temp *result)
+void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
{
- V4IR::Name *baseName = call->base->asName();
+ IR::Name *baseName = call->base->asName();
assert(baseName != 0);
switch (baseName->builtin) {
- case V4IR::Name::builtin_invalid:
+ case IR::Name::builtin_invalid:
callBuiltinInvalid(baseName, call->args, result);
return;
- case V4IR::Name::builtin_typeof: {
- if (V4IR::Member *m = call->args->expr->asMember()) {
+ case IR::Name::builtin_typeof: {
+ if (IR::Member *m = call->args->expr->asMember()) {
callBuiltinTypeofMember(m->base, *m->name, result);
return;
- } else if (V4IR::Subscript *ss = call->args->expr->asSubscript()) {
+ } else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
callBuiltinTypeofSubscript(ss->base, ss->index, result);
return;
- } else if (V4IR::Name *n = call->args->expr->asName()) {
+ } else if (IR::Name *n = call->args->expr->asName()) {
callBuiltinTypeofName(*n->id, result);
return;
} else if (call->args->expr->asTemp() || call->args->expr->asConst()){
@@ -277,14 +277,14 @@ void IRDecoder::callBuiltin(V4IR::Call *call, V4IR::Temp *result)
}
} break;
- case V4IR::Name::builtin_delete: {
- if (V4IR::Member *m = call->args->expr->asMember()) {
+ case IR::Name::builtin_delete: {
+ if (IR::Member *m = call->args->expr->asMember()) {
callBuiltinDeleteMember(m->base->asTemp(), *m->name, result);
return;
- } else if (V4IR::Subscript *ss = call->args->expr->asSubscript()) {
+ } else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
callBuiltinDeleteSubscript(ss->base->asTemp(), ss->index, result);
return;
- } else if (V4IR::Name *n = call->args->expr->asName()) {
+ } else if (IR::Name *n = call->args->expr->asName()) {
callBuiltinDeleteName(*n->id, result);
return;
} else if (call->args->expr->asTemp()){
@@ -294,107 +294,107 @@ void IRDecoder::callBuiltin(V4IR::Call *call, V4IR::Temp *result)
}
} break;
- case V4IR::Name::builtin_throw: {
- V4IR::Expr *arg = call->args->expr;
+ case IR::Name::builtin_throw: {
+ IR::Expr *arg = call->args->expr;
assert(arg->asTemp() || arg->asConst());
callBuiltinThrow(arg);
} return;
- case V4IR::Name::builtin_rethrow: {
+ case IR::Name::builtin_rethrow: {
callBuiltinReThrow();
} return;
- case V4IR::Name::builtin_unwind_exception: {
+ case IR::Name::builtin_unwind_exception: {
callBuiltinUnwindException(result);
} return;
- case V4IR::Name::builtin_push_catch_scope: {
- V4IR::String *s = call->args->expr->asString();
+ case IR::Name::builtin_push_catch_scope: {
+ IR::String *s = call->args->expr->asString();
Q_ASSERT(s);
callBuiltinPushCatchScope(*s->value);
} return;
- case V4IR::Name::builtin_foreach_iterator_object: {
- V4IR::Temp *arg = call->args->expr->asTemp();
+ case IR::Name::builtin_foreach_iterator_object: {
+ IR::Temp *arg = call->args->expr->asTemp();
assert(arg != 0);
callBuiltinForeachIteratorObject(arg, result);
} return;
- case V4IR::Name::builtin_foreach_next_property_name: {
- V4IR::Temp *arg = call->args->expr->asTemp();
+ case IR::Name::builtin_foreach_next_property_name: {
+ IR::Temp *arg = call->args->expr->asTemp();
assert(arg != 0);
callBuiltinForeachNextPropertyname(arg, result);
} return;
- case V4IR::Name::builtin_push_with_scope: {
- V4IR::Temp *arg = call->args->expr->asTemp();
+ case IR::Name::builtin_push_with_scope: {
+ IR::Temp *arg = call->args->expr->asTemp();
assert(arg != 0);
callBuiltinPushWithScope(arg);
} return;
- case V4IR::Name::builtin_pop_scope:
+ case IR::Name::builtin_pop_scope:
callBuiltinPopScope();
return;
- case V4IR::Name::builtin_declare_vars: {
+ case IR::Name::builtin_declare_vars: {
if (!call->args)
return;
- V4IR::Const *deletable = call->args->expr->asConst();
- assert(deletable->type == V4IR::BoolType);
- for (V4IR::ExprList *it = call->args->next; it; it = it->next) {
- V4IR::Name *arg = it->expr->asName();
+ IR::Const *deletable = call->args->expr->asConst();
+ assert(deletable->type == IR::BoolType);
+ for (IR::ExprList *it = call->args->next; it; it = it->next) {
+ IR::Name *arg = it->expr->asName();
assert(arg != 0);
callBuiltinDeclareVar(deletable->value != 0, *arg->id);
}
} return;
- case V4IR::Name::builtin_define_getter_setter: {
+ case IR::Name::builtin_define_getter_setter: {
if (!call->args)
return;
- V4IR::ExprList *args = call->args;
- V4IR::Temp *object = args->expr->asTemp();
+ IR::ExprList *args = call->args;
+ IR::Temp *object = args->expr->asTemp();
assert(object);
args = args->next;
assert(args);
- V4IR::Name *name = args->expr->asName();
+ IR::Name *name = args->expr->asName();
args = args->next;
assert(args);
- V4IR::Temp *getter = args->expr->asTemp();
+ IR::Temp *getter = args->expr->asTemp();
args = args->next;
assert(args);
- V4IR::Temp *setter = args->expr->asTemp();
+ IR::Temp *setter = args->expr->asTemp();
callBuiltinDefineGetterSetter(object, *name->id, getter, setter);
} return;
- case V4IR::Name::builtin_define_property: {
+ case IR::Name::builtin_define_property: {
if (!call->args)
return;
- V4IR::ExprList *args = call->args;
- V4IR::Temp *object = args->expr->asTemp();
+ IR::ExprList *args = call->args;
+ IR::Temp *object = args->expr->asTemp();
assert(object);
args = args->next;
assert(args);
- V4IR::Name *name = args->expr->asName();
+ IR::Name *name = args->expr->asName();
args = args->next;
assert(args);
- V4IR::Expr *value = args->expr;
+ IR::Expr *value = args->expr;
callBuiltinDefineProperty(object, *name->id, value);
} return;
- case V4IR::Name::builtin_define_array:
+ case IR::Name::builtin_define_array:
callBuiltinDefineArray(result, call->args);
return;
- case V4IR::Name::builtin_define_object_literal:
+ case IR::Name::builtin_define_object_literal:
callBuiltinDefineObjectLiteral(result, call->args);
return;
- case V4IR::Name::builtin_setup_argument_object:
+ case IR::Name::builtin_setup_argument_object:
callBuiltinSetupArgumentObject(result);
return;
- case V4IR::Name::builtin_convert_this_to_object:
+ case IR::Name::builtin_convert_this_to_object:
callBuiltinConvertThisToObject();
return;
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 5ddafc07ab..bfe0adc431 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -55,16 +55,14 @@ QT_BEGIN_NAMESPACE
class QQmlEnginePrivate;
namespace QV4 {
+
class ExecutableAllocator;
struct Function;
-}
-
-namespace QQmlJS {
class Q_QML_EXPORT EvalInstructionSelection
{
public:
- EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
virtual ~EvalInstructionSelection() = 0;
QV4::CompiledData::CompilationUnit *compile(bool generateUnitData = true);
@@ -72,11 +70,13 @@ public:
void setUseFastLookups(bool b) { useFastLookups = b; }
int registerString(const QString &str) { return jsGenerator->registerString(str); }
+ uint registerIndexedGetterLookup() { return jsGenerator->registerIndexedGetterLookup(); }
+ uint registerIndexedSetterLookup() { return jsGenerator->registerIndexedSetterLookup(); }
uint registerGetterLookup(const QString &name) { return jsGenerator->registerGetterLookup(name); }
uint registerSetterLookup(const QString &name) { return jsGenerator->registerSetterLookup(name); }
uint registerGlobalGetterLookup(const QString &name) { return jsGenerator->registerGlobalGetterLookup(name); }
- int registerRegExp(QQmlJS::V4IR::RegExp *regexp) { return jsGenerator->registerRegExp(regexp); }
- int registerJSClass(QQmlJS::V4IR::ExprList *args) { return jsGenerator->registerJSClass(args); }
+ int registerRegExp(IR::RegExp *regexp) { return jsGenerator->registerRegExp(regexp); }
+ int registerJSClass(IR::ExprList *args) { return jsGenerator->registerJSClass(args); }
QV4::Compiler::JSUnitGenerator *jsUnitGenerator() const { return jsGenerator; }
protected:
@@ -87,93 +87,93 @@ protected:
QV4::ExecutableAllocator *executableAllocator;
QV4::Compiler::JSUnitGenerator *jsGenerator;
QScopedPointer<QV4::Compiler::JSUnitGenerator> ownJSGenerator;
- V4IR::Module *irModule;
+ IR::Module *irModule;
};
class Q_QML_EXPORT EvalISelFactory
{
public:
virtual ~EvalISelFactory() = 0;
- virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) = 0;
+ virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) = 0;
virtual bool jitCompileRegexps() const = 0;
};
-namespace V4IR {
-class Q_QML_EXPORT IRDecoder: protected V4IR::StmtVisitor
+namespace IR {
+class Q_QML_EXPORT IRDecoder: protected IR::StmtVisitor
{
public:
IRDecoder() : _function(0) {}
virtual ~IRDecoder() = 0;
- virtual void visitPhi(V4IR::Phi *) {}
+ virtual void visitPhi(IR::Phi *) {}
public: // visitor methods for StmtVisitor:
- virtual void visitMove(V4IR::Move *s);
- virtual void visitExp(V4IR::Exp *s);
+ virtual void visitMove(IR::Move *s);
+ virtual void visitExp(IR::Exp *s);
public: // to implement by subclasses:
- virtual void callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void callBuiltinTypeofMember(V4IR::Expr *base, const QString &name, V4IR::Temp *result) = 0;
- virtual void callBuiltinTypeofSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *result) = 0;
- virtual void callBuiltinTypeofName(const QString &name, V4IR::Temp *result) = 0;
- virtual void callBuiltinTypeofValue(V4IR::Expr *value, V4IR::Temp *result) = 0;
- virtual void callBuiltinDeleteMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result) = 0;
- virtual void callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Expr *index, V4IR::Temp *result) = 0;
- virtual void callBuiltinDeleteName(const QString &name, V4IR::Temp *result) = 0;
- virtual void callBuiltinDeleteValue(V4IR::Temp *result) = 0;
- virtual void callBuiltinThrow(V4IR::Expr *arg) = 0;
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result) = 0;
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result) = 0;
+ virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result) = 0;
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result) = 0;
+ virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) = 0;
+ virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result) = 0;
+ virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result) = 0;
+ virtual void callBuiltinDeleteValue(IR::Temp *result) = 0;
+ virtual void callBuiltinThrow(IR::Expr *arg) = 0;
virtual void callBuiltinReThrow() = 0;
- virtual void callBuiltinUnwindException(V4IR::Temp *) = 0;
+ virtual void callBuiltinUnwindException(IR::Temp *) = 0;
virtual void callBuiltinPushCatchScope(const QString &exceptionName) = 0;
- virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result) = 0;
- virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result) = 0;
- virtual void callBuiltinPushWithScope(V4IR::Temp *arg) = 0;
+ virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) = 0;
+ virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) = 0;
+ virtual void callBuiltinPushWithScope(IR::Temp *arg) = 0;
virtual void callBuiltinPopScope() = 0;
virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0;
- virtual void callBuiltinDefineGetterSetter(V4IR::Temp *object, const QString &name, V4IR::Temp *getter, V4IR::Temp *setter) = 0;
- virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Expr *value) = 0;
- virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args) = 0;
- virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args) = 0;
- virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result) = 0;
+ virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) = 0;
+ virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Expr *value) = 0;
+ virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args) = 0;
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args) = 0;
+ virtual void callBuiltinSetupArgumentObject(IR::Temp *result) = 0;
virtual void callBuiltinConvertThisToObject() = 0;
- virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void convertType(V4IR::Temp *source, V4IR::Temp *target) = 0;
- virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) = 0;
- virtual void loadThisObject(V4IR::Temp *temp) = 0;
- virtual void loadQmlIdArray(V4IR::Temp *temp) = 0;
- virtual void loadQmlImportedScripts(V4IR::Temp *temp) = 0;
- virtual void loadQmlContextObject(V4IR::Temp *temp) = 0;
- virtual void loadQmlScopeObject(V4IR::Temp *temp) = 0;
- virtual void loadQmlSingleton(const QString &name, V4IR::Temp *temp) = 0;
- virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp) = 0;
- virtual void loadString(const QString &str, V4IR::Temp *targetTemp) = 0;
- virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp) = 0;
- virtual void getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp) = 0;
- virtual void setActivationProperty(V4IR::Expr *source, const QString &targetName) = 0;
- virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target) = 0;
- virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target) = 0;
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *targetTemp) = 0;
- virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName) = 0;
- virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex) = 0;
- virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target) = 0;
- virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex) = 0;
- virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp) = 0;
- virtual void swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp) = 0;
- virtual void unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp) = 0;
- virtual void binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target) = 0;
+ virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void convertType(IR::Temp *source, IR::Temp *target) = 0;
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0;
+ virtual void loadThisObject(IR::Temp *temp) = 0;
+ virtual void loadQmlIdArray(IR::Temp *temp) = 0;
+ virtual void loadQmlImportedScripts(IR::Temp *temp) = 0;
+ virtual void loadQmlContextObject(IR::Temp *temp) = 0;
+ virtual void loadQmlScopeObject(IR::Temp *temp) = 0;
+ virtual void loadQmlSingleton(const QString &name, IR::Temp *temp) = 0;
+ virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp) = 0;
+ virtual void loadString(const QString &str, IR::Temp *targetTemp) = 0;
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp) = 0;
+ virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp) = 0;
+ virtual void setActivationProperty(IR::Expr *source, const QString &targetName) = 0;
+ virtual void initClosure(IR::Closure *closure, IR::Temp *target) = 0;
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target) = 0;
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *targetTemp) = 0;
+ virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0;
+ virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0;
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target) = 0;
+ virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0;
+ virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
+ virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
+ virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) = 0;
protected:
- virtual void callBuiltin(V4IR::Call *c, V4IR::Temp *result);
+ virtual void callBuiltin(IR::Call *c, IR::Temp *result);
- V4IR::Function *_function; // subclass needs to set
+ IR::Function *_function; // subclass needs to set
};
} // namespace IR
-} // namespace QQmlJS
+} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 38ea682d3b..be1714f2de 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -42,12 +42,12 @@
#ifndef QV4ISEL_UTIL_P_H
#define QV4ISEL_UTIL_P_H
-#include "private/qv4value_def_p.h"
+#include "private/qv4value_p.h"
#include "qv4jsir_p.h"
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
+namespace QV4 {
inline bool canConvertToSignedInteger(double value)
{
@@ -63,104 +63,118 @@ inline bool canConvertToUnsignedInteger(double value)
return uval == value && !(value == 0 && isNegative(value));
}
-inline QV4::Primitive convertToValue(V4IR::Const *c)
+inline Primitive convertToValue(IR::Const *c)
{
switch (c->type) {
- case V4IR::MissingType:
- return QV4::Primitive::emptyValue();
- case V4IR::NullType:
- return QV4::Primitive::nullValue();
- case V4IR::UndefinedType:
- return QV4::Primitive::undefinedValue();
- case V4IR::BoolType:
- return QV4::Primitive::fromBoolean(c->value != 0);
- case V4IR::SInt32Type:
- return QV4::Primitive::fromInt32(int(c->value));
- case V4IR::UInt32Type:
- return QV4::Primitive::fromUInt32(unsigned(c->value));
- case V4IR::DoubleType:
- return QV4::Primitive::fromDouble(c->value);
- case V4IR::NumberType: {
+ case IR::MissingType:
+ return Primitive::emptyValue();
+ case IR::NullType:
+ return Primitive::nullValue();
+ case IR::UndefinedType:
+ return Primitive::undefinedValue();
+ case IR::BoolType:
+ return Primitive::fromBoolean(c->value != 0);
+ case IR::SInt32Type:
+ return Primitive::fromInt32(int(c->value));
+ case IR::UInt32Type:
+ return Primitive::fromUInt32(unsigned(c->value));
+ case IR::DoubleType:
+ return Primitive::fromDouble(c->value);
+ case IR::NumberType: {
int ival = (int)c->value;
if (canConvertToSignedInteger(c->value)) {
- return QV4::Primitive::fromInt32(ival);
+ return Primitive::fromInt32(ival);
} else {
- return QV4::Primitive::fromDouble(c->value);
+ return Primitive::fromDouble(c->value);
}
}
default:
Q_UNREACHABLE();
}
// unreachable, but the function must return something
- return QV4::Primitive::undefinedValue();
+ return Primitive::undefinedValue();
}
-class ConvertTemps: protected V4IR::StmtVisitor, protected V4IR::ExprVisitor
+class ConvertTemps: protected IR::StmtVisitor, protected IR::ExprVisitor
{
- int _nextFreeStackSlot;
- QHash<V4IR::Temp, int> _stackSlotForTemp;
-
- void renumber(V4IR::Temp *t)
+ void renumber(IR::Temp *t)
{
- if (t->kind != V4IR::Temp::VirtualRegister)
+ if (t->kind != IR::Temp::VirtualRegister)
return;
- int stackSlot = _stackSlotForTemp.value(*t, -1);
+ int stackSlot = _stackSlotForTemp.value(t->index, -1);
if (stackSlot == -1) {
- stackSlot = _nextFreeStackSlot++;
- _stackSlotForTemp[*t] = stackSlot;
+ stackSlot = allocateFreeSlot();
+ _stackSlotForTemp[t->index] = stackSlot;
}
- t->kind = V4IR::Temp::StackSlot;
+ t->kind = IR::Temp::StackSlot;
t->index = stackSlot;
}
+protected:
+ int _nextUnusedStackSlot;
+ QHash<int, int> _stackSlotForTemp;
+ IR::BasicBlock *_currentBasicBlock;
+ virtual int allocateFreeSlot()
+ {
+ return _nextUnusedStackSlot++;
+ }
+
+ virtual void process(IR::Stmt *s)
+ {
+ s->accept(this);
+ }
+
public:
ConvertTemps()
- : _nextFreeStackSlot(0)
+ : _nextUnusedStackSlot(0)
+ , _currentBasicBlock(0)
{}
- void toStackSlots(V4IR::Function *function)
+ void toStackSlots(IR::Function *function)
{
_stackSlotForTemp.reserve(function->tempCount);
- foreach (V4IR::BasicBlock *bb, function->basicBlocks)
- foreach (V4IR::Stmt *s, bb->statements)
- s->accept(this);
+ foreach (IR::BasicBlock *bb, function->basicBlocks) {
+ _currentBasicBlock = bb;
+ foreach (IR::Stmt *s, bb->statements)
+ process(s);
+ }
- function->tempCount = _nextFreeStackSlot;
+ function->tempCount = _nextUnusedStackSlot;
}
protected:
- virtual void visitConst(V4IR::Const *) {}
- virtual void visitString(V4IR::String *) {}
- virtual void visitRegExp(V4IR::RegExp *) {}
- virtual void visitName(V4IR::Name *) {}
- virtual void visitTemp(V4IR::Temp *e) { renumber(e); }
- virtual void visitClosure(V4IR::Closure *) {}
- virtual void visitConvert(V4IR::Convert *e) { e->expr->accept(this); }
- virtual void visitUnop(V4IR::Unop *e) { e->expr->accept(this); }
- virtual void visitBinop(V4IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
- virtual void visitCall(V4IR::Call *e) {
+ virtual void visitConst(IR::Const *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
+ virtual void visitName(IR::Name *) {}
+ virtual void visitTemp(IR::Temp *e) { renumber(e); }
+ virtual void visitClosure(IR::Closure *) {}
+ virtual void visitConvert(IR::Convert *e) { e->expr->accept(this); }
+ virtual void visitUnop(IR::Unop *e) { e->expr->accept(this); }
+ virtual void visitBinop(IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
+ virtual void visitCall(IR::Call *e) {
e->base->accept(this);
- for (V4IR::ExprList *it = e->args; it; it = it->next)
+ for (IR::ExprList *it = e->args; it; it = it->next)
it->expr->accept(this);
}
- virtual void visitNew(V4IR::New *e) {
+ virtual void visitNew(IR::New *e) {
e->base->accept(this);
- for (V4IR::ExprList *it = e->args; it; it = it->next)
+ for (IR::ExprList *it = e->args; it; it = it->next)
it->expr->accept(this);
}
- virtual void visitSubscript(V4IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
- virtual void visitMember(V4IR::Member *e) { e->base->accept(this); }
- virtual void visitExp(V4IR::Exp *s) { s->expr->accept(this); }
- virtual void visitMove(V4IR::Move *s) { s->target->accept(this); s->source->accept(this); }
- virtual void visitJump(V4IR::Jump *) {}
- virtual void visitCJump(V4IR::CJump *s) { s->cond->accept(this); }
- virtual void visitRet(V4IR::Ret *s) { s->expr->accept(this); }
- virtual void visitPhi(V4IR::Phi *) { Q_UNREACHABLE(); }
+ virtual void visitSubscript(IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
+ virtual void visitMember(IR::Member *e) { e->base->accept(this); }
+ virtual void visitExp(IR::Exp *s) { s->expr->accept(this); }
+ virtual void visitMove(IR::Move *s) { s->target->accept(this); s->source->accept(this); }
+ virtual void visitJump(IR::Jump *) {}
+ virtual void visitCJump(IR::CJump *s) { s->cond->accept(this); }
+ virtual void visitRet(IR::Ret *s) { s->expr->accept(this); }
+ virtual void visitPhi(IR::Phi *) { Q_UNREACHABLE(); }
};
-} // namespace QQmlJS
+} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index deb1af51b4..2683278b12 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -55,8 +55,8 @@
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
-namespace V4IR {
+namespace QV4 {
+namespace IR {
QString typeName(Type t)
{
@@ -154,7 +154,7 @@ AluOp binaryOperator(int op)
}
}
-struct RemoveSharedExpressions: V4IR::StmtVisitor, V4IR::ExprVisitor
+struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
{
CloneExpr clone;
QSet<Expr *> subexpressions; // contains all the non-cloned subexpressions in the given function
@@ -162,7 +162,7 @@ struct RemoveSharedExpressions: V4IR::StmtVisitor, V4IR::ExprVisitor
RemoveSharedExpressions(): uniqueExpr(0) {}
- void operator()(V4IR::Function *function)
+ void operator()(IR::Function *function)
{
subexpressions.clear();
@@ -185,7 +185,7 @@ struct RemoveSharedExpressions: V4IR::StmtVisitor, V4IR::ExprVisitor
}
subexpressions.insert(expr);
- V4IR::Expr *e = expr;
+ IR::Expr *e = expr;
qSwap(uniqueExpr, e);
expr->accept(this);
qSwap(uniqueExpr, e);
@@ -219,7 +219,7 @@ struct RemoveSharedExpressions: V4IR::StmtVisitor, V4IR::ExprVisitor
s->expr = cleanup(s->expr);
}
- virtual void visitPhi(V4IR::Phi *) { Q_UNIMPLEMENTED(); }
+ virtual void visitPhi(IR::Phi *) { Q_UNIMPLEMENTED(); }
// expressions
virtual void visitConst(Const *) {}
@@ -248,14 +248,14 @@ struct RemoveSharedExpressions: V4IR::StmtVisitor, V4IR::ExprVisitor
virtual void visitCall(Call *e)
{
e->base = cleanup(e->base);
- for (V4IR::ExprList *it = e->args; it; it = it->next)
+ for (IR::ExprList *it = e->args; it; it = it->next)
it->expr = cleanup(it->expr);
}
virtual void visitNew(New *e)
{
e->base = cleanup(e->base);
- for (V4IR::ExprList *it = e->args; it; it = it->next)
+ for (IR::ExprList *it = e->args; it; it = it->next)
it->expr = cleanup(it->expr);
}
@@ -299,16 +299,16 @@ void Const::dump(QTextStream &out) const
if (type != UndefinedType && type != NullType)
out << dumpStart(this);
switch (type) {
- case QQmlJS::V4IR::UndefinedType:
+ case QV4::IR::UndefinedType:
out << "undefined";
break;
- case QQmlJS::V4IR::NullType:
+ case QV4::IR::NullType:
out << "null";
break;
- case QQmlJS::V4IR::BoolType:
+ case QV4::IR::BoolType:
out << (value ? "true" : "false");
break;
- case QQmlJS::V4IR::MissingType:
+ case QV4::IR::MissingType:
out << "missing";
break;
default:
@@ -417,35 +417,35 @@ static const char *builtin_to_string(Name::Builtin b)
return "builtin_unwind_exception";
case Name::builtin_push_catch_scope:
return "builtin_push_catch_scope";
- case V4IR::Name::builtin_foreach_iterator_object:
+ case IR::Name::builtin_foreach_iterator_object:
return "builtin_foreach_iterator_object";
- case V4IR::Name::builtin_foreach_next_property_name:
+ case IR::Name::builtin_foreach_next_property_name:
return "builtin_foreach_next_property_name";
- case V4IR::Name::builtin_push_with_scope:
+ case IR::Name::builtin_push_with_scope:
return "builtin_push_with_scope";
- case V4IR::Name::builtin_pop_scope:
+ case IR::Name::builtin_pop_scope:
return "builtin_pop_scope";
- case V4IR::Name::builtin_declare_vars:
+ case IR::Name::builtin_declare_vars:
return "builtin_declare_vars";
- case V4IR::Name::builtin_define_property:
+ case IR::Name::builtin_define_property:
return "builtin_define_property";
- case V4IR::Name::builtin_define_array:
+ case IR::Name::builtin_define_array:
return "builtin_define_array";
- case V4IR::Name::builtin_define_getter_setter:
+ case IR::Name::builtin_define_getter_setter:
return "builtin_define_getter_setter";
- case V4IR::Name::builtin_define_object_literal:
+ case IR::Name::builtin_define_object_literal:
return "builtin_define_object_literal";
- case V4IR::Name::builtin_setup_argument_object:
+ case IR::Name::builtin_setup_argument_object:
return "builtin_setup_argument_object";
- case V4IR::Name::builtin_convert_this_to_object:
+ case IR::Name::builtin_convert_this_to_object:
return "builtin_convert_this_to_object";
- case V4IR::Name::builtin_qml_id_array:
+ case IR::Name::builtin_qml_id_array:
return "builtin_qml_id_array";
- case V4IR::Name::builtin_qml_imported_scripts_object:
+ case IR::Name::builtin_qml_imported_scripts_object:
return "builtin_qml_imported_scripts_object";
- case V4IR::Name::builtin_qml_scope_object:
+ case IR::Name::builtin_qml_scope_object:
return "builtin_qml_scope_object";
- case V4IR::Name::builtin_qml_context_object:
+ case IR::Name::builtin_qml_context_object:
return "builtin_qml_context_object";
}
return "builtin_(###FIXME)";
@@ -663,8 +663,8 @@ Function::~Function()
{
// destroy the Stmt::Data blocks manually, because memory pool cleanup won't
// call the Stmt destructors.
- foreach (V4IR::BasicBlock *b, basicBlocks)
- foreach (V4IR::Stmt *s, b->statements)
+ foreach (IR::BasicBlock *b, basicBlocks)
+ foreach (IR::Stmt *s, b->statements)
s->destroyData();
qDeleteAll(basicBlocks);
@@ -740,7 +740,7 @@ Temp *BasicBlock::LOCAL(unsigned index, unsigned scope)
}
Expr *BasicBlock::CONST(Type type, double value)
-{
+{
Const *e = function->New<Const>();
if (type == NumberType) {
int ival = (int)value;
@@ -769,7 +769,7 @@ Expr *BasicBlock::REGEXP(const QString *value, int flags)
}
Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
-{
+{
Name *e = function->New<Name>();
e->init(function->newString(id), line, column);
return e;
@@ -805,7 +805,7 @@ Expr *BasicBlock::CONVERT(Expr *expr, Type type)
}
Expr *BasicBlock::UNOP(AluOp op, Expr *expr)
-{
+{
Unop *e = function->New<Unop>();
e->init(op, expr);
return e;
@@ -819,7 +819,7 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
}
Expr *BasicBlock::CALL(Expr *base, ExprList *args)
-{
+{
Call *e = function->New<Call>();
e->init(base, args);
int argc = 0;
@@ -851,7 +851,7 @@ Expr *BasicBlock::MEMBER(Expr *base, const QString *name, QQmlPropertyData *prop
}
Stmt *BasicBlock::EXP(Expr *expr)
-{
+{
if (isTerminated())
return 0;
@@ -862,7 +862,7 @@ Stmt *BasicBlock::EXP(Expr *expr)
}
Stmt *BasicBlock::MOVE(Expr *target, Expr *source)
-{
+{
if (isTerminated())
return 0;
@@ -872,7 +872,7 @@ Stmt *BasicBlock::MOVE(Expr *target, Expr *source)
return s;
}
-Stmt *BasicBlock::JUMP(BasicBlock *target)
+Stmt *BasicBlock::JUMP(BasicBlock *target)
{
if (isTerminated())
return 0;
@@ -890,7 +890,7 @@ Stmt *BasicBlock::JUMP(BasicBlock *target)
return s;
}
-Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
+Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
{
if (isTerminated())
return 0;
@@ -969,7 +969,7 @@ ExprList *CloneExpr::clone(ExprList *list)
if (! list)
return 0;
- ExprList *clonedList = block->function->New<V4IR::ExprList>();
+ ExprList *clonedList = block->function->New<IR::ExprList>();
clonedList->init(clone(list->expr), clone(list->next));
return clonedList;
}
@@ -1041,6 +1041,6 @@ void CloneExpr::visitMember(Member *e)
}
} // end of namespace IR
-} // end of namespace QQmlJS
+} // end of namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 46aea546ab..89b6da6278 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -81,7 +81,7 @@ namespace QV4 {
struct ExecutionContext;
}
-namespace QQmlJS {
+namespace QV4 {
inline bool isNegative(double d)
{
@@ -93,7 +93,7 @@ inline bool isNegative(double d)
}
-namespace V4IR {
+namespace IR {
struct BasicBlock;
struct Function;
@@ -176,7 +176,7 @@ enum AluOp {
LastAluOp = OpOr
};
AluOp binaryOperator(int op);
-const char *opname(V4IR::AluOp op);
+const char *opname(IR::AluOp op);
enum Type {
UnknownType = 0,
@@ -618,7 +618,7 @@ struct Stmt {
Data *d;
int id;
- AST::SourceLocation location;
+ QQmlJS::AST::SourceLocation location;
Stmt(): d(0), id(-1) {}
virtual ~Stmt()
@@ -740,7 +740,7 @@ struct Phi: Stmt {
};
struct Q_QML_EXPORT Module {
- MemoryPool pool;
+ QQmlJS::MemoryPool pool;
QVector<Function *> functions;
Function *rootFunction;
QString fileName;
@@ -764,7 +764,7 @@ typedef QHash<int, int> PropertyDependencyMap;
struct Function {
Module *module;
- MemoryPool *pool;
+ QQmlJS::MemoryPool *pool;
const QString *name;
QVector<BasicBlock *> basicBlocks;
int tempCount;
@@ -850,7 +850,7 @@ struct BasicBlock {
QBitArray liveOut;
int index;
bool isExceptionHandler;
- AST::SourceLocation nextLocation;
+ QQmlJS::AST::SourceLocation nextLocation;
BasicBlock(Function *function, BasicBlock *containingLoop, BasicBlock *catcher)
: function(function)
@@ -931,12 +931,12 @@ private:
bool _groupStart;
};
-class CloneExpr: protected V4IR::ExprVisitor
+class CloneExpr: protected IR::ExprVisitor
{
public:
- explicit CloneExpr(V4IR::BasicBlock *block = 0);
+ explicit CloneExpr(IR::BasicBlock *block = 0);
- void setBasicBlock(V4IR::BasicBlock *block);
+ void setBasicBlock(IR::BasicBlock *block);
template <typename _Expr>
_Expr *operator()(_Expr *expr)
@@ -985,7 +985,7 @@ public:
}
protected:
- V4IR::ExprList *clone(V4IR::ExprList *list);
+ IR::ExprList *clone(IR::ExprList *list);
virtual void visitConst(Const *);
virtual void visitString(String *);
@@ -1002,13 +1002,13 @@ protected:
virtual void visitMember(Member *);
private:
- V4IR::BasicBlock *block;
- V4IR::Expr *cloned;
+ IR::BasicBlock *block;
+ IR::Expr *cloned;
};
} // end of namespace IR
-} // end of namespace QQmlJS
+} // end of namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index f887006b50..e2c88c88f4 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -72,15 +72,15 @@
QT_USE_NAMESPACE
-using namespace QQmlJS;
-using namespace V4IR;
+using namespace QV4;
+using namespace IR;
namespace {
Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
#define qout *qout()
-void showMeTheCode(Function *function)
+void showMeTheCode(IR::Function *function)
{
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
if (showCode) {
@@ -244,22 +244,29 @@ public:
}
};
-inline Temp *unescapableTemp(Expr *e, bool variablesCanEscape)
+inline bool unescapableTemp(Temp *t, IR::Function *f)
{
- Temp *t = e->asTemp();
- if (!t)
- return 0;
-
switch (t->kind) {
- case Temp::VirtualRegister:
- return t;
+ case Temp::Formal:
+ case Temp::ScopedFormal:
+ case Temp::ScopedLocal:
+ return false;
case Temp::Local:
- return variablesCanEscape ? 0 : t;
+ return !f->variablesCanEscape();
default:
- return 0;
+ return true;
}
}
+inline Temp *unescapableTemp(Expr *e, IR::Function *f)
+{
+ Temp *t = e->asTemp();
+ if (!t)
+ return 0;
+
+ return unescapableTemp(t, f) ? t : 0;
+}
+
class BasicBlockSet
{
typedef std::vector<int> Numbers;
@@ -773,28 +780,16 @@ class VariableCollector: public StmtVisitor, ExprVisitor {
QSet<Temp> killed;
BasicBlock *currentBB;
- const bool variablesCanEscape;
+ IR::Function *function;
bool isCollectable(Temp *t) const
{
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- return false;
- case Temp::Local:
- return !variablesCanEscape;
- case Temp::VirtualRegister:
- return true;
- default:
- // PhysicalRegister and StackSlot can only get inserted later.
- Q_ASSERT(!"Invalid temp kind!");
- return false;
- }
+ Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
+ return unescapableTemp(t, function);
}
public:
- VariableCollector(Function *function)
- : variablesCanEscape(function->variablesCanEscape())
+ VariableCollector(IR::Function *function)
+ : function(function)
{
_defsites.reserve(function->tempCount);
@@ -842,8 +837,8 @@ protected:
virtual void visitConvert(Convert *e) { e->expr->accept(this); };
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitClosure(Closure *) {}
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -897,7 +892,7 @@ protected:
}
};
-void insertPhiNode(const Temp &a, BasicBlock *y, Function *f) {
+void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
#if defined(SHOW_SSA)
qout << "-> inserted phi node for variable ";
a.dump(qout);
@@ -988,8 +983,7 @@ void insertPhiNode(const Temp &a, BasicBlock *y, Function *f) {
// mapping[t] = c
class VariableRenamer: public StmtVisitor, public ExprVisitor
{
- Function *function;
- const bool variablesCanEscape;
+ IR::Function *function;
unsigned tempCount;
typedef QHash<unsigned, int> Mapping; // maps from existing/old temp number to the new and unique temp number.
@@ -1000,19 +994,8 @@ class VariableRenamer: public StmtVisitor, public ExprVisitor
bool isRenamable(Temp *t) const
{
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- return false;
- case Temp::Local:
- return !variablesCanEscape;
- case Temp::VirtualRegister:
- return true;
- default:
- Q_ASSERT(!"Invalid temp kind!");
- return false;
- }
+ Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
+ return unescapableTemp(t, function);
}
struct TodoAction {
@@ -1056,9 +1039,8 @@ class VariableRenamer: public StmtVisitor, public ExprVisitor
QVector<TodoAction> todo;
public:
- VariableRenamer(Function *f)
+ VariableRenamer(IR::Function *f)
: function(f)
- , variablesCanEscape(f->variablesCanEscape())
, tempCount(0)
, processed(f->basicBlocks)
{
@@ -1234,8 +1216,8 @@ protected:
virtual void visitRet(Ret *s) { s->expr->accept(this); }
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitClosure(Closure *) {}
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -1262,7 +1244,7 @@ protected:
}
};
-void convertToSSA(Function *function, const DominatorTree &df)
+void convertToSSA(IR::Function *function, const DominatorTree &df)
{
#ifdef SHOW_SSA
qout << "Converting function ";
@@ -1329,7 +1311,7 @@ public:
};
private:
- const bool _variablesCanEscape;
+ IR::Function *function;
QHash<UntypedTemp, DefUse> _defUses;
QHash<Stmt *, QList<Temp> > _usesPerStatement;
@@ -1337,19 +1319,8 @@ private:
Stmt *_stmt;
bool isCollectible(Temp *t) const {
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- return false;
- case Temp::Local:
- return !_variablesCanEscape;
- case Temp::VirtualRegister:
- return true;
- default:
- Q_UNREACHABLE();
- return false;
- }
+ Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
+ return unescapableTemp(t, function);
}
void addUse(Temp *t) {
@@ -1373,8 +1344,8 @@ private:
}
public:
- DefUsesCalculator(Function *function)
- : _variablesCanEscape(function->variablesCanEscape())
+ DefUsesCalculator(IR::Function *function)
+ : function(function)
{
foreach (BasicBlock *bb, function->basicBlocks) {
_block = bb;
@@ -1441,7 +1412,8 @@ public:
{
QVector<Stmt*> defStmts;
foreach (const Temp &usedVar, usedVars(s)) {
- defStmts += defStmt(usedVar);
+ if (Stmt *ds = defStmt(usedVar))
+ defStmts += ds;
removeUse(s, usedVar);
}
if (Move *m = s->asMove()) {
@@ -1492,8 +1464,8 @@ protected:
virtual void visitTemp(Temp *e) { addUse(e); }
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
@@ -1562,18 +1534,139 @@ void cleanupPhis(DefUsesCalculator &defUses)
}
}
+class StatementWorklist
+{
+ QVector<Stmt *> worklist;
+ QBitArray inWorklist;
+ QHash<Stmt*,Stmt**> ref;
+
+public:
+ StatementWorklist(IR::Function *function)
+ {
+ QVector<Stmt *> w;
+ int stmtCount = 0;
+
+ // Put in all statements, and number them on the fly. The numbering is used to index the
+ // bit array.
+ foreach (BasicBlock *bb, function->basicBlocks) {
+ for (int i = 0, ei = bb->statements.size(); i != ei; ++i) {
+ Stmt **s = &bb->statements[i];
+ (*s)->id = stmtCount++;
+ w.append(*s);
+ ref.insert(*s, s);
+ }
+ }
+
+ // For QVector efficiency reasons, we process statements from the back. However, it is more
+ // effective to process the statements in ascending order. So we need to invert the
+ // order.
+ worklist.reserve(w.size());
+ for (int i = w.size() - 1; i >= 0; --i)
+ worklist.append(w.at(i));
+
+ inWorklist = QBitArray(stmtCount, true);
+ }
+
+ // This will clear the entry for the statement in the basic block. After processing all
+ // statements, the cleanup method needs to be run to remove all null-pointers.
+ void clear(Stmt *stmt)
+ {
+ Q_ASSERT(!inWorklist.at(stmt->id));
+ *ref[stmt] = 0;
+ }
+
+ void replace(Stmt *oldStmt, Stmt *newStmt)
+ {
+ Q_ASSERT(oldStmt);
+ Q_ASSERT(newStmt);
+
+ if (newStmt->id == -1)
+ newStmt->id = oldStmt->id;
+ *ref[oldStmt] = newStmt;
+ }
+
+ void cleanup(IR::Function *function)
+ {
+ foreach (BasicBlock *bb, function->basicBlocks) {
+ for (int i = 0; i < bb->statements.size();) {
+ if (bb->statements[i]) {
+ bb->statements[i]->id = -1;
+ ++i;
+ } else {
+ bb->statements.remove(i);
+ }
+ }
+ }
+ }
+
+ StatementWorklist &operator+=(const QVector<Stmt *> &stmts)
+ {
+ foreach (Stmt *s, stmts)
+ this->operator+=(s);
+
+ return *this;
+ }
+
+
+ StatementWorklist &operator+=(Stmt *s)
+ {
+ if (!s)
+ return *this;
+
+ Q_ASSERT(s->id >= 0);
+ Q_ASSERT(s->id < inWorklist.size());
+
+ if (!inWorklist.at(s->id)) {
+ worklist.append(s);
+ inWorklist.setBit(s->id);
+ }
+
+ return *this;
+ }
+
+ StatementWorklist &operator-=(Stmt *s)
+ {
+ Q_ASSERT(s->id >= 0);
+ Q_ASSERT(s->id < inWorklist.size());
+
+ if (inWorklist.at(s->id)) {
+ worklist.remove(worklist.indexOf(s));
+ inWorklist.clearBit(s->id);
+ }
+
+ return *this;
+ }
+
+ bool isEmpty() const
+ {
+ return worklist.isEmpty();
+ }
+
+ Stmt *takeOne()
+ {
+ if (isEmpty())
+ return 0;
+
+ Stmt *s = worklist.last();
+ Q_ASSERT(s->id < inWorklist.size());
+ worklist.removeLast();
+ inWorklist.clearBit(s->id);
+ return s;
+ }
+};
+
class EliminateDeadCode: public ExprVisitor {
DefUsesCalculator &_defUses;
- QVector<Stmt *> _worklist;
- const bool _variablesCanEscape;
+ StatementWorklist &_worklist;
+ IR::Function *function;
bool _sideEffect;
QVector<Temp *> _collectedTemps;
public:
- EliminateDeadCode(DefUsesCalculator &defUses, QVector<Stmt *> worklist, bool variablesCanEscape)
+ EliminateDeadCode(DefUsesCalculator &defUses, StatementWorklist &worklist, IR::Function *function)
: _defUses(defUses)
, _worklist(worklist)
- , _variablesCanEscape(variablesCanEscape)
+ , function(function)
{
_collectedTemps.reserve(8);
}
@@ -1606,22 +1699,13 @@ private:
bool isCollectable(Temp *t) const
{
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- return false;
- case Temp::Local:
- return !_variablesCanEscape;
- default:
- return true;
- }
+ return unescapableTemp(t, function);
}
protected:
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *e)
{
@@ -1757,8 +1841,8 @@ public:
protected:
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *e) {
if (theTemp == UntypedTemp(*e)) {
@@ -1808,7 +1892,7 @@ protected:
class TypeInference: public StmtVisitor, public ExprVisitor {
QQmlEnginePrivate *qmlEngine;
- bool _variablesCanEscape;
+ IR::Function *function;
const DefUsesCalculator &_defUses;
QHash<Temp, DiscoveredType> _tempTypes;
QSet<Stmt *> _worklist;
@@ -1828,8 +1912,8 @@ public:
, _ty(UnknownType)
{}
- void run(Function *function) {
- _variablesCanEscape = function->variablesCanEscape();
+ void run(IR::Function *f) {
+ function = f;
// TODO: the worklist handling looks a bit inefficient... check if there is something better
_worklist.clear();
@@ -1890,19 +1974,10 @@ private:
}
bool isAlwaysVar(Temp *t) {
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- t->type = VarType;
- return true;
- case Temp::Local:
- if (_variablesCanEscape)
- t->type = VarType;
- return _variablesCanEscape;
- default:
+ if (unescapableTemp(t, function))
return false;
- }
+ t->type = VarType;
+ return true;
}
void setType(Expr *e, DiscoveredType ty) {
@@ -1942,8 +2017,8 @@ protected:
} else
_ty = TypingResult(e->type);
}
- virtual void visitString(String *) { _ty = TypingResult(StringType); }
- virtual void visitRegExp(RegExp *) { _ty = TypingResult(VarType); }
+ virtual void visitString(IR::String *) { _ty = TypingResult(StringType); }
+ virtual void visitRegExp(IR::RegExp *) { _ty = TypingResult(VarType); }
virtual void visitName(Name *) { _ty = TypingResult(VarType); }
virtual void visitTemp(Temp *e) {
if (isAlwaysVar(e))
@@ -2126,19 +2201,14 @@ protected:
class ReverseInference
{
const DefUsesCalculator &_defUses;
- bool _variablesCanExcape;
public:
ReverseInference(const DefUsesCalculator &defUses)
: _defUses(defUses)
{}
- void run(Function *f)
+ void run(IR::Function *f)
{
- _variablesCanExcape = f->variablesCanEscape();
-
- QTextStream os(stderr, QIODevice::WriteOnly);
-
QVector<UntypedTemp> knownOk;
QList<UntypedTemp> candidates = _defUses.defsUntyped();
while (!candidates.isEmpty()) {
@@ -2181,13 +2251,13 @@ public:
default:
continue;
}
- if (Temp *lt = unescapableTemp(b->left, _variablesCanExcape))
+ if (Temp *lt = unescapableTemp(b->left, f))
candidates.append(*lt);
- if (Temp *rt = unescapableTemp(b->right, _variablesCanExcape))
+ if (Temp *rt = unescapableTemp(b->right, f))
candidates.append(*rt);
} else if (Unop *u = m->source->asUnop()) {
if (u->op == OpCompl || u->op == OpUPlus) {
- if (Temp *t = unescapableTemp(u->expr, _variablesCanExcape))
+ if (Temp *t = unescapableTemp(u->expr, f))
candidates.append(*t);
}
} else {
@@ -2202,12 +2272,14 @@ public:
propagator.run(t, SInt32Type);
if (Stmt *defStmt = _defUses.defStmt(t)) {
if (Move *m = defStmt->asMove()) {
- if (Convert *c = m->source->asConvert())
+ if (Convert *c = m->source->asConvert()) {
c->type = SInt32Type;
- else if (Unop *u = m->source->asUnop())
- u->type = SInt32Type;
- else if (Binop *b = m->source->asBinop())
+ } else if (Unop *u = m->source->asUnop()) {
+ if (u->op != OpUMinus)
+ u->type = SInt32Type;
+ } else if (Binop *b = m->source->asBinop()) {
b->type = SInt32Type;
+ }
}
}
}
@@ -2289,7 +2361,7 @@ void convertConst(Const *c, Type targetType)
class TypePropagation: public StmtVisitor, public ExprVisitor {
DefUsesCalculator &_defUses;
Type _ty;
- Function *_f;
+ IR::Function *_f;
bool run(Expr *&e, Type requestedType = UnknownType, bool insertConversion = true) {
qSwap(_ty, requestedType);
@@ -2340,7 +2412,7 @@ class TypePropagation: public StmtVisitor, public ExprVisitor {
public:
TypePropagation(DefUsesCalculator &defUses) : _defUses(defUses), _ty(UnknownType) {}
- void run(Function *f) {
+ void run(IR::Function *f) {
_f = f;
foreach (BasicBlock *bb, f->basicBlocks) {
_conversions.clear();
@@ -2351,7 +2423,7 @@ public:
}
foreach (const Conversion &conversion, _conversions) {
- V4IR::Move *move = conversion.stmt->asMove();
+ IR::Move *move = conversion.stmt->asMove();
// Note: isel only supports move into member when source is a temp, so convert
// is not a supported source.
@@ -2384,6 +2456,29 @@ public:
}
*conversion.expr = source;
+ } else if (Unop *u = (*conversion.expr)->asUnop()) {
+ // convert:
+ // int32{%2} = double{-double{%1}};
+ // to:
+ // double{%3} = double{-double{%1}};
+ // int32{%2} = int32{convert(double{%3})};
+ Temp *tmp = bb->TEMP(bb->newTemp());
+ tmp->type = u->type;
+ Move *extraMove = f->New<Move>();
+ extraMove->init(tmp, u);
+ _defUses.addTemp(tmp, extraMove, bb);
+
+ if (Temp *unopOperand = u->expr->asTemp()) {
+ _defUses.addUse(*unopOperand, extraMove);
+ _defUses.removeUse(move, *unopOperand);
+ }
+
+ int idx = bb->statements.indexOf(conversion.stmt);
+ Q_ASSERT(idx != -1);
+ bb->statements.insert(idx, extraMove);
+
+ *conversion.expr = bb->CONVERT(tmp, conversion.targetType);
+ _defUses.addUse(*tmp, move);
} else {
Q_UNREACHABLE();
}
@@ -2402,8 +2497,8 @@ protected:
}
}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *) {}
virtual void visitClosure(Closure *) {}
@@ -2510,7 +2605,7 @@ protected:
}
};
-void splitCriticalEdges(Function *f, DominatorTree &df)
+void splitCriticalEdges(IR::Function *f, DominatorTree &df)
{
for (int i = 0, ei = f->basicBlocks.size(); i != ei; ++i) {
BasicBlock *bb = f->basicBlocks[i];
@@ -2592,7 +2687,7 @@ void splitCriticalEdges(Function *f, DominatorTree &df)
// the same reason.
class BlockScheduler
{
- Function *function;
+ IR::Function *function;
const DominatorTree &dominatorTree;
struct WorkForGroup
@@ -2698,7 +2793,7 @@ class BlockScheduler
}
public:
- BlockScheduler(Function *function, const DominatorTree &dominatorTree)
+ BlockScheduler(IR::Function *function, const DominatorTree &dominatorTree)
: function(function)
, dominatorTree(dominatorTree)
, emitted(function->basicBlocks)
@@ -2737,7 +2832,7 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
}
#endif
-void cleanupBasicBlocks(Function *function, bool renumber)
+void cleanupBasicBlocks(IR::Function *function, bool renumber)
{
showMeTheCode(function);
@@ -2826,7 +2921,7 @@ inline Const *isConstPhi(Phi *phi)
return 0;
}
-static Expr *clone(Expr *e, Function *function) {
+static Expr *clone(Expr *e, IR::Function *function) {
if (Temp *t = e->asTemp()) {
return CloneExpr::cloneTemp(t, function);
} else if (Const *c = e->asConst()) {
@@ -2842,12 +2937,12 @@ static Expr *clone(Expr *e, Function *function) {
class ExprReplacer: public StmtVisitor, public ExprVisitor
{
DefUsesCalculator &_defUses;
- Function* _function;
+ IR::Function* _function;
Temp *_toReplace;
Expr *_replacement;
public:
- ExprReplacer(DefUsesCalculator &defUses, Function *function)
+ ExprReplacer(DefUsesCalculator &defUses, IR::Function *function)
: _defUses(defUses)
, _function(function)
, _toReplace(0)
@@ -2881,8 +2976,8 @@ public:
protected:
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *) {}
virtual void visitClosure(Closure *) {}
@@ -2950,7 +3045,7 @@ namespace {
/// and removes unreachable staements from the worklist, so that optimiseSSA won't consider them
/// anymore.
/// Important: this assumes that there are no critical edges in the control-flow graph!
-void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector<Stmt *> &W,
+void purgeBB(BasicBlock *bb, IR::Function *func, DefUsesCalculator &defUses, StatementWorklist &W,
DominatorTree &df)
{
// TODO: change this to mark the block as deleted, but leave it alone so that other references
@@ -3017,9 +3112,8 @@ void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector
if (!s)
continue;
- W << defUses.removeDefUses(s);
- for (int idx = W.indexOf(s); idx != -1; idx = W.indexOf(s))
- W.remove(idx);
+ W += defUses.removeDefUses(s);
+ W -= s;
// clean-up the statement's data
s->destroyData();
@@ -3092,27 +3186,13 @@ bool tryOptimizingComparison(Expr *&expr)
}
} // anonymous namespace
-void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &df)
+void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTree &df)
{
- const bool variablesCanEscape = function->variablesCanEscape();
-
- QHash<Stmt*,Stmt**> ref;
- QVector<Stmt *> W;
- foreach (BasicBlock *bb, function->basicBlocks) {
- for (int i = 0, ei = bb->statements.size(); i != ei; ++i) {
- Stmt **s = &bb->statements[i];
- if ((*s)->asJump())
- continue; // nothing do do there
- W.append(*s);
- ref.insert(*s, s);
- }
- }
-
+ StatementWorklist W(function);
ExprReplacer replaceUses(defUses, function);
while (!W.isEmpty()) {
- Stmt *s = W.last();
- W.removeLast();
+ Stmt *s = W.takeOne();
if (!s)
continue;
@@ -3121,7 +3201,7 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
if (Const *c = isConstPhi(phi)) {
W += replaceUses(phi->targetTemp, c);
defUses.removeDef(*phi->targetTemp);
- *ref[s] = 0;
+ W.clear(s);
continue;
}
@@ -3137,7 +3217,19 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
defUses.addUses(*t2, QList<Stmt*>::fromVector(newT2Uses));
}
defUses.removeDef(*t);
- *ref[s] = 0;
+ W.clear(s);
+ continue;
+ }
+
+ // dead code elimination:
+ if (defUses.useCount(*phi->targetTemp) == 0) {
+ foreach (Expr *in, phi->d->incoming) {
+ if (Temp *t = in->asTemp())
+ W += defUses.defStmt(*t);
+ }
+
+ defUses.removeDef(*phi->targetTemp);
+ W.clear(s);
continue;
}
} else if (Move *m = s->asMove()) {
@@ -3156,12 +3248,12 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
}
}
- if (Temp *targetTemp = unescapableTemp(m->target, variablesCanEscape)) {
+ if (Temp *targetTemp = unescapableTemp(m->target, function)) {
// dead code elimination:
if (defUses.useCount(*targetTemp) == 0) {
- EliminateDeadCode(defUses, W, variablesCanEscape).run(m->source, s);
+ EliminateDeadCode(defUses, W, function).run(m->source, s);
if (!m->source)
- *ref[s] = 0;
+ W.clear(s);
continue;
}
@@ -3172,7 +3264,7 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
// optimization passes have to be changed to cope with them.
W += replaceUses(targetTemp, sourceConst);
defUses.removeDef(*targetTemp);
- *ref[s] = 0;
+ W.clear(s);
}
continue;
}
@@ -3183,7 +3275,7 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
c->init(SInt32Type, enumValue);
W += replaceUses(targetTemp, c);
defUses.removeDef(*targetTemp);
- *ref[s] = 0;
+ W.clear(s);
defUses.removeUse(s, *member->base->asTemp());
continue;
} else if (member->attachedPropertiesIdOrEnumValue != 0 && member->property && member->base->asTemp()) {
@@ -3198,13 +3290,13 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
}
// copy propagation:
- if (Temp *sourceTemp = unescapableTemp(m->source, variablesCanEscape)) {
+ if (Temp *sourceTemp = unescapableTemp(m->source, function)) {
QVector<Stmt *> newT2Uses = replaceUses(targetTemp, sourceTemp);
W += newT2Uses;
defUses.removeUse(s, *sourceTemp);
defUses.addUses(*sourceTemp, QList<Stmt*>::fromVector(newT2Uses));
defUses.removeDef(*targetTemp);
- *ref[s] = 0;
+ W.clear(s);
continue;
}
@@ -3275,16 +3367,16 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
Expr *casted = 0;
switch (binop->op) {
case OpBitAnd:
- if (leftConst && !rightConst && leftConst->value == 0xffffffff)
- casted = rightConst;
- else if (!leftConst && rightConst && rightConst->value == 0xffffffff)
- casted = leftConst;
+ if (leftConst && !rightConst && QV4::Primitive::toUInt32(leftConst->value) == 0xffffffff)
+ casted = binop->right;
+ else if (!leftConst && rightConst && QV4::Primitive::toUInt32(rightConst->value) == 0xffffffff)
+ casted = binop->left;
break;
case OpBitOr:
- if (leftConst && !rightConst && leftConst->value == 0)
- casted = rightConst;
- else if (!leftConst && rightConst && rightConst->value == 0)
- casted = leftConst;
+ if (leftConst && !rightConst && QV4::Primitive::toInt32(leftConst->value) == 0)
+ casted = binop->right;
+ else if (!leftConst && rightConst && QV4::Primitive::toUInt32(rightConst->value) == 0)
+ casted = binop->left;
break;
default:
break;
@@ -3296,6 +3388,18 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
continue;
}
}
+ if (rightConst) { // mask right hand side of shift operations
+ switch (binop->op) {
+ case OpLShift:
+ case OpRShift:
+ case OpURShift:
+ rightConst->value = QV4::Primitive::toInt32(rightConst->value) & 0x1f;
+ rightConst->type = SInt32Type;
+ break;
+ default:
+ break;
+ }
+ }
// TODO: More constant binary expression evaluation
// TODO: If the result of the move is only used in one single cjump, then
@@ -3363,7 +3467,7 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
jump->target = cjump->iffalse;
purgeBB(cjump->iftrue, function, defUses, W, df);
}
- *ref[s] = jump;
+ W.replace(s, jump);
continue;
} else if (cjump->cond->asBinop()) {
@@ -3377,24 +3481,17 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses, DominatorTree &
}
}
- foreach (BasicBlock *bb, function->basicBlocks) {
- for (int i = 0; i < bb->statements.size();) {
- if (bb->statements[i])
- ++i;
- else
- bb->statements.remove(i);
- }
- }
+ W.cleanup(function);
}
class InputOutputCollector: protected StmtVisitor, protected ExprVisitor {
- const bool variablesCanEscape;
+ IR::Function *function;
public:
QList<Temp> inputs;
QList<Temp> outputs;
- InputOutputCollector(bool variablesCanEscape): variablesCanEscape(variablesCanEscape) {}
+ InputOutputCollector(IR::Function *f): function(f) {}
void collect(Stmt *s) {
inputs.clear();
@@ -3404,23 +3501,12 @@ public:
protected:
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *e) {
- switch (e->kind) {
- case Temp::Local:
- if (!variablesCanEscape)
- inputs.append(*e);
- break;
-
- case Temp::VirtualRegister:
+ if (unescapableTemp(e, function))
inputs.append(*e);
- break;
-
- default:
- break;
- }
}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
@@ -3442,7 +3528,7 @@ protected:
virtual void visitMove(Move *s) {
s->source->accept(this);
if (Temp *t = s->target->asTemp()) {
- if ((t->kind == Temp::Local && !variablesCanEscape) || t->kind == Temp::VirtualRegister)
+ if (unescapableTemp(t, function))
outputs.append(*t);
else
s->target->accept(this);
@@ -3478,7 +3564,7 @@ class LifeRanges {
QVector<LifeTimeInterval> _sortedRanges;
public:
- LifeRanges(Function *function, const QHash<BasicBlock *, BasicBlock *> &startEndLoops)
+ LifeRanges(IR::Function *function, const QHash<BasicBlock *, BasicBlock *> &startEndLoops)
{
int id = 0;
foreach (BasicBlock *bb, function->basicBlocks) {
@@ -3492,7 +3578,7 @@ public:
for (int i = function->basicBlocks.size() - 1; i >= 0; --i) {
BasicBlock *bb = function->basicBlocks[i];
- buildIntervals(bb, startEndLoops.value(bb, 0), function->variablesCanEscape());
+ buildIntervals(bb, startEndLoops.value(bb, 0), function);
}
_sortedRanges.reserve(_intervals.size());
@@ -3528,7 +3614,7 @@ public:
}
private:
- void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd, bool variablesCanEscape)
+ void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd, IR::Function *function)
{
LiveRegs live;
foreach (BasicBlock *successor, bb->out) {
@@ -3549,11 +3635,17 @@ private:
foreach (const Temp &opd, live)
_intervals[opd].addRange(bb->statements.first()->id, bb->statements.last()->id);
- InputOutputCollector collector(variablesCanEscape);
+ InputOutputCollector collector(function);
for (int i = bb->statements.size() - 1; i >= 0; --i) {
Stmt *s = bb->statements[i];
if (Phi *phi = s->asPhi()) {
- live.remove(*phi->targetTemp);
+ LiveRegs::iterator it = live.find(*phi->targetTemp);
+ if (it == live.end()) {
+ // a phi node target that is only defined, but never used
+ _intervals[*phi->targetTemp].setFrom(s);
+ } else {
+ live.erase(it);
+ }
continue;
}
collector.collect(s);
@@ -3907,7 +3999,7 @@ QSet<Jump *> Optimizer::calculateOptionalJumps()
return optional;
}
-void Optimizer::showMeTheCode(Function *function)
+void Optimizer::showMeTheCode(IR::Function *function)
{
::showMeTheCode(function);
}
@@ -3992,15 +4084,21 @@ void MoveMapping::order()
qSwap(_moves, output);
}
-void MoveMapping::insertMoves(BasicBlock *bb, Function *function, bool atEnd) const
+QList<IR::Move *> MoveMapping::insertMoves(BasicBlock *bb, IR::Function *function, bool atEnd) const
{
+ QList<IR::Move *> newMoves;
+ newMoves.reserve(_moves.size());
+
int insertionPoint = atEnd ? bb->statements.size() - 1 : 0;
foreach (const Move &m, _moves) {
- V4IR::Move *move = function->New<V4IR::Move>();
- move->init(m.to, m.from);
+ IR::Move *move = function->New<IR::Move>();
+ move->init(clone(m.to, function), clone(m.from, function));
move->swap = m.needsSwap;
bb->statements.insert(insertionPoint++, move);
+ newMoves.append(move);
}
+
+ return newMoves;
}
void MoveMapping::dump() const
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 2ec81b9577..0f04138b41 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -48,8 +48,8 @@ QT_BEGIN_NAMESPACE
class QTextStream;
class QQmlEnginePrivate;
-namespace QQmlJS {
-namespace V4IR {
+namespace QV4 {
+namespace IR {
class Q_AUTOTEST_EXPORT LifeTimeInterval {
public:
@@ -88,7 +88,7 @@ public:
void setTemp(const Temp &temp) { this->_temp = temp; }
Temp temp() const { return _temp; }
- bool isFP() const { return _temp.type == V4IR::DoubleType; }
+ bool isFP() const { return _temp.type == IR::DoubleType; }
void setFrom(Stmt *from);
void addRange(int from, int to);
@@ -155,7 +155,7 @@ public:
QVector<LifeTimeInterval> lifeRanges() const;
- QSet<V4IR::Jump *> calculateOptionalJumps();
+ QSet<IR::Jump *> calculateOptionalJumps();
static void showMeTheCode(Function *function);
@@ -188,7 +188,7 @@ class MoveMapping
public:
void add(Expr *from, Temp *to);
void order();
- void insertMoves(BasicBlock *bb, Function *function, bool atEnd) const;
+ QList<IR::Move *> insertMoves(BasicBlock *bb, Function *function, bool atEnd) const;
void dump() const;
@@ -198,12 +198,12 @@ private:
QList<Move> &swaps) const;
};
-} // V4IR namespace
-} // QQmlJS namespace
+} // IR namespace
+} // QV4 namespace
-Q_DECLARE_TYPEINFO(QQmlJS::V4IR::LifeTimeInterval, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(QQmlJS::V4IR::LifeTimeInterval::Range, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QV4::IR::LifeTimeInterval, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QV4::IR::LifeTimeInterval::Range, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index c10f43c8c9..27b72a320c 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -3,10 +3,15 @@ SOURCES += \
$$PWD/qqmlprofilerservice.cpp \
$$PWD/qqmldebugserver.cpp \
$$PWD/qqmlinspectorservice.cpp \
- $$PWD/qv8profilerservice.cpp \
+ $$PWD/qv4profilerservice.cpp \
$$PWD/qqmlenginedebugservice.cpp \
$$PWD/qdebugmessageservice.cpp \
- $$PWD/qv4debugservice.cpp
+ $$PWD/qv4debugservice.cpp \
+ $$PWD/qqmlconfigurabledebugservice.cpp \
+ $$PWD/qqmlenginecontrolservice.cpp \
+ $$PWD/qqmlabstractprofileradapter.cpp \
+ $$PWD/qv4profileradapter.cpp \
+ $$PWD/qqmlprofiler.cpp
HEADERS += \
$$PWD/qqmldebugservice_p.h \
@@ -17,8 +22,15 @@ HEADERS += \
$$PWD/qqmldebugstatesdelegate_p.h \
$$PWD/qqmlinspectorservice_p.h \
$$PWD/qqmlinspectorinterface_p.h \
- $$PWD/qv8profilerservice_p.h \
+ $$PWD/qv4profilerservice_p.h \
$$PWD/qqmlenginedebugservice_p.h \
$$PWD/qqmldebug.h \
$$PWD/qdebugmessageservice_p.h \
- $$PWD/qv4debugservice_p.h
+ $$PWD/qv4debugservice_p.h \
+ $$PWD/qqmlconfigurabledebugservice_p.h \
+ $$PWD/qqmlconfigurabledebugservice_p_p.h \
+ $$PWD/qqmlenginecontrolservice_p.h \
+ $$PWD/qqmlprofilerdefinitions_p.h \
+ $$PWD/qqmlabstractprofileradapter_p.h \
+ $$PWD/qv4profileradapter_p.h \
+ $$PWD/qqmlprofiler_p.h
diff --git a/src/qml/debugger/qqmlabstractprofileradapter.cpp b/src/qml/debugger/qqmlabstractprofileradapter.cpp
new file mode 100644
index 0000000000..d7168428f6
--- /dev/null
+++ b/src/qml/debugger/qqmlabstractprofileradapter.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlabstractprofileradapter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ * \class QQmlAbstractProfilerAdapter
+ * Abstract base class for all adapters between profilers and the QQmlProfilerService. Adapters have
+ * to retrieve profiler-specific data and convert it to the format sent over the wire. Adapters must
+ * live in the QDebugServer thread but the actual profilers can live in different threads. The
+ * recommended way to deal with this is passing the profiling data through a signal/slot connection.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::dataRequested()
+ * Signals that data has been requested by the \c QQmlProfilerService. This signal should be
+ * connected to a slot in the profiler and the profiler should then transfer its currently available
+ * profiling data to the adapter as soon as possible.
+ */
+
+/*!
+ * \fn qint64 QQmlAbstractProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+ * Append the messages up to the timestamp \a until, chronologically sorted, to \a messages. Keep
+ * track of the messages already sent and with each subsequent call to this method start with the
+ * first one not yet sent. Messages that have been sent can be deleted. When new data from the
+ * profiler arrives the information about the last sent message must be reset. Return the timestamp
+ * of the next message after \a until or \c -1 if there is no such message.
+ * The profiler service keeps a list of adapters, sorted by time of next message and keeps querying
+ * the first one to send messages up to the time of the second one. Like that we get chronologically
+ * sorted messages and can occasionally post the messages to exploit parallelism and save memory.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::startProfiling()
+ * Emits either \c profilingEnabled() or \c profilingEnabledWhileWaiting(), depending on \c waiting.
+ * If the profiler's thread is waiting for an initial start signal we can emit the signal over a
+ * \c Qt::DirectConnection to avoid the delay of the event loop.
+ */
+void QQmlAbstractProfilerAdapter::startProfiling()
+{
+ if (waiting)
+ emit profilingEnabledWhileWaiting();
+ else
+ emit profilingEnabled();
+ running = true;
+}
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::stopProfiling()
+ * Emits either \c profilingDisabled() or \c profilingDisabledWhileWaiting(), depending on
+ * \c waiting. If the profiler's thread is waiting for an initial start signal we can emit the
+ * signal over a \c Qt::DirectConnection to avoid the delay of the event loop. This should trigger
+ * the profiler to report its collected data and subsequently delete it.
+ */
+void QQmlAbstractProfilerAdapter::stopProfiling() {
+ if (waiting)
+ emit profilingDisabledWhileWaiting();
+ else
+ emit profilingDisabled();
+ running = false;
+}
+
+/*!
+ * \fn bool QQmlAbstractProfilerAdapter::isRunning()
+ * Returns if the profiler is currently running. The profiler is considered to be running after
+ * \c startProfiling() has been called until \c stopProfiling() is called. That is independent of
+ * \c waiting. The profiler may be running and waiting at the same time.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::profilingDisabled()
+ * This signal is emitted if \c stopProfiling() is called while the profiler is not considered to
+ * be waiting. The profiler is expected to handle the signal asynchronously.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting()
+ * This signal is emitted if \c stopProfiling() is called while the profiler is considered to be
+ * waiting. In many cases this signal can be connected with a \c Qt::DirectConnection.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::profilingEnabled()
+ * This signal is emitted if \c startProfiling() is called while the profiler is not considered to
+ * be waiting. The profiler is expected to handle the signal asynchronously.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting()
+ * This signal is emitted if \c startProfiling() is called while the profiler is considered to be
+ * waiting. In many cases this signal can be connected with a \c Qt::DirectConnection. By starting
+ * the profiler synchronously when the QML engine starts instead of waiting for the first iteration
+ * of the event loop the engine startup can be profiled.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::referenceTimeKnown(const QElapsedTimer &timer)
+ * This signal is used to synchronize the profiler's timer to the QQmlProfilerservice's. The
+ * profiler is expected to save \a timer and use it for timestamps on its data.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::synchronize(const QElapsedTimer &timer)
+ * Synchronize the profiler to \a timer. This emits \c referenceTimeKnown().
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::reportData()
+ * Make the profiler report its current data without stopping the collection. The same (and
+ * additional) data can later be requested again with \c stopProfiling() or \c reportData().
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::startWaiting()
+ * Consider the profiler to be waiting from now on. While the profiler is waiting it can be directly
+ * accessed even if it is in a different thread. This method should only be called if it is actually
+ * safe to do so.
+ */
+
+/*!
+ * \fn void QQmlAbstractProfilerAdapter::stopWaiting()
+ * Consider the profiler not to be waiting anymore. If it lives in a different threads any requests
+ * for it have to be done via a queued connection then.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickfiledialog_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index a4c7939fda..89b241e8d6 100644
--- a/src/imports/dialogs/qquickfiledialog_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,8 +39,14 @@
**
****************************************************************************/
-#ifndef QQUICKFILEDIALOG_P_H
-#define QQUICKFILEDIALOG_P_H
+#ifndef QQMLABSTRACTPROFILERADAPTER_P_H
+#define QQMLABSTRACTPROFILERADAPTER_P_H
+
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmlprofilerdefinitions_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QElapsedTimer>
//
// W A R N I N G
@@ -53,41 +59,50 @@
// We mean it.
//
-#include "qquickabstractfiledialog_p.h"
-
QT_BEGIN_NAMESPACE
-class QQuickFileDialog : public QQuickAbstractFileDialog
-{
+class QQmlProfilerService;
+class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
- Q_PROPERTY(QObject* implementation READ qmlImplementation WRITE setQmlImplementation DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "implementation") // AbstractFileDialog in QML can have only one child
public:
- explicit QQuickFileDialog(QObject *parent = 0);
- ~QQuickFileDialog();
- virtual QList<QUrl> fileUrls();
+ QQmlAbstractProfilerAdapter(QQmlProfilerService *service) :
+ service(service), waiting(true), running(false) {}
+ virtual ~QQmlAbstractProfilerAdapter() {}
+
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
+
+ void startProfiling();
+
+ void stopProfiling();
+
+ void reportData() { emit dataRequested(); }
-Q_SIGNALS:
+ void stopWaiting() { waiting = false; }
+ void startWaiting() { waiting = true; }
-public Q_SLOTS:
- void clearSelection();
- bool addSelection(const QUrl &path);
+ bool isRunning() const { return running; }
+
+ void synchronize(const QElapsedTimer &t) { emit referenceTimeKnown(t); }
+
+signals:
+ void profilingEnabled();
+ void profilingEnabledWhileWaiting();
+
+ void profilingDisabled();
+ void profilingDisabledWhileWaiting();
+
+ void dataRequested();
+ void referenceTimeKnown(const QElapsedTimer &timer);
protected:
- virtual QPlatformFileDialogHelper *helper() { return 0; }
- Q_INVOKABLE QString urlToPath(const QUrl &url) { return url.toLocalFile(); }
- Q_INVOKABLE QUrl pathToUrl(const QString &path) { return QUrl::fromLocalFile(path); }
- Q_INVOKABLE QUrl pathFolder(const QString &path);
+ QQmlProfilerService *service;
private:
- QList<QUrl> m_selections;
-
- Q_DISABLE_COPY(QQuickFileDialog)
+ bool waiting;
+ bool running;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickFileDialog *)
-
-#endif // QQUICKFILEDIALOG_P_H
+#endif // QQMLABSTRACTPROFILERADAPTER_P_H
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice.cpp b/src/qml/debugger/qqmlconfigurabledebugservice.cpp
new file mode 100644
index 0000000000..076e12b613
--- /dev/null
+++ b/src/qml/debugger/qqmlconfigurabledebugservice.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlconfigurabledebugservice_p.h"
+#include "qqmlconfigurabledebugservice_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlConfigurableDebugService::QQmlConfigurableDebugService(const QString &name, float version,
+ QObject *parent) :
+ QQmlDebugService((*new QQmlConfigurableDebugServicePrivate), name, version, parent) { init(); }
+
+QQmlConfigurableDebugService::QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd,
+ const QString &name, float version,
+ QObject *parent) :
+ QQmlDebugService(dd, name, version, parent) { init(); }
+
+QMutex *QQmlConfigurableDebugService::configMutex()
+{
+ Q_D(QQmlConfigurableDebugService);
+ return &d->configMutex;
+}
+
+void QQmlConfigurableDebugService::init()
+{
+ Q_D(QQmlConfigurableDebugService);
+ QMutexLocker lock(&d->configMutex);
+ // If we're not enabled or not blocking, don't wait for configuration
+ d->waitingForConfiguration = (registerService() == Enabled && blockingMode());
+}
+
+void QQmlConfigurableDebugService::stopWaiting()
+{
+ Q_D(QQmlConfigurableDebugService);
+ QMutexLocker lock(&d->configMutex);
+ d->waitingForConfiguration = false;
+ foreach (QQmlEngine *engine, d->waitingEngines)
+ emit attachedToEngine(engine);
+ d->waitingEngines.clear();
+}
+
+void QQmlConfigurableDebugService::stateChanged(QQmlDebugService::State newState)
+{
+ if (newState != Enabled)
+ stopWaiting();
+}
+
+void QQmlConfigurableDebugService::engineAboutToBeAdded(QQmlEngine *engine)
+{
+ Q_D(QQmlConfigurableDebugService);
+ QMutexLocker lock(&d->configMutex);
+ if (d->waitingForConfiguration)
+ d->waitingEngines.append(engine);
+ else
+ emit attachedToEngine(engine);
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickmessagedialog_p.h b/src/qml/debugger/qqmlconfigurabledebugservice_p.h
index 99c59ecca1..92d18bea90 100644
--- a/src/imports/dialogs/qquickmessagedialog_p.h
+++ b/src/qml/debugger/qqmlconfigurabledebugservice_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,8 +39,9 @@
**
****************************************************************************/
-#ifndef QQUICKMESSAGEDIALOG_P_H
-#define QQUICKMESSAGEDIALOG_P_H
+
+#ifndef QQMLCONFIGURABLEDEBUGSEVICE_H
+#define QQMLCONFIGURABLEDEBUGSEVICE_H
//
// W A R N I N G
@@ -53,33 +54,34 @@
// We mean it.
//
-#include "qquickabstractmessagedialog_p.h"
+#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-class QQuickMessageDialog : public QQuickAbstractMessageDialog
+class QMutex;
+class QQmlConfigurableDebugServicePrivate;
+class QQmlConfigurableDebugService : public QQmlDebugService
{
Q_OBJECT
- Q_PROPERTY(QObject* implementation READ qmlImplementation WRITE setQmlImplementation DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "implementation") // AbstractMessageDialog in QML can have only one child
-
public:
- explicit QQuickMessageDialog(QObject *parent = 0);
- ~QQuickMessageDialog();
+ QQmlConfigurableDebugService(const QString &name, float version, QObject *parent = 0);
protected:
- virtual QPlatformDialogHelper *helper() { return 0; }
+ QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-protected Q_SLOTS:
- virtual void accept();
- virtual void reject();
+ QMutex *configMutex();
+ void stopWaiting();
+ void init();
+ void stateChanged(State);
+ void engineAboutToBeAdded(QQmlEngine *);
+
+ virtual ~QQmlConfigurableDebugService() {}
private:
- Q_DISABLE_COPY(QQuickMessageDialog)
+ Q_DISABLE_COPY(QQmlConfigurableDebugService)
+ Q_DECLARE_PRIVATE(QQmlConfigurableDebugService)
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickMessageDialog *)
-
-#endif // QQUICKMESSAGEDIALOG_P_H
+#endif // QQMLCONFIGURABLEDEBUGSEVICE_H
diff --git a/src/imports/widgets/qquickqcolordialog_p.h b/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h
index 3fb0476299..0537933889 100644
--- a/src/imports/widgets/qquickqcolordialog_p.h
+++ b/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QQUICKQCOLORDIALOG_P_H
-#define QQUICKQCOLORDIALOG_P_H
+#ifndef QQMLCONFIGURABLEDEBUGSERVICE_P_H
+#define QQMLCONFIGURABLEDEBUGSERVICE_P_H
//
// W A R N I N G
@@ -53,26 +53,26 @@
// We mean it.
//
-#include "../dialogs/qquickabstractcolordialog_p.h"
+#include "qqmldebugservice_p.h"
+#include "qqmldebugservice_p_p.h"
+
+#include <QMutex>
QT_BEGIN_NAMESPACE
-class QQuickQColorDialog : public QQuickAbstractColorDialog
-{
- Q_OBJECT
+class QQmlEngine;
+class QQmlConfigurableDebugServicePrivate : public QQmlDebugServicePrivate
+{
+ Q_DECLARE_PUBLIC(QQmlConfigurableDebugService)
public:
- QQuickQColorDialog(QObject *parent = 0);
- virtual ~QQuickQColorDialog();
+ QQmlConfigurableDebugServicePrivate() : configMutex(QMutex::Recursive) {}
-protected:
- QPlatformColorDialogHelper *helper();
-
- Q_DISABLE_COPY(QQuickQColorDialog)
+ QMutex configMutex;
+ QList<QQmlEngine *> waitingEngines;
+ bool waitingForConfiguration;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickQColorDialog *)
-
-#endif // QQUICKQCOLORDIALOG_P_H
+#endif // QQMLCONFIGURABLEDEBUGSERVICE_P_H
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
index 0523762971..a2bf19dee7 100644
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ b/src/qml/debugger/qqmldebugserver.cpp
@@ -42,6 +42,12 @@
#include "qqmldebugserver_p.h"
#include "qqmldebugservice_p.h"
#include "qqmldebugservice_p_p.h"
+#include "qqmlenginedebugservice_p.h"
+#include "qv4debugservice_p.h"
+#include "qv4profilerservice_p.h"
+#include "qdebugmessageservice_p.h"
+#include "qqmlprofilerservice_p.h"
+
#include <private/qqmlengine_p.h>
#include <private/qqmlglobal_p.h>
@@ -56,6 +62,17 @@
QT_BEGIN_NAMESPACE
+// We can't friend the Q_GLOBAL_STATIC to have the constructor available so we need a little
+// workaround here. Using this wrapper we can also make QQmlEnginePrivate's cleanup() available to
+// qAddPostRoutine(). We can't do the cleanup in the destructor because we need a QApplication to
+// be available when stopping the plugins.
+struct QQmlDebugServerInstanceWrapper {
+ QQmlDebugServer m_instance;
+ void cleanup();
+};
+
+Q_GLOBAL_STATIC(QQmlDebugServerInstanceWrapper, debugServerInstance)
+
/*
QQmlDebug Protocol (Version 1):
@@ -93,6 +110,7 @@ public:
QQmlDebugServerPrivate();
void advertisePlugins();
+ void cleanup();
QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
QQmlDebugServerConnection *connection;
@@ -102,6 +120,22 @@ public:
bool gotHello;
bool blockingMode;
+ class EngineCondition {
+ public:
+ EngineCondition() : numServices(0), condition(new QWaitCondition) {}
+
+ bool waitForServices(QReadWriteLock *locked, int numEngines);
+
+ void wake();
+ private:
+ int numServices;
+
+ // shared pointer to allow for QHash-inflicted copying.
+ QSharedPointer<QWaitCondition> condition;
+ };
+
+ QHash<QQmlEngine *, EngineCondition> engineConditions;
+
QMutex helloMutex;
QWaitCondition helloCondition;
QQmlDebugServerThread *thread;
@@ -115,6 +149,9 @@ private:
void _q_sendMessages(const QList<QByteArray> &messages);
};
+void QQmlDebugServerInstanceWrapper::cleanup()
+{ m_instance.d_func()->cleanup(); }
+
class QQmlDebugServerThread : public QThread
{
public:
@@ -174,6 +211,35 @@ void QQmlDebugServerPrivate::advertisePlugins()
QMetaObject::invokeMethod(q, "_q_sendMessages", Qt::QueuedConnection, Q_ARG(QList<QByteArray>, QList<QByteArray>() << message));
}
+void QQmlDebugServerPrivate::cleanup()
+{
+ Q_Q(QQmlDebugServer);
+ {
+ QReadLocker lock(&pluginsLock);
+ foreach (QQmlDebugService *service, plugins.values()) {
+ changeServiceStateCalls.ref();
+ QMetaObject::invokeMethod(q, "_q_changeServiceState", Qt::QueuedConnection,
+ Q_ARG(QString, service->name()),
+ Q_ARG(QQmlDebugService::State, QQmlDebugService::NotConnected));
+ }
+ }
+
+ // Wait for changeServiceState calls to finish
+ // (while running an event loop because some services
+ // might again use slots to execute stuff in the GUI thread)
+ QEventLoop loop;
+ while (!changeServiceStateCalls.testAndSetOrdered(0, 0))
+ loop.processEvents();
+
+ // Stop the thread while the application is still there.
+ if (thread) {
+ thread->exit();
+ thread->wait();
+ delete thread;
+ thread = 0;
+ }
+}
+
QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
const QString &pluginName)
{
@@ -222,11 +288,13 @@ QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
void QQmlDebugServerThread::run()
{
- QQmlDebugServer *server = QQmlDebugServer::instance();
+ QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
+ Q_ASSERT_X(wrapper != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
+ QQmlDebugServer *server = &wrapper->m_instance;
QQmlDebugServerConnection *connection
= server->d_func()->loadConnectionPlugin(m_pluginName);
if (connection) {
- connection->setServer(QQmlDebugServer::instance());
+ connection->setServer(server);
connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress);
} else {
QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
@@ -255,112 +323,107 @@ bool QQmlDebugServer::blockingMode() const
return d->blockingMode;
}
-static QQmlDebugServer *qQmlDebugServer = 0;
-
-
-static void cleanup()
+QQmlDebugServer *QQmlDebugServer::instance()
{
- delete qQmlDebugServer;
- qQmlDebugServer = 0;
+ QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
+ if (wrapper && wrapper->m_instance.d_func()->thread) {
+ QQmlDebugServer *ret = &(wrapper->m_instance);
+ QQmlDebugServerPrivate *d = ret->d_func();
+ QMutexLocker locker(&d->helloMutex);
+ if (d->blockingMode && !d->gotHello)
+ d->helloCondition.wait(&d->helloMutex);
+ return ret;
+ } else {
+ return 0;
+ }
}
-QQmlDebugServer *QQmlDebugServer::instance()
+static void cleanup()
{
- static bool commandLineTested = false;
+ QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
+ if (wrapper)
+ wrapper->cleanup();
+}
- if (!commandLineTested) {
- commandLineTested = true;
- QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
+QQmlDebugServer::QQmlDebugServer()
+ : QObject(*(new QQmlDebugServerPrivate))
+{
+ QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
#ifndef QT_QML_NO_DEBUGGER
- // ### remove port definition when protocol is changed
- int portFrom = 0;
- int portTo = 0;
- bool block = false;
- bool ok = false;
- QString hostAddress;
-
- // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- if (!QQmlEnginePrivate::qml_debugging_enabled) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Debugging has not been enabled.")).arg(
- appD->qmljsDebugArgumentsString());
- return 0;
- }
+ // ### remove port definition when protocol is changed
+ int portFrom = 0;
+ int portTo = 0;
+ bool block = false;
+ bool ok = false;
+ QString hostAddress;
+
+ // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
+ if (!appD->qmljsDebugArgumentsString().isEmpty()) {
+ if (!QQmlEnginePrivate::qml_debugging_enabled) {
+ qWarning() << QString(QLatin1String(
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
+ "Debugging has not been enabled.")).arg(
+ appD->qmljsDebugArgumentsString());
+ return;
+ }
- QString pluginName;
- QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
- .split(QLatin1Char(','));
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.end();
- QStringList::const_iterator argsIt = lstjsDebugArguments.begin();
- for (; argsIt != argsItEnd; ++argsIt) {
- const QString strArgument = *argsIt;
- if (strArgument.startsWith(QLatin1String("port:"))) {
- pluginName = QLatin1String("qmldbg_tcp");
- portFrom = strArgument.mid(5).toInt(&ok);
- portTo = portFrom;
- QStringList::const_iterator argsNext = argsIt + 1;
- if (argsNext == argsItEnd)
- break;
- const QString nextArgument = *argsNext;
- if (ok && nextArgument.contains(QRegExp(QStringLiteral("^\\s*\\d+\\s*$")))) {
- portTo = nextArgument.toInt(&ok);
- ++argsIt;
- }
- } else if (strArgument.startsWith(QLatin1String("host:"))) {
- hostAddress = strArgument.mid(5);
- } else if (strArgument == QLatin1String("block")) {
- block = true;
- } else {
- qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
- "detected. Ignoring the same.")
- .arg(strArgument);
+ QString pluginName;
+ QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
+ .split(QLatin1Char(','));
+ QStringList::const_iterator argsItEnd = lstjsDebugArguments.end();
+ QStringList::const_iterator argsIt = lstjsDebugArguments.begin();
+ for (; argsIt != argsItEnd; ++argsIt) {
+ const QString strArgument = *argsIt;
+ if (strArgument.startsWith(QLatin1String("port:"))) {
+ pluginName = QLatin1String("qmldbg_tcp");
+ portFrom = strArgument.mid(5).toInt(&ok);
+ portTo = portFrom;
+ QStringList::const_iterator argsNext = argsIt + 1;
+ if (argsNext == argsItEnd)
+ break;
+ const QString nextArgument = *argsNext;
+ if (ok && nextArgument.contains(QRegExp(QStringLiteral("^\\s*\\d+\\s*$")))) {
+ portTo = nextArgument.toInt(&ok);
+ ++argsIt;
}
+ } else if (strArgument.startsWith(QLatin1String("host:"))) {
+ hostAddress = strArgument.mid(5);
+ } else if (strArgument == QLatin1String("block")) {
+ block = true;
+ } else {
+ qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
+ "detected. Ignoring the same.")
+ .arg(strArgument);
}
+ }
- if (ok) {
- qQmlDebugServer = new QQmlDebugServer();
- QQmlDebugServerThread *thread = new QQmlDebugServerThread;
- qQmlDebugServer->d_func()->thread = thread;
- qQmlDebugServer->moveToThread(thread);
- thread->setPluginName(pluginName);
- thread->setPortRange(portFrom, portTo, block, hostAddress);
-
- QQmlDebugServerPrivate *d = qQmlDebugServer->d_func();
- d->blockingMode = block;
-
- QMutexLocker locker(&d->helloMutex);
- thread->start();
+ if (ok) {
+ qAddPostRoutine(cleanup);
+ Q_D(QQmlDebugServer);
+ d->thread = new QQmlDebugServerThread;
+ moveToThread(d->thread);
+ d->thread->setPluginName(pluginName);
+ d->thread->setPortRange(portFrom, portTo, block, hostAddress);
- if (d->blockingMode)
- d->helloCondition.wait(&d->helloMutex);
+ d->blockingMode = block;
+ d->thread->start();
- } else {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
- "<ip address>][,block]")).arg(appD->qmljsDebugArgumentsString());
- }
- }
-#else
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
+ } else {
qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "QtQml is not configured for debugging.")).arg(
- appD->qmljsDebugArgumentsString());
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
+ "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
+ "<ip address>][,block]")).arg(appD->qmljsDebugArgumentsString());
}
-#endif
}
-
- return qQmlDebugServer;
-}
-
-QQmlDebugServer::QQmlDebugServer()
- : QObject(*(new QQmlDebugServerPrivate))
-{
- qAddPostRoutine(cleanup);
+#else
+ if (!appD->qmljsDebugArgumentsString().isEmpty()) {
+ qWarning() << QString(QLatin1String(
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
+ "QtQml is not configured for debugging.")).arg(
+ appD->qmljsDebugArgumentsString());
+ }
+#endif
}
// called from GUI thread!
@@ -368,28 +431,7 @@ QQmlDebugServer::~QQmlDebugServer()
{
Q_D(QQmlDebugServer);
- {
- QReadLocker lock(&d->pluginsLock);
- foreach (QQmlDebugService *service, d->plugins.values()) {
- d->changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(this, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, QQmlDebugService::NotConnected));
- }
- }
-
- // Wait for changeServiceState calls to finish
- // (while running an event loop because some services
- // might again use slots to execute stuff in the GUI thread)
- QEventLoop loop;
- while (!d->changeServiceStateCalls.testAndSetOrdered(0, 0))
- loop.processEvents();
-
- if (d->thread) {
- d->thread->exit();
- d->thread->wait();
- delete d->thread;
- }
+ delete d->thread;
delete d->connection;
}
@@ -409,6 +451,7 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message)
int op = -1;
in >> op;
if (op == 0) {
+ QWriteLocker lock(&d->pluginsLock);
int version;
in >> version >> d->clientPlugins;
@@ -423,24 +466,22 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message)
// the plugins below start sending messages.
QByteArray helloAnswer;
- {
- QReadLocker readPluginsLock(&d->pluginsLock);
- QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, d->plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
-
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
- << pluginNames << pluginVersions << s_dataStreamVersion;
+ QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ foreach (QQmlDebugService *service, d->plugins.values()) {
+ pluginNames << service->name();
+ pluginVersions << service->version();
}
+
+ out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
+ << pluginNames << pluginVersions << s_dataStreamVersion;
+
d->connection->send(QList<QByteArray>() << helloAnswer);
+ QMutexLocker helloLock(&d->helloMutex);
d->gotHello = true;
- QReadLocker lock(&d->pluginsLock);
QHash<QString, QQmlDebugService*>::ConstIterator iter = d->plugins.constBegin();
for (; iter != d->plugins.constEnd(); ++iter) {
QQmlDebugService::State newState = QQmlDebugService::Unavailable;
@@ -450,16 +491,15 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message)
d->_q_changeServiceState(iter.value()->name(), newState);
}
- QMutexLocker helloLock(&d->helloMutex);
d->helloCondition.wakeAll();
} else if (op == 1) {
+ QWriteLocker lock(&d->pluginsLock);
// Service Discovery
QStringList oldClientPlugins = d->clientPlugins;
in >> d->clientPlugins;
- QReadLocker lock(&d->pluginsLock);
QHash<QString, QQmlDebugService*>::ConstIterator iter = d->plugins.constBegin();
for (; iter != d->plugins.constEnd(); ++iter) {
const QString pluginName = iter.key();
@@ -507,7 +547,10 @@ void QQmlDebugServerPrivate::_q_changeServiceState(const QString &serviceName,
QQmlDebugService *service = 0;
{
- QReadLocker lock(&pluginsLock);
+ // Write lock here, because this can be called from receiveMessage which already has a write
+ // lock. We cannot downgrade it. We also don't want to give up the write lock and later get
+ // a read lock as that technique has great potential for deadlocks.
+ QWriteLocker lock(&pluginsLock);
service = plugins.value(serviceName);
}
@@ -543,27 +586,56 @@ QStringList QQmlDebugServer::serviceNames() const
return d->plugins.keys();
}
+void QQmlDebugServer::addEngine(QQmlEngine *engine)
+{
+ Q_D(QQmlDebugServer);
+ QWriteLocker lock(&d->pluginsLock);
+
+ foreach (QQmlDebugService *service, d->plugins)
+ service->engineAboutToBeAdded(engine);
+
+ d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
+
+ foreach (QQmlDebugService *service, d->plugins)
+ service->engineAdded(engine);
+}
+
+void QQmlDebugServer::removeEngine(QQmlEngine *engine)
+{
+ Q_D(QQmlDebugServer);
+ QWriteLocker lock(&d->pluginsLock);
+
+ foreach (QQmlDebugService *service, d->plugins)
+ service->engineAboutToBeRemoved(engine);
+
+ d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
+
+ foreach (QQmlDebugService *service, d->plugins)
+ service->engineRemoved(engine);
+}
+
bool QQmlDebugServer::addService(QQmlDebugService *service)
{
Q_D(QQmlDebugServer);
- // to be executed in GUI thread
- Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != thread());
- {
- QWriteLocker lock(&d->pluginsLock);
- if (!service || d->plugins.contains(service->name()))
- return false;
- d->plugins.insert(service->name(), service);
- }
- {
- QReadLocker lock(&d->pluginsLock);
- d->advertisePlugins();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(service->name()))
- newState = QQmlDebugService::Enabled;
- service->d_func()->state = newState;
- }
+ connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+ connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+
+
+ QWriteLocker lock(&d->pluginsLock);
+ if (!service || d->plugins.contains(service->name()))
+ return false;
+ d->plugins.insert(service->name(), service);
+ d->advertisePlugins();
+ QQmlDebugService::State newState = QQmlDebugService::Unavailable;
+ if (d->clientPlugins.contains(service->name()))
+ newState = QQmlDebugService::Enabled;
+ service->d_func()->state = newState;
return true;
}
@@ -571,24 +643,22 @@ bool QQmlDebugServer::removeService(QQmlDebugService *service)
{
Q_D(QQmlDebugServer);
- // to be executed in GUI thread
- Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != thread());
- {
- QWriteLocker lock(&d->pluginsLock);
- QQmlDebugService::State newState = QQmlDebugService::NotConnected;
+ QWriteLocker lock(&d->pluginsLock);
+ QQmlDebugService::State newState = QQmlDebugService::NotConnected;
- d->changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(this, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, newState));
+ d->changeServiceStateCalls.ref();
+ QMetaObject::invokeMethod(this, "_q_changeServiceState", Qt::QueuedConnection,
+ Q_ARG(QString, service->name()),
+ Q_ARG(QQmlDebugService::State, newState));
- if (!service || !d->plugins.contains(service->name()))
- return false;
- d->plugins.remove(service->name());
+ if (!service || !d->plugins.contains(service->name()))
+ return false;
+ d->plugins.remove(service->name());
- d->advertisePlugins();
- }
+ d->advertisePlugins();
return true;
}
@@ -608,6 +678,33 @@ void QQmlDebugServer::sendMessages(QQmlDebugService *service,
Q_ARG(QList<QByteArray>, prefixedMessages));
}
+void QQmlDebugServer::wakeEngine(QQmlEngine *engine)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ Q_D(QQmlDebugServer);
+ QWriteLocker lock(&d->pluginsLock);
+ d->engineConditions[engine].wake();
+}
+
+bool QQmlDebugServerPrivate::EngineCondition::waitForServices(QReadWriteLock *locked, int num)
+{
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != QQmlDebugServer::instance()->thread());
+
+ Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished");
+ numServices = num;
+ return condition->wait(locked);
+}
+
+void QQmlDebugServerPrivate::EngineCondition::wake()
+{
+ if (--numServices == 0)
+ condition->wakeAll();
+ Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services.");
+}
+
QT_END_NAMESPACE
#include "moc_qqmldebugserver_p.cpp"
diff --git a/src/qml/debugger/qqmldebugserver_p.h b/src/qml/debugger/qqmldebugserver_p.h
index e285d7cfe7..0675faaef7 100644
--- a/src/qml/debugger/qqmldebugserver_p.h
+++ b/src/qml/debugger/qqmldebugserver_p.h
@@ -77,6 +77,8 @@ public:
QList<QQmlDebugService*> services() const;
QStringList serviceNames() const;
+ void addEngine(QQmlEngine *engine);
+ void removeEngine(QQmlEngine *engine);
bool addService(QQmlDebugService *service);
bool removeService(QQmlDebugService *service);
@@ -85,10 +87,14 @@ public:
void sendMessages(QQmlDebugService *service, const QList<QByteArray> &messages);
+private slots:
+ void wakeEngine(QQmlEngine *engine);
+
private:
friend class QQmlDebugService;
friend class QQmlDebugServicePrivate;
friend class QQmlDebugServerThread;
+ friend struct QQmlDebugServerInstanceWrapper;
QQmlDebugServer();
Q_PRIVATE_SLOT(d_func(), void _q_changeServiceState(const QString &serviceName,
QQmlDebugService::State state))
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index d8fc2f2bb2..da62393d97 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -318,6 +318,24 @@ void QQmlDebugService::messageReceived(const QByteArray &)
{
}
+void QQmlDebugService::engineAboutToBeAdded(QQmlEngine *engine)
+{
+ emit attachedToEngine(engine);
+}
+
+void QQmlDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
+{
+ emit detachedFromEngine(engine);
+}
+
+void QQmlDebugService::engineAdded(QQmlEngine *)
+{
+}
+
+void QQmlDebugService::engineRemoved(QQmlEngine *)
+{
+}
+
QQmlDebugStream::QQmlDebugStream()
: QDataStream()
{
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 71a116f6a5..5208b2dfa8 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -60,6 +60,7 @@
QT_BEGIN_NAMESPACE
+class QQmlEngine;
class QQmlDebugServicePrivate;
class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
@@ -103,6 +104,15 @@ protected:
virtual void stateChanged(State);
virtual void messageReceived(const QByteArray &);
+ virtual void engineAboutToBeAdded(QQmlEngine *);
+ virtual void engineAboutToBeRemoved(QQmlEngine *);
+ virtual void engineAdded(QQmlEngine *);
+ virtual void engineRemoved(QQmlEngine *);
+
+signals:
+ void attachedToEngine(QQmlEngine *);
+ void detachedFromEngine(QQmlEngine *);
+
private:
friend class QQmlDebugServer;
friend class QQmlDebugServerPrivate;
diff --git a/src/qml/debugger/qqmlenginecontrolservice.cpp b/src/qml/debugger/qqmlenginecontrolservice.cpp
new file mode 100644
index 0000000000..90815912ad
--- /dev/null
+++ b/src/qml/debugger/qqmlenginecontrolservice.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QQmlEngine>
+#include "qqmldebug.h"
+#include "qqmlenginecontrolservice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QQmlEngineControlService, qmlEngineControlService)
+
+QQmlEngineControlService::QQmlEngineControlService() :
+ QQmlDebugService(QStringLiteral("EngineControl"), 1)
+{
+ QMutexLocker lock(&dataMutex);
+ registerService();
+}
+
+QQmlEngineControlService *QQmlEngineControlService::instance()
+{
+ return qmlEngineControlService();
+}
+
+void QQmlEngineControlService::messageReceived(const QByteArray &message)
+{
+ QMutexLocker lock(&dataMutex);
+ QQmlDebugStream d(message);
+ int command;
+ int engineId;
+ d >> command >> engineId;
+ QQmlEngine *engine = qobject_cast<QQmlEngine *>(objectForId(engineId));
+ if (command == StartWaitingEngine && startingEngines.contains(engine)) {
+ startingEngines.removeOne(engine);
+ emit attachedToEngine(engine);
+ } else if (command == StopWaitingEngine && stoppingEngines.contains(engine)) {
+ stoppingEngines.removeOne(engine);
+ emit detachedFromEngine(engine);
+ }
+}
+
+void QQmlEngineControlService::engineAboutToBeAdded(QQmlEngine *engine)
+{
+ QMutexLocker lock(&dataMutex);
+ if (state() == Enabled) {
+ Q_ASSERT(!stoppingEngines.contains(engine));
+ Q_ASSERT(!startingEngines.contains(engine));
+ startingEngines.append(engine);
+ sendMessage(EngineAboutToBeAdded, engine);
+ } else {
+ emit attachedToEngine(engine);
+ }
+}
+
+void QQmlEngineControlService::engineAboutToBeRemoved(QQmlEngine *engine)
+{
+ QMutexLocker lock(&dataMutex);
+ if (state() == Enabled) {
+ Q_ASSERT(!stoppingEngines.contains(engine));
+ Q_ASSERT(!startingEngines.contains(engine));
+ stoppingEngines.append(engine);
+ sendMessage(EngineAboutToBeRemoved, engine);
+ } else {
+ emit detachedFromEngine(engine);
+ }
+}
+
+void QQmlEngineControlService::engineAdded(QQmlEngine *engine)
+{
+ if (state() == Enabled) {
+ QMutexLocker lock(&dataMutex);
+ Q_ASSERT(!startingEngines.contains(engine));
+ Q_ASSERT(!stoppingEngines.contains(engine));
+ sendMessage(EngineAdded, engine);
+ }
+}
+
+void QQmlEngineControlService::engineRemoved(QQmlEngine *engine)
+{
+ if (state() == Enabled) {
+ QMutexLocker lock(&dataMutex);
+ Q_ASSERT(!startingEngines.contains(engine));
+ Q_ASSERT(!stoppingEngines.contains(engine));
+ sendMessage(EngineRemoved, engine);
+ }
+}
+
+void QQmlEngineControlService::sendMessage(QQmlEngineControlService::MessageType type, QQmlEngine *engine)
+{
+ QByteArray message;
+ QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ d << type << idForObject(engine);
+ QQmlDebugService::sendMessage(message);
+}
+
+void QQmlEngineControlService::stateChanged(State)
+{
+ // We flush everything for any kind of state change, to avoid complicated timing issues.
+ QMutexLocker lock(&dataMutex);
+ foreach (QQmlEngine *engine, startingEngines)
+ emit attachedToEngine(engine);
+ startingEngines.clear();
+ foreach (QQmlEngine *engine, stoppingEngines)
+ emit detachedFromEngine(engine);
+ stoppingEngines.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/dialogs/qquickplatformfontdialog_p.h b/src/qml/debugger/qqmlenginecontrolservice_p.h
index 743b24ad87..150d36d9cf 100644
--- a/src/imports/dialogs/qquickplatformfontdialog_p.h
+++ b/src/qml/debugger/qqmlenginecontrolservice_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,8 +39,11 @@
**
****************************************************************************/
-#ifndef QQUICKPLATFORMFONTDIALOG_P_H
-#define QQUICKPLATFORMFONTDIALOG_P_H
+#ifndef QQMLENGINECONTROLSERVICE_H
+#define QQMLENGINECONTROLSERVICE_H
+
+#include <QMutex>
+#include "qqmldebugservice_p.h"
//
// W A R N I N G
@@ -53,26 +56,43 @@
// We mean it.
//
-#include "qquickabstractfontdialog_p.h"
-
QT_BEGIN_NAMESPACE
-class QQuickPlatformFontDialog : public QQuickAbstractFontDialog
+class QQmlEngineControlService : public QQmlDebugService
{
- Q_OBJECT
-
public:
- QQuickPlatformFontDialog(QObject *parent = 0);
- virtual ~QQuickPlatformFontDialog();
+ enum MessageType {
+ EngineAboutToBeAdded,
+ EngineAdded,
+ EngineAboutToBeRemoved,
+ EngineRemoved
+ };
+
+ enum CommandType {
+ StartWaitingEngine,
+ StopWaitingEngine
+ };
+
+ QQmlEngineControlService();
+
+ static QQmlEngineControlService *instance();
protected:
- QPlatformFontDialogHelper *helper();
+ QMutex dataMutex;
+ QList<QQmlEngine *> startingEngines;
+ QList<QQmlEngine *> stoppingEngines;
+
+ void messageReceived(const QByteArray &);
+ void engineAboutToBeAdded(QQmlEngine *);
+ void engineAboutToBeRemoved(QQmlEngine *);
+ void engineAdded(QQmlEngine *);
+ void engineRemoved(QQmlEngine *);
- Q_DISABLE_COPY(QQuickPlatformFontDialog)
+ void sendMessage(MessageType type, QQmlEngine *engine);
+
+ void stateChanged(State);
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickPlatformFontDialog *)
-
-#endif // QQUICKPLATFORMFONTDIALOG_P_H
+#endif // QQMLENGINECONTROLSERVICE_H
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index 5f3db9fb65..2c6c1e22f5 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -83,7 +83,7 @@ QQmlEngineDebugService::~QQmlEngineDebugService()
delete m_statesDelegate;
}
-QDataStream &operator<<(QDataStream &ds,
+QDataStream &operator<<(QDataStream &ds,
const QQmlEngineDebugService::QQmlObjectData &data)
{
ds << data.url << data.lineNumber << data.columnNumber << data.idString
@@ -92,7 +92,7 @@ QDataStream &operator<<(QDataStream &ds,
return ds;
}
-QDataStream &operator>>(QDataStream &ds,
+QDataStream &operator>>(QDataStream &ds,
QQmlEngineDebugService::QQmlObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
@@ -101,7 +101,7 @@ QDataStream &operator>>(QDataStream &ds,
return ds;
}
-QDataStream &operator<<(QDataStream &ds,
+QDataStream &operator<<(QDataStream &ds,
const QQmlEngineDebugService::QQmlObjectProperty &data)
{
ds << (int)data.type << data.name << data.value << data.valueTypeName
@@ -109,7 +109,7 @@ QDataStream &operator<<(QDataStream &ds,
return ds;
}
-QDataStream &operator>>(QDataStream &ds,
+QDataStream &operator>>(QDataStream &ds,
QQmlEngineDebugService::QQmlObjectProperty &data)
{
int type;
@@ -219,13 +219,13 @@ QVariant QQmlEngineDebugService::valueContents(const QVariant &value) const
return QString(QStringLiteral("<unknown value>"));
}
-void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
+void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
QObject *object, bool recur, bool dumpProperties)
{
message << objectData(object);
QObjectList children = object->children();
-
+
int childrenCount = children.count();
for (int ii = 0; ii < children.count(); ++ii) {
if (qobject_cast<QQmlContext*>(children[ii]))
@@ -759,20 +759,22 @@ void QQmlEngineDebugService::propertyChanged(int id, int objectId, const QMetaPr
sendMessage(reply);
}
-void QQmlEngineDebugService::addEngine(QQmlEngine *engine)
+void QQmlEngineDebugService::engineAboutToBeAdded(QQmlEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(!m_engines.contains(engine));
m_engines.append(engine);
+ emit attachedToEngine(engine);
}
-void QQmlEngineDebugService::remEngine(QQmlEngine *engine)
+void QQmlEngineDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
m_engines.removeAll(engine);
+ emit detachedFromEngine(engine);
}
void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h
index bbd6aac1b1..4809ee3ed5 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/qml/debugger/qqmlenginedebugservice_p.h
@@ -96,8 +96,8 @@ public:
bool hasNotifySignal;
};
- void addEngine(QQmlEngine *);
- void remEngine(QQmlEngine *);
+ void engineAboutToBeAdded(QQmlEngine *);
+ void engineAboutToBeRemoved(QQmlEngine *);
void objectCreated(QQmlEngine *, QObject *);
void setStatesDelegate(QQmlDebugStatesDelegate *);
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
new file mode 100644
index 0000000000..f92d76cf5d
--- /dev/null
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlprofiler_p.h"
+#include "qqmlprofilerservice_p.h"
+#include "qqmldebugservice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+// (see tst_qqmldebugtrace::trace() benchmark)
+void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
+{
+ QByteArray data;
+ Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
+ for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
+ if ((messageType & (1 << decodedMessageType)) == 0)
+ continue;
+
+ for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
+ if ((detailType & (1 << decodedDetailType)) == 0)
+ continue;
+
+ //### using QDataStream is relatively expensive
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << time << decodedMessageType << decodedDetailType;
+
+ switch (decodedMessageType) {
+ case QQmlProfilerDefinitions::RangeStart:
+ if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
+ ds << QQmlProfilerDefinitions::QmlBinding;
+ break;
+ case QQmlProfilerDefinitions::RangeData:
+ ds << detailString;
+ break;
+ case QQmlProfilerDefinitions::RangeLocation:
+ ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y;
+ break;
+ case QQmlProfilerDefinitions::RangeEnd: break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
+ }
+ messages << data;
+ data.clear();
+ }
+ }
+}
+
+QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
+ QQmlAbstractProfilerAdapter(service)
+{
+ engine->enableProfiler();
+ connect(this, SIGNAL(profilingEnabled()), engine->profiler, SLOT(startProfiling()));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting()),
+ engine->profiler, SLOT(startProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()),
+ engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(referenceTimeKnown(const QElapsedTimer &)),
+ engine->profiler, SLOT(setTimer(const QElapsedTimer &)));
+ connect(engine->profiler, SIGNAL(dataReady(const QList<QQmlProfilerData> &)),
+ this, SLOT(receiveData(const QList<QQmlProfilerData> &)));
+}
+
+qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ while (!data.empty() && data.front().time <= until) {
+ data.front().toByteArrays(messages);
+ data.pop_front();
+ }
+ return data.empty() ? -1 : data.front().time;
+}
+
+void QQmlProfilerAdapter::receiveData(const QList<QQmlProfilerData> &new_data)
+{
+ data = new_data;
+ service->dataReady(this);
+}
+
+
+QQmlProfiler::QQmlProfiler() : enabled(false)
+{
+ static int metatype = qRegisterMetaType<QList<QQmlProfilerData> >();
+ Q_UNUSED(metatype);
+ m_timer.start();
+}
+
+void QQmlProfiler::startProfiling()
+{
+ enabled = true;
+}
+
+void QQmlProfiler::stopProfiling()
+{
+ enabled = false;
+ reportData();
+ m_data.clear();
+}
+
+void QQmlProfiler::reportData()
+{
+ QList<QQmlProfilerData> result;
+ result.reserve(m_data.size());
+ for (int i = 0; i < m_data.size(); ++i)
+ result.append(m_data[i]);
+ emit dataReady(result);
+}
+
+/*!
+ * \fn void QQmlVmeProfiler::Data::clear()
+ * Resets the profiling data to defaults.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::startBackground(const QString &typeName)
+ * If profiling is enabled clears the current range data, then stops the
+ * profiler previously running in the foreground if any, then starts a new one
+ * in the background, setting the given typeName. \a typeName is the type of
+ * object being created.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::start(const QString &typeName, const QUrl &url, int line, int column)
+ * If profiling is enabled clears the current range data, then stops the
+ * profiler previously running in the foreground if any, then starts a new one
+ * in the foreground, setting the given location. \a url is the URL of
+ * file being executed, \line line is the current line in in that file, and
+ * \a column is the current column in that file.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::pop()
+ * Stops the currently running profiler, if any, then retrieves an old one from the stack
+ * of paused profilers and starts that if possible.
+ */
+
+/*!
+ * \fn void QQmlVmeProfiler::push()
+ * Pushes the currently running profiler on the stack of paused profilers. Note: The profiler
+ * isn't paused here. That's a separate step. If it's never paused, but pop()'ed later that
+ * won't do any harm, though.
+ */
+
+/*!
+ * \fn void QQmlVmeProfiler::clear()
+ * Stops the currently running (foreground and background) profilers and removes all saved
+ * data about paused profilers.
+ */
+
+/*!
+ * \fn void QQmlVmeProfiler::stop()
+ * Stop profiler running in the foreground, if any.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::foreground(const QUrl &url, int line, int column)
+ * Stops the profiler currently running in the foreground, if any and puts the
+ * next profiler from the background in its place if there are any profilers in
+ * the background. Additionally the rangeLocation is set. \a url is the URL of
+ * file being executed, \line line is the current line in in that file, and
+ * \a column is the current column in that file.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
new file mode 100644
index 0000000000..ca464e86a3
--- /dev/null
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROFILER_P_H
+#define QQMLPROFILER_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/qv4function_p.h>
+#include <private/qqmlboundsignal_p.h>
+#include "qqmlprofilerdefinitions_p.h"
+#include "qqmlabstractprofileradapter_p.h"
+
+#include <QUrl>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+#define Q_QML_PROFILE_IF_ENABLED(profiler, Code)\
+ if (profiler && profiler->enabled) {\
+ Code;\
+ } else\
+ (void)0
+
+#define Q_QML_PROFILE(profiler, Method)\
+ Q_QML_PROFILE_IF_ENABLED(profiler, profiler->Method)
+
+// This struct is somewhat dangerous to use:
+// The messageType is a bit field. You can pack multiple messages into
+// one object, e.g. RangeStart and RangeLocation. Each one will be read
+// independently by toByteArrays. Thus you can only pack messages if their data
+// doesn't overlap. It's up to you to figure that out.
+struct Q_AUTOTEST_EXPORT QQmlProfilerData
+{
+ QQmlProfilerData() {}
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url,
+ int x = 0, int y = 0) :
+ time(time), messageType(messageType), detailType(detailType), detailUrl(url),
+ x(x), y(y) {}
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
+ int x = 0, int y = 0) :
+ time(time), messageType(messageType), detailType(detailType),detailString(str),
+ x(x), y(y) {}
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
+ const QUrl &url, int x = 0, int y = 0) :
+ time(time), messageType(messageType), detailType(detailType), detailString(str),
+ detailUrl(url), x(x), y(y) {}
+
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType) :
+ time(time), messageType(messageType), detailType(detailType) {}
+
+
+ qint64 time;
+ int messageType; //bit field of QQmlProfilerService::Message
+ int detailType;
+
+ QString detailString; //used by RangeData and possibly by RangeLocation
+ QUrl detailUrl; //used by RangeLocation, overrides detailString
+
+ int x; //used by RangeLocation
+ int y; //used by RangeLocation
+
+ void toByteArrays(QList<QByteArray> &messages) const;
+};
+
+Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
+
+class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
+ Q_OBJECT
+public:
+ void startBinding(const QString &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation), 1 << Binding,
+ fileName, line, column));
+ }
+
+ // Have toByteArrays() construct another RangeData event from the same QString later.
+ // This is somewhat pointless but important for backwards compatibility.
+ void startCompiling(const QString &name)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
+ 1 << Compiling, name, 1, 1));
+ }
+
+ void startHandlingSignal(const QString &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal,
+ fileName, line, column));
+ }
+
+ void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
+ 1 << Creating, typeName, fileName, line, column));
+ }
+
+ void startCreating(const QString &typeName)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeData),
+ 1 << Creating, typeName));
+ }
+
+ void creatingLocation(const QUrl &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeLocation, 1 << Creating,
+ fileName, line, column));
+ }
+
+ template<RangeType Range>
+ void endRange()
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range));
+ }
+
+ QQmlProfiler();
+
+ bool enabled;
+
+public slots:
+ void startProfiling();
+ void stopProfiling();
+ void reportData();
+ void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
+
+signals:
+ void dataReady(const QList<QQmlProfilerData> &);
+
+protected:
+ QElapsedTimer m_timer;
+ QVarLengthArray<QQmlProfilerData> m_data;
+};
+
+class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
+public:
+ QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+public slots:
+ void receiveData(const QList<QQmlProfilerData> &new_data);
+
+private:
+ QList<QQmlProfilerData> data;
+};
+
+//
+// RAII helper structs
+//
+
+struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
+ QQmlProfiler *profiler;
+ QQmlProfilerHelper(QQmlProfiler *profiler) : profiler(profiler) {}
+};
+
+struct QQmlBindingProfiler : public QQmlProfilerHelper {
+ QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) :
+ QQmlProfilerHelper(profiler)
+ {
+ Q_QML_PROFILE(profiler, startBinding(url, line, column));
+ }
+
+ ~QQmlBindingProfiler()
+ {
+ Q_QML_PROFILE(profiler, endRange<Binding>());
+ }
+};
+
+struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
+ QQmlHandlingSignalProfiler(QQmlProfiler *profiler, QQmlBoundSignalExpression *expression) :
+ QQmlProfilerHelper(profiler)
+ {
+ Q_QML_PROFILE_IF_ENABLED(profiler, {
+ QV4::Function *function;
+ if (expression->sourceFile().isEmpty() && (function = expression->function())) {
+ profiler->startHandlingSignal(
+ function->sourceFile(), function->compiledFunction->location.line,
+ function->compiledFunction->location.column);
+
+ } else {
+ profiler->startHandlingSignal(
+ expression->sourceFile(), expression->lineNumber(),
+ expression->columnNumber());
+ }
+ });
+ }
+
+ ~QQmlHandlingSignalProfiler()
+ {
+ Q_QML_PROFILE(profiler, endRange<QQmlProfiler::HandlingSignal>());
+ }
+};
+
+struct QQmlCompilingProfiler : public QQmlProfilerHelper {
+ QQmlCompilingProfiler(QQmlProfiler *profiler, const QString &name) :
+ QQmlProfilerHelper(profiler)
+ {
+ Q_QML_PROFILE(profiler, startCompiling(name));
+ }
+
+ ~QQmlCompilingProfiler()
+ {
+ Q_QML_PROFILE(profiler, endRange<Compiling>());
+ }
+};
+
+#define Q_QML_VME_PROFILE(profiler, Method) Q_QML_PROFILE_IF_ENABLED(profiler.profiler, profiler.Method)
+
+struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
+public:
+
+ struct Data {
+ Data() : line(0), column(0) {}
+ QUrl url;
+ int line;
+ int column;
+ QString typeName;
+ };
+
+ QQmlVmeProfiler() : profiler(0), running(false) {}
+
+ void clear(bool stopProfiling = false)
+ {
+ ranges.clear();
+ if (running)
+ profiler->endRange<Creating>();
+ for (int i = 0; i < backgroundRanges.count(); ++i) {
+ profiler->endRange<Creating>();
+ }
+ backgroundRanges.clear();
+ running = false;
+ if (stopProfiling) profiler = 0;
+ }
+
+ void startBackground(const QString &typeName)
+ {
+ if (running) {
+ profiler->endRange<Creating>();
+ running = false;
+ }
+ profiler->startCreating(typeName);
+ backgroundRanges.push(typeName);
+ }
+
+ void start(const QString &typeName, const QUrl &url, int line, int column)
+ {
+ switchRange();
+ setCurrentRange(typeName, url, line, column);
+ profiler->startCreating(typeName, url, line, column);
+ }
+
+ void stop()
+ {
+ if (running) {
+ profiler->endRange<Creating>();
+ running = false;
+ }
+ }
+
+ void pop()
+ {
+ if (ranges.count() > 0) {
+ switchRange();
+ currentRange = ranges.pop();
+ profiler->startCreating(currentRange.typeName, currentRange.url,
+ currentRange.line, currentRange.column);
+ }
+ }
+
+ void push()
+ {
+ if (running)
+ ranges.push(currentRange);
+ }
+
+ void foreground(const QUrl &url, int line, int column)
+ {
+ if (backgroundRanges.count() > 0) {
+ switchRange();
+ setCurrentRange(backgroundRanges.pop(), url, line, column);
+ profiler->creatingLocation(url, line, column);
+ }
+ }
+
+ QQmlProfiler *profiler;
+
+private:
+
+ void switchRange()
+ {
+ if (running)
+ profiler->endRange<Creating>();
+ else
+ running = true;
+ }
+
+ void setCurrentRange(const QString &typeName, const QUrl &url, int line, int column)
+ {
+ currentRange.typeName = typeName;
+ currentRange.url = url;
+ currentRange.line = line;
+ currentRange.column = column;
+ }
+
+ Data currentRange;
+ QStack<Data> ranges;
+ QStack<QString> backgroundRanges;
+ bool running;
+};
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QList<QQmlProfilerData>)
+
+#endif // QQMLPROFILER_P_H
diff --git a/src/imports/widgets/qquickqfiledialog_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h
index 2bd364eba0..9452260ce4 100644
--- a/src/imports/widgets/qquickqfiledialog_p.h
+++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -39,8 +39,10 @@
**
****************************************************************************/
-#ifndef QQUICKQFILEDIALOG_P_H
-#define QQUICKQFILEDIALOG_P_H
+#ifndef QQMLPROFILERDEFINITIONS_P_H
+#define QQMLPROFILERDEFINITIONS_P_H
+
+#include <private/qtqmlglobal_p.h>
//
// W A R N I N G
@@ -53,55 +55,79 @@
// We mean it.
//
-#include <QFileDialog>
-#include "../dialogs/qquickabstractfiledialog_p.h"
-
QT_BEGIN_NAMESPACE
-class QQuickQFileDialog : public QQuickAbstractFileDialog
-{
- Q_OBJECT
+struct QQmlProfilerDefinitions {
+ enum Message {
+ Event,
+ RangeStart,
+ RangeData,
+ RangeLocation,
+ RangeEnd,
+ Complete, // end of transmission
+ PixmapCacheEvent,
+ SceneGraphFrame,
-public:
- QQuickQFileDialog(QObject *parent = 0);
- virtual ~QQuickQFileDialog();
+ MaximumMessage
+ };
-protected:
- QPlatformFileDialogHelper *helper();
+ enum EventType {
+ FramePaint,
+ Mouse,
+ Key,
+ AnimationFrame,
+ EndTrace,
+ StartTrace,
- Q_DISABLE_COPY(QQuickQFileDialog)
-};
+ MaximumEventType
+ };
+
+ enum RangeType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding, //running a binding
+ HandlingSignal, //running a signal handler
+ Javascript,
+
+ MaximumRangeType
+ };
+
+ enum BindingType {
+ QmlBinding,
+ V8Binding,
+ V4Binding,
-class QFileDialogHelper : public QPlatformFileDialogHelper
-{
- Q_OBJECT
-public:
- QFileDialogHelper();
-
- bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return true; }
- void setDirectory(const QUrl &dir) Q_DECL_OVERRIDE { m_dialog.setDirectoryUrl(dir); }
- QUrl directory() const Q_DECL_OVERRIDE { return m_dialog.directoryUrl(); }
- void selectFile(const QUrl &f) Q_DECL_OVERRIDE { m_dialog.selectUrl(f); }
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- void setFilter() Q_DECL_OVERRIDE;
- void selectNameFilter(const QString &f) Q_DECL_OVERRIDE { m_dialog.selectNameFilter(f); }
- QString selectedNameFilter() const Q_DECL_OVERRIDE { return m_dialog.selectedNameFilter(); }
- void exec() Q_DECL_OVERRIDE { m_dialog.exec(); }
- bool show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE { m_dialog.hide(); }
-
-private Q_SLOTS:
- void currentChanged(const QString& path);
- void directoryEntered(const QString& path);
- void fileSelected(const QString& path);
- void filesSelected(const QStringList& paths);
-
-private:
- QFileDialog m_dialog;
+ MaximumBindingType
+ };
+
+ enum PixmapEventType {
+ PixmapSizeKnown,
+ PixmapReferenceCountChanged,
+ PixmapCacheCountChanged,
+ PixmapLoadingStarted,
+ PixmapLoadingFinished,
+ PixmapLoadingError,
+
+ MaximumPixmapEventType
+ };
+
+ enum SceneGraphFrameType {
+ SceneGraphRendererFrame,
+ SceneGraphAdaptationLayerFrame,
+ SceneGraphContextFrame,
+ SceneGraphRenderLoopFrame,
+ SceneGraphTexturePrepare,
+ SceneGraphTextureDeletion,
+ SceneGraphPolishAndSync,
+ SceneGraphWindowsRenderShow,
+ SceneGraphWindowsAnimations,
+ SceneGraphWindowsPolishFrame,
+
+ MaximumSceneGraphFrameType
+ };
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickQFileDialog *)
-
-#endif // QQUICKQFILEDIALOG_P_H
+#endif
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index af2aea21ae..5500b8f22c 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -40,6 +40,10 @@
****************************************************************************/
#include "qqmlprofilerservice_p.h"
+#include "qqmldebugserver_p.h"
+#include "qv4profileradapter_p.h"
+#include "qqmlprofiler_p.h"
+#include <private/qqmlengine_p.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qurl.h>
@@ -47,336 +51,240 @@
#include <QtCore/qthread.h>
#include <QtCore/qcoreapplication.h>
-// this contains QUnifiedTimer
-#include <private/qabstractanimation_p.h>
-
QT_BEGIN_NAMESPACE
-// instance will be set, unset in constructor. Allows static methods to be inlined.
-QQmlProfilerService *QQmlProfilerService::instance = 0;
Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance)
-bool QQmlProfilerService::enabled = false;
-
-// convert to a QByteArray that can be sent to the debug client
-// use of QDataStream can skew results
-// (see tst_qqmldebugtrace::trace() benchmark)
-QByteArray QQmlProfilerData::toByteArray() const
-{
- QByteArray data;
- //### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << time << messageType << detailType;
- if (messageType == (int)QQmlProfilerService::RangeStart &&
- detailType == (int)QQmlProfilerService::Binding)
- ds << bindingType;
- if (messageType == (int)QQmlProfilerService::RangeData)
- ds << detailData;
- if (messageType == (int)QQmlProfilerService::RangeLocation)
- ds << detailData << line << column;
- if (messageType == (int)QQmlProfilerService::Event &&
- detailType == (int)QQmlProfilerService::AnimationFrame)
- ds << framerate << animationcount;
- if (messageType == (int)QQmlProfilerService::PixmapCacheEvent) {
- ds << detailData;
- switch (detailType) {
- case QQmlProfilerService::PixmapSizeKnown: ds << line << column; break;
- case QQmlProfilerService::PixmapReferenceCountChanged: ds << animationcount; break;
- case QQmlProfilerService::PixmapCacheCountChanged: ds << animationcount; break;
- default: break;
- }
- }
- if (messageType == (int)QQmlProfilerService::SceneGraphFrame) {
- switch (detailType) {
- // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
- case QQmlProfilerService::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
- // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
- case QQmlProfilerService::SceneGraphAdaptationLayerFrame: ds << (int)subtime_1 << subtime_2 << subtime_3; break;
- // ContextFrame: compiling material time
- case QQmlProfilerService::SceneGraphContextFrame: ds << subtime_1; break;
- // RenderLoop: syncTime, renderTime, swapTime
- case QQmlProfilerService::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break;
- // TexturePrepare: bind, convert, swizzle, upload, mipmap
- case QQmlProfilerService::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break;
- // TextureDeletion: deletionTime
- case QQmlProfilerService::SceneGraphTextureDeletion: ds << subtime_1; break;
- // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
- case QQmlProfilerService::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
- // WindowsRenderLoop: GL time, make current time, SceneGraph time
- case QQmlProfilerService::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break;
- // WindowsAnimations: update time
- case QQmlProfilerService::SceneGraphWindowsAnimations: ds << subtime_1; break;
- // WindowsRenderWindow: polish time
- case QQmlProfilerService::SceneGraphWindowsPolishFrame: ds << subtime_1; break;
- default:break;
- }
- }
-
- return data;
-}
QQmlProfilerService::QQmlProfilerService()
- : QQmlDebugService(QStringLiteral("CanvasFrameRate"), 1)
+ : QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1)
{
m_timer.start();
- // don't execute stateAboutToBeChanged(), messageReceived() in parallel
- QMutexLocker lock(&m_initializeMutex);
-
- if (registerService() == Enabled) {
- QUnifiedTimer::instance()->registerProfilerCallback(&animationFrame);
- if (blockingMode())
- m_initializeCondition.wait(&m_initializeMutex);
- }
+ QMutexLocker lock(configMutex());
+ // If there is no debug server it doesn't matter as we'll never get enabled anyway.
+ if (QQmlDebugServer::instance() != 0)
+ moveToThread(QQmlDebugServer::instance()->thread());
}
QQmlProfilerService::~QQmlProfilerService()
{
- instance = 0;
-}
-
-void QQmlProfilerService::initialize()
-{
- // just make sure that the service is properly registered
- instance = profilerInstance();
-}
-
-bool QQmlProfilerService::startProfiling()
-{
- return profilerInstance()->startProfilingImpl();
-}
-
-bool QQmlProfilerService::stopProfiling()
-{
- return profilerInstance()->stopProfilingImpl();
-}
-
-void QQmlProfilerService::sendStartedProfilingMessage()
-{
- profilerInstance()->sendStartedProfilingMessageImpl();
-}
-
-void QQmlProfilerService::addEvent(EventType t)
-{
- profilerInstance()->addEventImpl(t);
-}
-
-void QQmlProfilerService::animationFrame(qint64 delta)
-{
- profilerInstance()->animationFrameImpl(delta);
-}
-
-void QQmlProfilerService::sceneGraphFrame(SceneGraphFrameType frameType, qint64 value1, qint64 value2, qint64 value3, qint64 value4, qint64 value5)
-{
- profilerInstance()->sceneGraphFrameImpl(frameType, value1, value2, value3, value4, value5);
-}
-
-void QQmlProfilerService::sendProfilingData()
-{
- profilerInstance()->sendMessages();
+ // No need to lock here. If any engine or global profiler is still trying to register at this
+ // point we have a nasty bug anyway.
+ qDeleteAll(m_engineProfilers.keys());
+ qDeleteAll(m_globalProfilers);
}
-bool QQmlProfilerService::startProfilingImpl()
+void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
{
- bool success = false;
- if (QQmlDebugService::isDebuggingEnabled() && !profilingEnabled()) {
- setProfilingEnabled(true);
- sendStartedProfilingMessageImpl();
- success = true;
+ QMutexLocker lock(configMutex());
+ bool dataComplete = true;
+ for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin()); i != m_startTimes.end();) {
+ if (i.value() == profiler) {
+ m_startTimes.erase(i++);
+ } else {
+ if (i.key() == -1)
+ dataComplete = false;
+ ++i;
+ }
}
- return success;
-}
-
-bool QQmlProfilerService::stopProfilingImpl()
-{
- bool success = false;
- if (profilingEnabled()) {
- addEventImpl(EndTrace);
- setProfilingEnabled(false);
- success = true;
+ m_startTimes.insert(0, profiler);
+ if (dataComplete) {
+ QList<QQmlEngine *> enginesToRelease;
+ foreach (QQmlEngine *engine, m_stoppingEngines) {
+ foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers.values(engine)) {
+ if (m_startTimes.values().contains(engineProfiler)) {
+ enginesToRelease.append(engine);
+ break;
+ }
+ }
+ }
+ sendMessages();
+ foreach (QQmlEngine *engine, enginesToRelease) {
+ m_stoppingEngines.removeOne(engine);
+ emit detachedFromEngine(engine);
+ }
}
- return success;
}
-void QQmlProfilerService::sendStartedProfilingMessageImpl()
+QQmlProfilerService *QQmlProfilerService::instance()
{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
-
- QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)StartTrace,
- QString(), -1, -1, 0, 0, 0,
- 0, 0, 0, 0, 0};
- QQmlDebugService::sendMessage(ed.toByteArray());
-}
-
-void QQmlProfilerService::addEventImpl(EventType event)
-{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
-
- QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event,
- QString(), -1, -1, 0, 0, 0,
- 0, 0, 0, 0, 0};
- processMessage(ed);
-}
-
-void QQmlProfilerService::startRange(RangeType range, BindingType bindingType)
-{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
-
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range,
- QString(), -1, -1, 0, 0, (int)bindingType,
- 0, 0, 0, 0, 0};
- processMessage(rd);
-}
-
-void QQmlProfilerService::rangeData(RangeType range, const QString &rData)
-{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
-
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range,
- rData, -1, -1, 0, 0, 0,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ // just make sure that the service is properly registered
+ return profilerInstance();
}
-void QQmlProfilerService::rangeData(RangeType range, const QUrl &rData)
+void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine)
{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
+ Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range,
- rData.toString(), -1, -1, 0, 0, 0,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ QMutexLocker lock(configMutex());
+ QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
+ QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
+ addEngineProfiler(qmlAdapter, engine);
+ addEngineProfiler(v4Adapter, engine);
+ QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
}
-void QQmlProfilerService::rangeLocation(RangeType range, const QString &fileName, int line, int column)
+void QQmlProfilerService::engineAdded(QQmlEngine *engine)
{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
+ Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range,
- fileName, line, column, 0, 0, 0,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ QMutexLocker lock(configMutex());
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine))
+ profiler->stopWaiting();
}
-void QQmlProfilerService::rangeLocation(RangeType range, const QUrl &fileName, int line, int column)
+void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine)
{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
+ Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range,
- fileName.toString(), line, column, 0, 0, 0,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ QMutexLocker lock(configMutex());
+ bool isRunning = false;
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
+ if (profiler->isRunning())
+ isRunning = true;
+ profiler->startWaiting();
+ }
+ if (isRunning) {
+ m_stoppingEngines.append(engine);
+ stopProfiling(engine);
+ } else {
+ emit detachedFromEngine(engine);
+ }
}
-void QQmlProfilerService::endRange(RangeType range)
+void QQmlProfilerService::engineRemoved(QQmlEngine *engine)
{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
+ Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range,
- QString(), -1, -1, 0, 0, 0,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ QMutexLocker lock(configMutex());
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine))
+ delete profiler;
+ m_engineProfilers.remove(engine);
}
-void QQmlProfilerService::pixmapEventImpl(PixmapEventType eventType, const QUrl &url)
+void QQmlProfilerService::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
{
- // assuming enabled checked by caller
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)PixmapCacheEvent, (int)eventType,
- url.toString(), -1, -1, -1, -1, -1,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ profiler->moveToThread(thread());
+ profiler->synchronize(m_timer);
+ m_engineProfilers.insert(engine, profiler);
}
-void QQmlProfilerService::pixmapEventImpl(PixmapEventType eventType, const QUrl &url, int width, int height)
+void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
{
- // assuming enabled checked by caller
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)PixmapCacheEvent, (int)eventType,
- url.toString(), width, height, -1, -1, -1,
- 0, 0, 0, 0, 0};
- processMessage(rd);
-}
-
-void QQmlProfilerService::pixmapEventImpl(PixmapEventType eventType, const QUrl &url, int count)
-{
- // assuming enabled checked by caller
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)PixmapCacheEvent, (int)eventType,
- url.toString(), -1, -1, -1, count, -1,
- 0, 0, 0, 0, 0};
- processMessage(rd);
+ QMutexLocker lock(configMutex());
+ profiler->synchronize(m_timer);
+ m_globalProfilers.append(profiler);
+ // Global profiler, not connected to a specific engine.
+ // Global profilers are started whenever any engine profiler is started and stopped when
+ // all engine profilers are stopped.
+ foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers) {
+ if (engineProfiler->isRunning()) {
+ profiler->startProfiling();
+ break;
+ }
+ }
}
-void QQmlProfilerService::sceneGraphFrameImpl(SceneGraphFrameType frameType, qint64 value1, qint64 value2, qint64 value3, qint64 value4, qint64 value5)
+void QQmlProfilerService::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
{
- if (!QQmlDebugService::isDebuggingEnabled() || !enabled)
- return;
-
- // because I already have some space to store ints in the struct, I'll use it to store the frame data
- // even though the field names do not match
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)SceneGraphFrame, (int)frameType, QString(),
- -1, -1, -1, -1, -1,
- value1, value2, value3, value4, value5};
- processMessage(rd);
+ QMutexLocker lock(configMutex());
+ for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin()); i != m_startTimes.end();) {
+ if (i.value() == profiler)
+ m_startTimes.erase(i++);
+ else
+ ++i;
+ }
+ m_globalProfilers.removeOne(profiler);
+ delete profiler;
}
-void QQmlProfilerService::animationFrameImpl(qint64 delta)
+void QQmlProfilerService::startProfiling(QQmlEngine *engine)
{
- Q_ASSERT(QQmlDebugService::isDebuggingEnabled());
- if (!enabled)
- return;
-
- int animCount = QUnifiedTimer::instance()->runningAnimationCount();
+ QMutexLocker lock(configMutex());
- if (animCount > 0 && delta > 0) {
- // trim fps to integer
- int fps = 1000 / delta;
- QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame,
- QString(), -1, -1, fps, animCount, 0,
- 0, 0, 0, 0, 0};
- processMessage(ed);
+ QByteArray message;
+ QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ d << m_timer.nsecsElapsed() << (int)Event << (int)StartTrace << idForObject(engine);
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
+ profiler->startProfiling();
+ }
+ if (!m_engineProfilers.values(engine).empty()) {
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
+ if (!profiler->isRunning())
+ profiler->startProfiling();
+ }
}
-}
-/*
- Either send the message directly, or queue up
- a list of messages to send later (via sendMessages)
-*/
-void QQmlProfilerService::processMessage(const QQmlProfilerData &message)
-{
- QMutexLocker locker(&m_dataMutex);
- m_data.append(message);
+ QQmlDebugService::sendMessage(message);
}
-bool QQmlProfilerService::profilingEnabled()
+void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
{
- return enabled;
-}
+ QMutexLocker lock(configMutex());
-void QQmlProfilerService::setProfilingEnabled(bool enable)
-{
- enabled = enable;
+ bool stillRunning = false;
+ m_startTimes.clear();
+ for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ i != m_engineProfilers.end(); ++i) {
+ if (i.value()->isRunning()) {
+ if (i.key() == engine) {
+ m_startTimes.insert(-1, i.value());
+ i.value()->stopProfiling();
+ } else {
+ stillRunning = true;
+ }
+ }
+ }
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
+ if (!profiler->isRunning())
+ continue;
+ m_startTimes.insert(-1, profiler);
+ if (stillRunning) {
+ profiler->reportData();
+ } else {
+ profiler->stopProfiling();
+ }
+ }
}
/*
- Send the messages queued up by processMessage
+ Send the queued up messages.
*/
void QQmlProfilerService::sendMessages()
{
- QMutexLocker locker(&m_dataMutex);
-
QList<QByteArray> messages;
- for (int i = 0; i < m_data.count(); ++i)
- messages << m_data.at(i).toByteArray();
- m_data.clear();
- //indicate completion
QByteArray data;
+ QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
+ traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
+
+ QSet<QQmlEngine *> seen;
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
+ for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ i != m_engineProfilers.end(); ++i) {
+ if (i.value() == profiler && !seen.contains(i.key())) {
+ seen << i.key();
+ traceEnd << idForObject(i.key());
+ }
+ }
+ }
+
+ while (!m_startTimes.empty()) {
+ QQmlAbstractProfilerAdapter *first = m_startTimes.begin().value();
+ m_startTimes.erase(m_startTimes.begin());
+ if (!m_startTimes.empty()) {
+ qint64 next = first->sendMessages(m_startTimes.begin().key(), messages);
+ if (next != -1)
+ m_startTimes.insert(next, first);
+ } else {
+ first->sendMessages(std::numeric_limits<qint64>::max(), messages);
+ }
+ }
+
+ //indicate completion
+ messages << data;
+ data.clear();
+
QQmlDebugStream ds(&data, QIODevice::WriteOnly);
ds << (qint64)-1 << (int)Complete;
messages << data;
@@ -386,193 +294,49 @@ void QQmlProfilerService::sendMessages()
void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
{
- QMutexLocker lock(&m_initializeMutex);
+ QMutexLocker lock(configMutex());
if (state() == newState)
return;
- if (state() == Enabled
- && enabled) {
- stopProfilingImpl();
- sendMessages();
- }
-
- if (state() != Enabled) {
- // wake up constructor in blocking mode
- // (we might got disabled before first message arrived)
- m_initializeCondition.wakeAll();
+ // Stop all profiling and send the data before we get disabled.
+ if (newState != Enabled) {
+ foreach (QQmlEngine *engine, m_engineProfilers.keys())
+ stopProfiling(engine);
}
}
void QQmlProfilerService::messageReceived(const QByteArray &message)
{
- QMutexLocker lock(&m_initializeMutex);
+ QMutexLocker lock(configMutex());
QByteArray rwData = message;
QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
+ int engineId = -1;
bool enabled;
stream >> enabled;
-
- if (enabled) {
- startProfilingImpl();
+ if (!stream.atEnd())
+ stream >> engineId;
+
+ // The second time around there will be specific engineIds.
+ // We only have to wait after the first, empty start message.
+ if (engineId == -1) {
+ // Wait until no engine registers within RegisterTimeout anymore.
+ foreach (QQmlEngine *engine, m_engineProfilers.keys().toSet()) {
+ if (enabled)
+ startProfiling(engine);
+ else
+ stopProfiling(engine);
+ }
} else {
- if (stopProfilingImpl())
- sendMessages();
- }
-
- // wake up constructor in blocking mode
- m_initializeCondition.wakeAll();
-}
-
-/*!
- * \brief QQmlVmeProfiler::Data::clear Reset to defaults
- * Reset the profiling data to defaults.
- */
-void QQmlVmeProfiler::Data::clear()
-{
- url.clear();
- line = 0;
- column = 0;
- typeName.clear();
-}
-
-/*!
- * \brief QQmlVmeProfiler::start Start profiler without data
- * Clears the current range data, then stops the profiler previously running in the
- * foreground if any, then starts a new one.
- */
-bool QQmlVmeProfiler::start()
-{
- if (QQmlProfilerService::enabled) {
- currentRange.clear();
- if (running)
- QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
+ if (enabled)
+ startProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)));
else
- running = true;
- QQmlProfilerService::instance->startRange(QQmlProfilerService::Creating);
- return true;
- }
- return false;
-}
-
-/*!
- * \brief QQmlVmeProfiler::updateLocation Update current location information
- * \param url URL of file being executed
- * \param line line Curent line in file
- * \param column column Current column in file
- * Updates the current profiler's location information.
- */
-void QQmlVmeProfiler::updateLocation(const QUrl &url, int line, int column)
-{
- if (QQmlProfilerService::enabled && running) {
- currentRange.url = url;
- currentRange.line = line;
- currentRange.column = column;
- QQmlProfilerService::instance->rangeLocation(
- QQmlProfilerService::Creating, url, line, column);
+ stopProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)));
}
-}
-
-/*!
- * \brief QQmlVmeProfiler::updateTypeName Update current type information
- * \param typeName Type of object being created
- * Updates the current profiler's type information.
- */
-void QQmlVmeProfiler::updateTypeName(const QString &typeName)
-{
- if (QQmlProfilerService::enabled && running) {
- currentRange.typeName = typeName;
- QQmlProfilerService::instance->rangeData(QQmlProfilerService::Creating, typeName);
- }
-}
-
-/*!
- * \brief QQmlVmeProfiler::pop Pops a paused profiler from the stack and restarts it
- * Stops the currently running profiler, if any, then retrieves an old one from the stack
- * of paused profilers and starts that.
- */
-void QQmlVmeProfiler::pop()
-{
- if (QQmlProfilerService::enabled && ranges.count() > 0) {
- start();
- currentRange = ranges.pop();
- QQmlProfilerService::instance->rangeLocation(
- QQmlProfilerService::Creating, currentRange.url, currentRange.line, currentRange.column);
- QQmlProfilerService::instance->rangeData(QQmlProfilerService::Creating, currentRange.typeName);
- }
-}
-/*!
- * \brief QQmlVmeProfiler::push Pushes the currently running profiler on the stack.
- * Pushes the currently running profiler on the stack of paused profilers. Note: The profiler
- * isn't paused here. That's a separate step. If it's never paused, but pop()'ed later that
- * won't do any harm, though.
- */
-void QQmlVmeProfiler::push()
-{
- if (QQmlProfilerService::enabled && running)
- ranges.push(currentRange);
-}
-
-/*!
- * \brief QQmlVmeProfiler::clear Stop all running profilers and clear all data.
- * Stops the currently running (foreground and background) profilers and removes all saved
- * data about paused profilers.
- */
-void QQmlVmeProfiler::clear()
-{
- stop();
- ranges.clear();
- if (QQmlProfilerService::enabled) {
- for (int i = 0; i < backgroundRanges.count(); ++i) {
- QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
- }
- }
- backgroundRanges.clear();
- running = false;
-}
-
-/*!
- * \brief QQmlVmeProfiler::stop Stop profiler running in the foreground, if any.
- */
-void QQmlVmeProfiler::stop()
-{
- if (QQmlProfilerService::enabled && running) {
- QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
- currentRange.clear();
- running = false;
- }
-}
-
-/*!
- * \brief QQmlVmeProfiler::background Push the current profiler to the background.
- * Push the profiler currently running in the foreground to the background so that it
- * won't be stopped by stop() or start(). There can be multiple profilers in the background.
- * You can retrieve them in reverse order by calling foreground().
- */
-void QQmlVmeProfiler::background()
-{
- if (QQmlProfilerService::enabled && running) {
- backgroundRanges.push(currentRange);
- running = false;
- }
-}
-
-/*!
- * \brief QQmlVmeProfiler::foreground Retrieve a profiler from the background
- * Stop the profiler currently running in the foreground, if any and put the next profiler
- * from the background in its place.
- */
-bool QQmlVmeProfiler::foreground()
-{
- if (QQmlProfilerService::enabled && backgroundRanges.count() > 0) {
- stop();
- currentRange = backgroundRanges.pop();
- running = true;
- return true;
- }
- return false;
+ stopWaiting();
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 32b88e3ec3..9e05424ce1 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -53,9 +53,11 @@
// We mean it.
//
-#include <private/qqmldebugservice_p.h>
+#include "qqmlconfigurabledebugservice_p.h"
+#include "qqmlprofilerdefinitions_p.h"
+#include "qqmlabstractprofileradapter_p.h"
+
#include <private/qqmlboundsignal_p.h>
-#include <private/qv4function_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetaobject.h>
@@ -64,313 +66,49 @@
#include <QtCore/qstringbuilder.h>
#include <QtCore/qwaitcondition.h>
-
QT_BEGIN_NAMESPACE
-struct Q_AUTOTEST_EXPORT QQmlProfilerData
-{
- qint64 time;
- int messageType;
- int detailType;
-
- //###
- QString detailData; //used by RangeData and RangeLocation
- int line; //used by RangeLocation, also as "width" for pixmaps
- int column; //used by RangeLocation, also as "height" for pixmaps
- int framerate; //used by animation events
- int animationcount; //used by animation events, also as "cache/reference count" for pixmaps
- int bindingType;
-
- qint64 subtime_1;
- qint64 subtime_2;
- qint64 subtime_3;
- qint64 subtime_4;
- qint64 subtime_5;
-
- QByteArray toByteArray() const;
-};
-
-Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
-
class QUrl;
class QQmlEngine;
-class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlConfigurableDebugService, public QQmlProfilerDefinitions
{
+ Q_OBJECT
public:
- enum Message {
- Event,
- RangeStart,
- RangeData,
- RangeLocation,
- RangeEnd,
- Complete, // end of transmission
- PixmapCacheEvent,
- SceneGraphFrame,
-
- MaximumMessage
- };
-
- enum EventType {
- FramePaint,
- Mouse,
- Key,
- AnimationFrame,
- EndTrace,
- StartTrace,
-
- MaximumEventType
- };
-
- enum RangeType {
- Painting,
- Compiling,
- Creating,
- Binding, //running a binding
- HandlingSignal, //running a signal handler
-
- MaximumRangeType
- };
-
- enum BindingType {
- QmlBinding,
- V8Binding,
- V4Binding,
- MaximumBindingType
- };
+ static QQmlProfilerService *instance();
+ void engineAboutToBeAdded(QQmlEngine *engine);
+ void engineAboutToBeRemoved(QQmlEngine *engine);
+ void engineAdded(QQmlEngine *engine);
+ void engineRemoved(QQmlEngine *engine);
- enum PixmapEventType {
- PixmapSizeKnown,
- PixmapReferenceCountChanged,
- PixmapCacheCountChanged,
- PixmapLoadingStarted,
- PixmapLoadingFinished,
- PixmapLoadingError,
+ void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
+ void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
- MaximumPixmapEventType
- };
-
- enum SceneGraphFrameType {
- SceneGraphRendererFrame,
- SceneGraphAdaptationLayerFrame,
- SceneGraphContextFrame,
- SceneGraphRenderLoopFrame,
- SceneGraphTexturePrepare,
- SceneGraphTextureDeletion,
- SceneGraphPolishAndSync,
- SceneGraphWindowsRenderShow,
- SceneGraphWindowsAnimations,
- SceneGraphWindowsPolishFrame,
-
- MaximumSceneGraphFrameType
- };
-
- static void initialize();
-
- static bool startProfiling();
- static bool stopProfiling();
- static void sendStartedProfilingMessage();
- static bool profilingEnabled();
-
- static void addEvent(EventType);
- static void animationFrame(qint64);
-
- static void sceneGraphFrame(SceneGraphFrameType frameType, qint64 value1, qint64 value2 = -1, qint64 value3 = -1, qint64 value4 = -1, qint64 value5 = -1);
- static void sendProfilingData();
+ void startProfiling(QQmlEngine *engine);
+ void stopProfiling(QQmlEngine *engine);
QQmlProfilerService();
~QQmlProfilerService();
+ void dataReady(QQmlAbstractProfilerAdapter *profiler);
+
protected:
virtual void stateAboutToBeChanged(State state);
virtual void messageReceived(const QByteArray &);
private:
- bool startProfilingImpl();
- bool stopProfilingImpl();
- void sendStartedProfilingMessageImpl();
- void addEventImpl(EventType);
- void animationFrameImpl(qint64);
- void startRange(RangeType, BindingType bindingType = QmlBinding);
- void rangeData(RangeType, const QString &);
- void rangeData(RangeType, const QUrl &);
- void rangeLocation(RangeType, const QString &, int, int);
- void rangeLocation(RangeType, const QUrl &, int, int);
- void endRange(RangeType);
-
- // overloading depending on parameters
- void pixmapEventImpl(PixmapEventType eventType, const QUrl &url);
- void pixmapEventImpl(PixmapEventType eventType, const QUrl &url, int width, int height);
- void pixmapEventImpl(PixmapEventType eventType, const QUrl &url, int count);
-
- void sceneGraphFrameImpl(SceneGraphFrameType frameType, qint64 value1, qint64 value2, qint64 value3, qint64 value4, qint64 value5);
-
-
- void setProfilingEnabled(bool enable);
void sendMessages();
- void processMessage(const QQmlProfilerData &);
+ void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine);
-public:
- static bool enabled;
-private:
QElapsedTimer m_timer;
- QVector<QQmlProfilerData> m_data;
- QMutex m_dataMutex;
- QMutex m_initializeMutex;
- QWaitCondition m_initializeCondition;
-
- static QQmlProfilerService *instance;
-
- friend struct QQmlBindingProfiler;
- friend struct QQmlHandlingSignalProfiler;
- friend struct QQmlVmeProfiler;
- friend struct QQmlCompilingProfiler;
- friend struct QQmlPixmapProfiler;
-};
-
-//
-// RAII helper structs
-//
-
-struct QQmlBindingProfiler {
- QQmlBindingProfiler(const QString &url, int line, int column, QQmlProfilerService::BindingType bindingType)
- {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->startRange(QQmlProfilerService::Binding, bindingType);
- QQmlProfilerService::instance->rangeLocation(QQmlProfilerService::Binding, url, line, column);
- }
- }
-
- ~QQmlBindingProfiler()
- {
- if (QQmlProfilerService::enabled)
- QQmlProfilerService::instance->endRange(QQmlProfilerService::Binding);
- }
-};
-
-struct QQmlHandlingSignalProfiler {
- QQmlHandlingSignalProfiler(QQmlBoundSignalExpression *expression)
- {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService *service = QQmlProfilerService::instance;
- service->startRange(QQmlProfilerService::HandlingSignal);
- if (expression->sourceFile().isEmpty()) {
- QV4::Function *function = expression->function();
- if (function) {
- service->rangeLocation(QQmlProfilerService::HandlingSignal,
- function->sourceFile(), function->compiledFunction->location.line,
- function->compiledFunction->location.column);
- }
- } else {
- service->rangeLocation(QQmlProfilerService::HandlingSignal,
- expression->sourceFile(), expression->lineNumber(),
- expression->columnNumber());
- }
- }
- }
-
- ~QQmlHandlingSignalProfiler()
- {
- if (QQmlProfilerService::enabled)
- QQmlProfilerService::instance->endRange(QQmlProfilerService::HandlingSignal);
- }
-};
-
-struct QQmlCompilingProfiler {
- QQmlCompilingProfiler(const QString &name)
- {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->startRange(QQmlProfilerService::Compiling);
- QQmlProfilerService::instance->rangeLocation(QQmlProfilerService::Compiling, name, 1, 1);
- QQmlProfilerService::instance->rangeData(QQmlProfilerService::Compiling, name);
- }
- }
-
- ~QQmlCompilingProfiler()
- {
- if (QQmlProfilerService::enabled)
- QQmlProfilerService::instance->endRange(QQmlProfilerService::Compiling);
- }
-};
-
-struct QQmlVmeProfiler {
-public:
-
- struct Data {
- Data() : line(0), column(0) {}
- QUrl url;
- int line;
- int column;
- QString typeName;
- void clear();
- };
-
- QQmlVmeProfiler() :
- running(false)
- {}
-
- ~QQmlVmeProfiler()
- {
- if (QQmlProfilerService::enabled)
- clear();
- }
-
- void clear();
-
- bool start();
- void stop();
-
- void updateLocation(const QUrl &url, int line, int column);
- void updateTypeName(const QString &typeName);
-
- void pop();
- void push();
-
- void background();
- bool foreground();
-
-private:
-
- Data currentRange;
- QStack<Data> ranges;
- QStack<Data> backgroundRanges;
- bool running;
-};
-struct QQmlPixmapProfiler {
- void startLoading(const QUrl &pixmapUrl) {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->pixmapEventImpl(QQmlProfilerService::PixmapLoadingStarted, pixmapUrl);
- }
- }
- void finishLoading(const QUrl &pixmapUrl) {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->pixmapEventImpl(QQmlProfilerService::PixmapLoadingFinished, pixmapUrl);
- }
- }
- void errorLoading(const QUrl &pixmapUrl) {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->pixmapEventImpl(QQmlProfilerService::PixmapLoadingError, pixmapUrl);
- }
- }
- void cacheCountChanged(const QUrl &pixmapUrl, int cacheCount) {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->pixmapEventImpl(QQmlProfilerService::PixmapCacheCountChanged, pixmapUrl, cacheCount);
- }
- }
- void referenceCountChanged(const QUrl &pixmapUrl, int referenceCount) {
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::instance->pixmapEventImpl(QQmlProfilerService::PixmapReferenceCountChanged, pixmapUrl, referenceCount);
- }
- }
- void setSize(const QUrl &pixmapUrl, const QSize &size) {
- if (QQmlProfilerService::enabled && size.width() > 0) {
- QQmlProfilerService::instance->pixmapEventImpl(QQmlProfilerService::PixmapSizeKnown, pixmapUrl, size.width(), size.height());
- }
- }
+ QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
+ QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
+ QList<QQmlEngine *> m_stoppingEngines;
+ QMultiMap<qint64, QQmlAbstractProfilerAdapter *> m_startTimes;
};
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
index 372a51e997..8e81d6e24e 100644
--- a/src/qml/debugger/qv4debugservice.cpp
+++ b/src/qml/debugger/qv4debugservice.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "qv4debugservice_p.h"
-#include "qqmldebugservice_p_p.h"
+#include "qqmlconfigurabledebugservice_p_p.h"
#include "qqmlengine.h"
#include "qv4debugging_p.h"
#include "qv4engine_p.h"
@@ -358,7 +358,7 @@ private:
QHash<QV4::Object *, int> objectRefs;
};
-class QV4DebugServicePrivate : public QQmlDebugServicePrivate
+class QV4DebugServicePrivate : public QQmlConfigurableDebugServicePrivate
{
Q_DECLARE_PUBLIC(QV4DebugService)
@@ -393,8 +393,6 @@ public:
void processCommand(const QByteArray &command, const QByteArray &data);
- QMutex initializeMutex;
- QWaitCondition initializeCondition;
QV4DebuggerAgent debuggerAgent;
QStringList breakOnSignals;
@@ -999,19 +997,9 @@ V8CommandHandler *QV4DebugServicePrivate::v8CommandHandler(const QString &comman
}
QV4DebugService::QV4DebugService(QObject *parent)
- : QQmlDebugService(*(new QV4DebugServicePrivate()),
+ : QQmlConfigurableDebugService(*(new QV4DebugServicePrivate()),
QStringLiteral("V8Debugger"), 1, parent)
-{
- Q_D(QV4DebugService);
-
- // don't execute stateChanged, messageReceived in parallel
- QMutexLocker lock(&d->initializeMutex);
-
- if (registerService() == Enabled && blockingMode()) {
- // let's wait for first message ...
- d->initializeCondition.wait(&d->initializeMutex);
- }
-}
+{}
QV4DebugService::~QV4DebugService()
{
@@ -1022,10 +1010,10 @@ QV4DebugService *QV4DebugService::instance()
return v4ServiceInstance();
}
-void QV4DebugService::addEngine(const QQmlEngine *engine)
+void QV4DebugService::engineAboutToBeAdded(QQmlEngine *engine)
{
Q_D(QV4DebugService);
-
+ QMutexLocker lock(configMutex());
if (engine) {
QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
if (QQmlDebugServer *server = QQmlDebugServer::instance()) {
@@ -1039,11 +1027,13 @@ void QV4DebugService::addEngine(const QQmlEngine *engine)
}
}
}
+ QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
}
-void QV4DebugService::removeEngine(const QQmlEngine *engine)
+void QV4DebugService::engineAboutToBeRemoved(QQmlEngine *engine)
{
Q_D(QV4DebugService);
+ QMutexLocker lock(configMutex());
if (engine){
const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
if (ee) {
@@ -1059,6 +1049,7 @@ void QV4DebugService::removeEngine(const QQmlEngine *engine)
d->debuggerAgent.removeDebugger(debugger);
}
}
+ QQmlConfigurableDebugService::engineAboutToBeRemoved(engine);
}
void QV4DebugService::signalEmitted(const QString &signal)
@@ -1080,22 +1071,10 @@ void QV4DebugService::signalEmitted(const QString &signal)
}
}
-void QV4DebugService::stateChanged(QQmlDebugService::State newState)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(&d->initializeMutex);
-
- if (newState != Enabled) {
- // wake up constructor in blocking mode
- // (we might got disabled before first message arrived)
- d->initializeCondition.wakeAll();
- }
-}
-
void QV4DebugService::messageReceived(const QByteArray &message)
{
Q_D(QV4DebugService);
- QMutexLocker lock(&d->initializeMutex);
+ QMutexLocker lock(configMutex());
QQmlDebugStream ms(message);
QByteArray header;
@@ -1111,7 +1090,7 @@ void QV4DebugService::messageReceived(const QByteArray &message)
if (type == V4_CONNECT) {
sendMessage(d->packMessage(type));
- d->initializeCondition.wakeAll();
+ stopWaiting();
} else if (type == V4_PAUSE) {
d->debuggerAgent.pauseAll();
sendSomethingToSomebody(type);
diff --git a/src/qml/debugger/qv4debugservice_p.h b/src/qml/debugger/qv4debugservice_p.h
index e35010bebf..d63d5fae1c 100644
--- a/src/qml/debugger/qv4debugservice_p.h
+++ b/src/qml/debugger/qv4debugservice_p.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
+#include "qqmlconfigurabledebugservice_p.h"
QT_BEGIN_NAMESPACE
@@ -61,7 +61,7 @@ namespace QV4 { struct ExecutionEngine; }
class QQmlEngine;
class QV4DebugServicePrivate;
-class QV4DebugService : public QQmlDebugService
+class QV4DebugService : public QQmlConfigurableDebugService
{
Q_OBJECT
public:
@@ -69,13 +69,12 @@ public:
~QV4DebugService();
static QV4DebugService *instance();
- void addEngine(const QQmlEngine *engine);
- void removeEngine(const QQmlEngine *engine);
+ void engineAboutToBeAdded(QQmlEngine *engine);
+ void engineAboutToBeRemoved(QQmlEngine *engine);
void signalEmitted(const QString &signal);
protected:
- void stateChanged(State newState);
void messageReceived(const QByteArray &);
void sendSomethingToSomebody(const char *type, int magicNumber = 1);
diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/qml/debugger/qv4profileradapter.cpp
new file mode 100644
index 0000000000..e7b82566d6
--- /dev/null
+++ b/src/qml/debugger/qv4profileradapter.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4profileradapter_p.h"
+#include "qqmlprofilerservice_p.h"
+#include "qqmldebugservice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
+ QQmlAbstractProfilerAdapter(service)
+{
+ engine->enableProfiler();
+ connect(this, SIGNAL(profilingEnabled()), engine->profiler, SLOT(startProfiling()));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting()), engine->profiler, SLOT(startProfiling()),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
+ engine->profiler, SLOT(setTimer(QElapsedTimer)));
+ connect(engine->profiler, SIGNAL(dataReady(QList<QV4::Profiling::FunctionCallProperties>)),
+ this, SLOT(receiveData(QList<QV4::Profiling::FunctionCallProperties>)));
+}
+
+
+qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ QByteArray message;
+ while (true) {
+ while (!stack.empty() && (data.empty() || stack.top() <= data.front().start)) {
+ if (stack.top() > until)
+ return stack.top();
+ QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ d << stack.pop() << RangeEnd << Javascript;
+ messages.append(message);
+ }
+ while (!data.empty() && (stack.empty() || data.front().start < stack.top())) {
+ if (data.front().start > until)
+ return data.front().start;
+ const QV4::Profiling::FunctionCallProperties &props = data.front();
+ QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
+ d_start << props.start << RangeStart << Javascript;
+ messages.push_back(message);
+ message.clear();
+ QQmlDebugStream d_location(&message, QIODevice::WriteOnly);
+ d_location << props.start << RangeLocation << Javascript << props.file << props.line
+ << props.column;
+ messages.push_back(message);
+ message.clear();
+ QQmlDebugStream d_data(&message, QIODevice::WriteOnly);
+ d_data << props.start << RangeData << Javascript << props.name;
+ messages.push_back(message);
+ message.clear();
+ stack.push(props.end);
+ data.pop_front();
+ }
+ if (stack.empty() && data.empty())
+ return -1;
+ }
+}
+
+void QV4ProfilerAdapter::receiveData(const QList<QV4::Profiling::FunctionCallProperties> &new_data)
+{
+ data = new_data;
+ stack.clear();
+ service->dataReady(this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/widgets/qquickqmessagebox_p.h b/src/qml/debugger/qv4profileradapter_p.h
index be91f1d02b..922aedd828 100644
--- a/src/imports/widgets/qquickqmessagebox_p.h
+++ b/src/qml/debugger/qv4profileradapter_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QQUICKQMESSAGEBOX_P_H
-#define QQUICKQMESSAGEBOX_P_H
+#ifndef QV4PROFILERADAPTER_P_H
+#define QV4PROFILERADAPTER_P_H
//
// W A R N I N G
@@ -53,25 +53,31 @@
// We mean it.
//
-#include "../dialogs/qquickabstractmessagedialog_p.h"
+#include "qv4profiling_p.h"
+#include "qqmlabstractprofileradapter_p.h"
+
+#include <QStack>
+#include <QList>
QT_BEGIN_NAMESPACE
-class QQuickQMessageBox : public QQuickAbstractMessageDialog
-{
+class QQmlProfilerService;
+class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
+
public:
- QQuickQMessageBox(QObject *parent = 0);
- virtual ~QQuickQMessageBox();
+ QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine);
-protected:
- virtual QPlatformDialogHelper *helper();
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
-protected:
- Q_DISABLE_COPY(QQuickQMessageBox)
+public slots:
+ void receiveData(const QList<QV4::Profiling::FunctionCallProperties> &);
+
+private:
+ QList<QV4::Profiling::FunctionCallProperties> data;
+ QStack<qint64> stack;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickQMessageBox *)
-
-#endif // QQUICKQMESSAGEBOX_P_H
+#endif // QV4PROFILERADAPTER_P_H
diff --git a/src/qml/debugger/qv8profilerservice.cpp b/src/qml/debugger/qv4profilerservice.cpp
index 7b9331da66..d8f69aecd9 100644
--- a/src/qml/debugger/qv8profilerservice.cpp
+++ b/src/qml/debugger/qv4profilerservice.cpp
@@ -39,9 +39,8 @@
**
****************************************************************************/
-#include "qv8profilerservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include <private/qv8profiler_p.h>
+#include "qv4profilerservice_p.h"
+#include "qqmlconfigurabledebugservice_p_p.h"
#include <QtCore/QHash>
#include <QtCore/QMutex>
@@ -49,7 +48,7 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance)
+Q_GLOBAL_STATIC(QV4ProfilerService, v4ProfilerInstance)
#if 0
// ### FIXME: v4
@@ -63,7 +62,7 @@ public:
{
QByteArray data;
QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size);
+ ds << QV4ProfilerService::V4SnapshotChunk << QByteArray(rawData, size);
messages.append(data);
return kContinue;
}
@@ -72,7 +71,7 @@ public:
#endif
// convert to a QByteArray that can be sent to the debug client
-QByteArray QV8ProfilerData::toByteArray() const
+QByteArray QV4ProfilerData::toByteArray() const
{
QByteArray data;
//### using QDataStream is relatively expensive
@@ -82,12 +81,12 @@ QByteArray QV8ProfilerData::toByteArray() const
return data;
}
-class QV8ProfilerServicePrivate : public QQmlDebugServicePrivate
+class QV4ProfilerServicePrivate : public QQmlConfigurableDebugServicePrivate
{
- Q_DECLARE_PUBLIC(QV8ProfilerService)
+ Q_DECLARE_PUBLIC(QV4ProfilerService)
public:
- QV8ProfilerServicePrivate()
+ QV4ProfilerServicePrivate()
:initialized(false)
{
}
@@ -97,46 +96,30 @@ public:
// void printProfileTree(const v8::CpuProfileNode *node, int level = 0);
// void sendMessages();
- QList<QV8ProfilerData> m_data;
+ QList<QV4ProfilerData> m_data;
bool initialized;
- QMutex initializeMutex;
- QWaitCondition initializeCondition;
QList<QString> m_ongoing;
};
-QV8ProfilerService::QV8ProfilerService(QObject *parent)
- : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QStringLiteral("V8Profiler"), 1, parent)
+QV4ProfilerService::QV4ProfilerService(QObject *parent)
+ : QQmlConfigurableDebugService(*(new QV4ProfilerServicePrivate()), QStringLiteral("V8Profiler"), 1, parent)
{
- Q_D(QV8ProfilerService);
-
- QMutexLocker lock(&d->initializeMutex);
-
- if (registerService() == Enabled
- && QQmlDebugService::blockingMode()) {
- // let's wait for first message ...
- d->initializeCondition.wait(&d->initializeMutex);
- }
}
-QV8ProfilerService::~QV8ProfilerService()
+QV4ProfilerService::~QV4ProfilerService()
{
}
-QV8ProfilerService *QV8ProfilerService::instance()
+QV4ProfilerService *QV4ProfilerService::instance()
{
- return v8ProfilerInstance();
+ return v4ProfilerInstance();
}
-void QV8ProfilerService::initialize()
+void QV4ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
{
- // just make sure that the service is properly registered
- v8ProfilerInstance();
-}
-
-void QV8ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
-{
- Q_D(QV8ProfilerService);
+ Q_D(QV4ProfilerService);
+ QMutexLocker lock(configMutex());
if (state() == newState)
return;
@@ -147,16 +130,12 @@ void QV8ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
Q_ARG(QString, title));
}
QMetaObject::invokeMethod(this, "sendProfilingData", Qt::BlockingQueuedConnection);
- } else {
- // wake up constructor in blocking mode
- // (we might got disabled before first message arrived)
- d->initializeCondition.wakeAll();
}
}
-void QV8ProfilerService::messageReceived(const QByteArray &message)
+void QV4ProfilerService::messageReceived(const QByteArray &message)
{
- Q_D(QV8ProfilerService);
+ Q_D(QV4ProfilerService);
QQmlDebugStream ds(message);
QByteArray command;
@@ -164,7 +143,7 @@ void QV8ProfilerService::messageReceived(const QByteArray &message)
QByteArray title;
ds >> command >> option;
- QMutexLocker lock(&d->initializeMutex);
+ QMutexLocker lock(configMutex());
if (command == "V8PROFILER") {
ds >> title;
@@ -187,14 +166,14 @@ void QV8ProfilerService::messageReceived(const QByteArray &message)
}
// wake up constructor in blocking mode
- d->initializeCondition.wakeAll();
+ stopWaiting();
QQmlDebugService::messageReceived(message);
}
-void QV8ProfilerService::startProfiling(const QString &title)
+void QV4ProfilerService::startProfiling(const QString &title)
{
- Q_D(QV8ProfilerService);
+ Q_D(QV4ProfilerService);
// Start Profiling
if (d->m_ongoing.contains(title))
@@ -209,14 +188,14 @@ void QV8ProfilerService::startProfiling(const QString &title)
// indicate profiling started
QByteArray data;
QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (int)QV8ProfilerService::V8Started;
+ ds << (int)QV4ProfilerService::V4Started;
sendMessage(data);
}
-void QV8ProfilerService::stopProfiling(const QString &title)
+void QV4ProfilerService::stopProfiling(const QString &title)
{
- Q_D(QV8ProfilerService);
+ Q_D(QV4ProfilerService);
// Stop profiling
if (!d->m_ongoing.contains(title))
@@ -237,7 +216,7 @@ void QV8ProfilerService::stopProfiling(const QString &title)
// indicate completion, even without data
QByteArray data;
QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (int)QV8ProfilerService::V8Complete;
+ ds << (int)QV4ProfilerService::V4Complete;
sendMessage(data);
#if 0
@@ -245,22 +224,22 @@ void QV8ProfilerService::stopProfiling(const QString &title)
#endif
}
-void QV8ProfilerService::takeSnapshot()
+void QV4ProfilerService::takeSnapshot()
{
-// Q_D(QV8ProfilerService);
+// Q_D(QV4ProfilerService);
// ### FIXME: v4
// d->takeSnapshot(v8::HeapSnapshot::kFull);
}
-void QV8ProfilerService::deleteSnapshots()
+void QV4ProfilerService::deleteSnapshots()
{
// ### FIXME: v4
// v8::HeapProfiler::DeleteAllSnapshots();
}
-void QV8ProfilerService::sendProfilingData()
+void QV4ProfilerService::sendProfilingData()
{
-// Q_D(QV8ProfilerService);
+// Q_D(QV4ProfilerService);
// Send messages to client
// ### FIXME: v4
// d->sendMessages();
@@ -268,14 +247,14 @@ void QV8ProfilerService::sendProfilingData()
#if 0
// ### FIXME: v4
-void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
+void QV4ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
{
for (int index = 0 ; index < node->GetChildrenCount() ; index++) {
const v8::CpuProfileNode* childNode = node->GetChild(index);
QString scriptResourceName = QJSConverter::toString(childNode->GetScriptResourceName());
if (scriptResourceName.length() > 0) {
- QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, scriptResourceName,
+ QV4ProfilerData rd = {(int)QV4ProfilerService::V4Entry, scriptResourceName,
QJSConverter::toString(childNode->GetFunctionName()),
childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level};
m_data.append(rd);
@@ -288,9 +267,9 @@ void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node,
}
}
-void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
+void QV4ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
{
- Q_Q(QV8ProfilerService);
+ Q_Q(QV4ProfilerService);
v8::HandleScope scope;
v8::Handle<v8::String> title = v8::String::New("");
@@ -303,15 +282,15 @@ void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType
//indicate completion
QByteArray data;
QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (int)QV8ProfilerService::V8SnapshotComplete;
+ ds << (int)QV4ProfilerService::V4SnapshotComplete;
messages.append(data);
q->sendMessages(messages);
}
-void QV8ProfilerServicePrivate::sendMessages()
+void QV4ProfilerServicePrivate::sendMessages()
{
- Q_Q(QV8ProfilerService);
+ Q_Q(QV4ProfilerService);
QList<QByteArray> messages;
for (int i = 0; i < m_data.count(); ++i)
@@ -321,7 +300,7 @@ void QV8ProfilerServicePrivate::sendMessages()
//indicate completion
QByteArray data;
QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (int)QV8ProfilerService::V8Complete;
+ ds << (int)QV4ProfilerService::V4Complete;
messages.append(data);
q->sendMessages(messages);
diff --git a/src/qml/debugger/qv8profilerservice_p.h b/src/qml/debugger/qv4profilerservice_p.h
index 60dc70f4db..b1a58dae03 100644
--- a/src/qml/debugger/qv8profilerservice_p.h
+++ b/src/qml/debugger/qv4profilerservice_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QV8PROFILERSERVICE_P_H
-#define QV8PROFILERSERVICE_P_H
+#ifndef QV4PROFILERSERVICE_P_H
+#define QV4PROFILERSERVICE_P_H
//
// W A R N I N G
@@ -53,12 +53,12 @@
// We mean it.
//
-#include <private/qqmldebugservice_p.h>
+#include <private/qqmlconfigurabledebugservice_p.h>
QT_BEGIN_NAMESPACE
-struct Q_AUTOTEST_EXPORT QV8ProfilerData
+struct Q_AUTOTEST_EXPORT QV4ProfilerData
{
int messageType;
QString filename;
@@ -72,27 +72,26 @@ struct Q_AUTOTEST_EXPORT QV8ProfilerData
};
class QQmlEngine;
-class QV8ProfilerServicePrivate;
+class QV4ProfilerServicePrivate;
-class Q_AUTOTEST_EXPORT QV8ProfilerService : public QQmlDebugService
+class Q_AUTOTEST_EXPORT QV4ProfilerService : public QQmlConfigurableDebugService
{
Q_OBJECT
public:
enum MessageType {
- V8Entry,
- V8Complete,
- V8SnapshotChunk,
- V8SnapshotComplete,
- V8Started,
+ V4Entry,
+ V4Complete,
+ V4SnapshotChunk,
+ V4SnapshotComplete,
+ V4Started,
- V8MaximumMessage
+ V4MaximumMessage
};
- QV8ProfilerService(QObject *parent = 0);
- ~QV8ProfilerService();
+ QV4ProfilerService(QObject *parent = 0);
+ ~QV4ProfilerService();
- static QV8ProfilerService *instance();
- static void initialize();
+ static QV4ProfilerService *instance();
public Q_SLOTS:
void startProfiling(const QString &title);
@@ -107,10 +106,10 @@ protected:
void messageReceived(const QByteArray &);
private:
- Q_DISABLE_COPY(QV8ProfilerService)
- Q_DECLARE_PRIVATE(QV8ProfilerService)
+ Q_DISABLE_COPY(QV4ProfilerService)
+ Q_DECLARE_PRIVATE(QV4ProfilerService)
};
QT_END_NAMESPACE
-#endif // QV8PROFILERSERVICE_P_H
+#endif // QV4PROFILERSERVICE_P_H
diff --git a/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml b/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml
index 1e8cfade96..f46671e9a0 100644
--- a/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml
+++ b/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml
@@ -55,7 +55,7 @@ ListView {
MouseArea {
anchors.fill: parent
onClicked: {
- if (model.hasModelChildren)
+ if (model.hasModelChildren)
view.model.rootIndex = view.model.modelIndex(index)
}
}
diff --git a/src/qml/doc/snippets/qml/SelfDestroyingRect.qml b/src/qml/doc/snippets/qml/SelfDestroyingRect.qml
index b2e8c318f2..16a73c204d 100644
--- a/src/qml/doc/snippets/qml/SelfDestroyingRect.qml
+++ b/src/qml/doc/snippets/qml/SelfDestroyingRect.qml
@@ -45,9 +45,9 @@ Rectangle {
width: 80; height: 80
color: "red"
- NumberAnimation on opacity {
+ NumberAnimation on opacity {
to: 0
- duration: 1000
+ duration: 1000
onRunningChanged: {
if (!running) {
diff --git a/src/qml/doc/snippets/qml/createQmlObject.qml b/src/qml/doc/snippets/qml/createQmlObject.qml
index 7984261f0f..10f49f13c3 100644
--- a/src/qml/doc/snippets/qml/createQmlObject.qml
+++ b/src/qml/doc/snippets/qml/createQmlObject.qml
@@ -45,7 +45,7 @@ Rectangle {
width: 100
height: 100
-
+
function createIt() {
//![0]
var newObject = Qt.createQmlObject('import QtQuick 2.0; Rectangle {color: "red"; width: 20; height: 20}',
diff --git a/src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml b/src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml
index c9637712f6..3c836d81cf 100644
--- a/src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml
+++ b/src/qml/doc/snippets/qml/listmodel/listmodel-nested.qml
@@ -86,7 +86,7 @@ Component {
Text { text: "Attributes:" }
Repeater {
model: attributes
- Text { text: description }
+ Text { text: description }
}
}
}
diff --git a/src/qml/doc/snippets/qml/qml-documents/inline-component.qml b/src/qml/doc/snippets/qml/qml-documents/inline-component.qml
index 5b600499c4..b8144c263f 100644
--- a/src/qml/doc/snippets/qml/qml-documents/inline-component.qml
+++ b/src/qml/doc/snippets/qml/qml-documents/inline-component.qml
@@ -42,7 +42,7 @@
import QtQuick 2.0
Rectangle {
- width: 240; height: 320;
+ width: 240; height: 320;
ListView {
anchors.fill: parent
@@ -52,6 +52,6 @@ Rectangle {
text: modelData.firstName + " " + modelData.lastName
}
}
- }
+ }
}
//! [document]
diff --git a/src/qml/doc/snippets/qml/qml-documents/inline-text-component.qml b/src/qml/doc/snippets/qml/qml-documents/inline-text-component.qml
index 44d67a7480..e731ce998f 100644
--- a/src/qml/doc/snippets/qml/qml-documents/inline-text-component.qml
+++ b/src/qml/doc/snippets/qml/qml-documents/inline-text-component.qml
@@ -42,7 +42,7 @@
import QtQuick 2.0
Rectangle {
- width: 240; height: 320;
+ width: 240; height: 320;
ListView {
anchors.fill: parent
@@ -50,6 +50,6 @@ Rectangle {
delegate: Text {
text: modelData.firstName + " " + modelData.lastName
}
- }
+ }
}
//! [document]
diff --git a/src/qml/doc/snippets/qml/qml-documents/non-trivial.qml b/src/qml/doc/snippets/qml/qml-documents/non-trivial.qml
index ccf4603b44..cedd09d3ce 100644
--- a/src/qml/doc/snippets/qml/qml-documents/non-trivial.qml
+++ b/src/qml/doc/snippets/qml/qml-documents/non-trivial.qml
@@ -42,7 +42,7 @@
import QtQuick 2.0
Rectangle {
- width: 240; height: 320;
+ width: 240; height: 320;
resources: [
Component {
@@ -57,6 +57,6 @@ Rectangle {
anchors.fill: parent
model: contactModel
delegate: contactDelegate
- }
+ }
}
//! [document]
diff --git a/src/qml/doc/snippets/qml/qml-documents/qmldocuments.qml b/src/qml/doc/snippets/qml/qml-documents/qmldocuments.qml
index 66322fdfd1..fd582db061 100644
--- a/src/qml/doc/snippets/qml/qml-documents/qmldocuments.qml
+++ b/src/qml/doc/snippets/qml/qml-documents/qmldocuments.qml
@@ -45,7 +45,7 @@ Rectangle {
property alias text: textItem.text
width: 100; height: 30
- border.width: 1
+ border.width: 1
radius: 5
antialiasing: true
diff --git a/src/qml/doc/snippets/qml/qtobject.qml b/src/qml/doc/snippets/qml/qtobject.qml
index 7d0957326e..6fdf7f74d3 100644
--- a/src/qml/doc/snippets/qml/qtobject.qml
+++ b/src/qml/doc/snippets/qml/qtobject.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
Item {
- QtObject {
+ QtObject {
id: attributes
property string name
property int size
diff --git a/src/qml/jit/jit.pri b/src/qml/jit/jit.pri
new file mode 100644
index 0000000000..151ff32df9
--- /dev/null
+++ b/src/qml/jit/jit.pri
@@ -0,0 +1,20 @@
+include(../../3rdparty/masm/masm-defs.pri)
+
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$OUT_PWD
+
+HEADERS += \
+ $$PWD/qv4assembler_p.h \
+ $$PWD/qv4regalloc_p.h \
+ $$PWD/qv4isel_masm_p.h \
+ $$PWD/qv4binop_p.h \
+ $$PWD/qv4unop_p.h \
+
+SOURCES += \
+ $$PWD/qv4assembler.cpp \
+ $$PWD/qv4regalloc.cpp \
+ $$PWD/qv4isel_masm.cpp \
+ $$PWD/qv4binop.cpp \
+ $$PWD/qv4unop.cpp \
+
+include(../../3rdparty/masm/masm.pri)
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
new file mode 100644
index 0000000000..0cede2a2f1
--- /dev/null
+++ b/src/qml/jit/qv4assembler.cpp
@@ -0,0 +1,468 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4isel_masm_p.h"
+#include "qv4runtime_p.h"
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+#include "qv4regexpobject_p.h"
+#include "qv4lookup_p.h"
+#include "qv4function_p.h"
+#include "qv4ssa_p.h"
+#include "qv4regalloc_p.h"
+#include "qv4assembler_p.h"
+
+#include <assembler/LinkBuffer.h>
+#include <WTFStubs.h>
+
+#include <iostream>
+#include <cassert>
+
+#if ENABLE(ASSEMBLER)
+
+#if USE(UDIS86)
+# include <udis86.h>
+#endif
+
+using namespace QV4;
+using namespace QV4::JIT;
+
+CompilationUnit::~CompilationUnit()
+{
+ foreach (Function *f, runtimeFunctions)
+ engine->allFunctions.remove(reinterpret_cast<quintptr>(f->code));
+}
+
+void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
+{
+ runtimeFunctions.resize(data->functionTableSize);
+ runtimeFunctions.fill(0);
+ for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
+ const CompiledData::Function *compiledFunction = data->functionAt(i);
+
+ QV4::Function *runtimeFunction = new QV4::Function(engine, this, compiledFunction,
+ (ReturnedValue (*)(QV4::ExecutionContext *, const uchar *)) codeRefs[i].code().executableAddress(),
+ codeSizes[i]);
+ runtimeFunctions[i] = runtimeFunction;
+ }
+
+ foreach (Function *f, runtimeFunctions)
+ engine->allFunctions.insert(reinterpret_cast<quintptr>(f->code), f);
+}
+
+QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int functionIndex)
+{
+ if (functionIndex < 0 || functionIndex >= codeRefs.count())
+ return 0;
+ JSC::ExecutableMemoryHandle *handle = codeRefs[functionIndex].executableMemory();
+ if (!handle)
+ return 0;
+ return handle->chunk();
+}
+
+
+
+/* Platform/Calling convention/Architecture specific section */
+
+#if CPU(X86_64)
+static const Assembler::RegisterID calleeSavedRegisters[] = {
+ // Not used: JSC::X86Registers::rbx,
+ // Not used: JSC::X86Registers::r10,
+ JSC::X86Registers::r12, // LocalsRegister
+ // Not used: JSC::X86Registers::r13,
+ JSC::X86Registers::r14 // ContextRegister
+ // Not used: JSC::X86Registers::r15,
+};
+#endif
+
+#if CPU(X86)
+static const Assembler::RegisterID calleeSavedRegisters[] = {
+ JSC::X86Registers::ebx, // temporary register
+ JSC::X86Registers::esi, // ContextRegister
+ JSC::X86Registers::edi // LocalsRegister
+};
+#endif
+
+#if CPU(ARM)
+static const Assembler::RegisterID calleeSavedRegisters[] = {
+ JSC::ARMRegisters::r11,
+ JSC::ARMRegisters::r10,
+ JSC::ARMRegisters::r9,
+ JSC::ARMRegisters::r8,
+ JSC::ARMRegisters::r7,
+ JSC::ARMRegisters::r6,
+ JSC::ARMRegisters::r5,
+ JSC::ARMRegisters::r4
+};
+#endif
+
+const int Assembler::calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
+
+/* End of platform/calling convention/architecture specific section */
+
+
+const Assembler::VoidType Assembler::Void;
+
+Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
+ int maxArgCountForBuiltins)
+ : _stackLayout(function, maxArgCountForBuiltins)
+ , _constTable(this)
+ , _function(function)
+ , _nextBlock(0)
+ , _executableAllocator(executableAllocator)
+ , _isel(isel)
+{
+}
+
+void Assembler::registerBlock(IR::BasicBlock* block, IR::BasicBlock *nextBlock)
+{
+ _addrs[block] = label();
+ catchBlock = block->catchBlock;
+ _nextBlock = nextBlock;
+}
+
+void Assembler::jumpToBlock(IR::BasicBlock* current, IR::BasicBlock *target)
+{
+ Q_UNUSED(current);
+
+ if (target != _nextBlock)
+ _patches[target].append(jump());
+}
+
+void Assembler::addPatch(IR::BasicBlock* targetBlock, Jump targetJump)
+{
+ _patches[targetBlock].append(targetJump);
+}
+
+void Assembler::addPatch(DataLabelPtr patch, Label target)
+{
+ DataLabelPatch p;
+ p.dataLabel = patch;
+ p.target = target;
+ _dataLabelPatches.append(p);
+}
+
+void Assembler::addPatch(DataLabelPtr patch, IR::BasicBlock *target)
+{
+ _labelPatches[target].append(patch);
+}
+
+void Assembler::generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBlock,
+ IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock)
+{
+ generateCJumpOnCompare(NotEqual, reg, TrustedImm32(0), currentBlock, trueBlock, falseBlock);
+}
+
+void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left,TrustedImm32 right,
+ IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ if (trueBlock == _nextBlock) {
+ Jump target = branch32(invert(cond), left, right);
+ addPatch(falseBlock, target);
+ } else {
+ Jump target = branch32(cond, left, right);
+ addPatch(trueBlock, target);
+ jumpToBlock(currentBlock, falseBlock);
+ }
+}
+
+void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left, RegisterID right,
+ IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ if (trueBlock == _nextBlock) {
+ Jump target = branch32(invert(cond), left, right);
+ addPatch(falseBlock, target);
+ } else {
+ Jump target = branch32(cond, left, right);
+ addPatch(trueBlock, target);
+ jumpToBlock(currentBlock, falseBlock);
+ }
+}
+
+Assembler::Pointer Assembler::loadTempAddress(RegisterID baseReg, IR::Temp *t)
+{
+ int32_t offset = 0;
+ int scope = t->scope;
+ RegisterID context = ContextRegister;
+ if (scope) {
+ loadPtr(Address(ContextRegister, qOffsetOf(ExecutionContext, outer)), baseReg);
+ --scope;
+ context = baseReg;
+ while (scope) {
+ loadPtr(Address(context, qOffsetOf(ExecutionContext, outer)), context);
+ --scope;
+ }
+ }
+ switch (t->kind) {
+ case IR::Temp::Formal:
+ case IR::Temp::ScopedFormal: {
+ loadPtr(Address(context, qOffsetOf(ExecutionContext, callData)), baseReg);
+ offset = sizeof(CallData) + (t->index - 1) * sizeof(Value);
+ } break;
+ case IR::Temp::Local:
+ case IR::Temp::ScopedLocal: {
+ loadPtr(Address(context, qOffsetOf(CallContext, locals)), baseReg);
+ offset = t->index * sizeof(Value);
+ } break;
+ case IR::Temp::StackSlot: {
+ return stackSlotPointer(t);
+ } break;
+ default:
+ Q_UNREACHABLE();
+ }
+ return Pointer(baseReg, offset);
+}
+
+Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &string)
+{
+ loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, compilationUnit)), Assembler::ScratchRegister);
+ loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
+ const int id = _isel->registerString(string);
+ return Pointer(reg, id * sizeof(QV4::StringValue));
+}
+
+void Assembler::loadStringRef(RegisterID reg, const QString &string)
+{
+ loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, compilationUnit)), reg);
+ loadPtr(Address(reg, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
+ const int id = _isel->registerString(string);
+ addPtr(TrustedImmPtr(id * sizeof(QV4::StringValue)), reg);
+}
+
+void Assembler::storeValue(QV4::Primitive value, IR::Temp* destination)
+{
+ Address addr = loadTempAddress(ScratchRegister, destination);
+ storeValue(value, addr);
+}
+
+void Assembler::enterStandardStackFrame()
+{
+ platformEnterStandardStackFrame();
+
+ // ### FIXME: Handle through calleeSavedRegisters mechanism
+ // or eliminate StackFrameRegister altogether.
+ push(StackFrameRegister);
+ move(StackPointerRegister, StackFrameRegister);
+
+ int frameSize = _stackLayout.calculateStackFrameSize();
+
+ subPtr(TrustedImm32(frameSize), StackPointerRegister);
+
+ for (int i = 0; i < calleeSavedRegisterCount; ++i)
+ storePtr(calleeSavedRegisters[i], Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
+
+}
+
+void Assembler::leaveStandardStackFrame()
+{
+ // restore the callee saved registers
+ for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
+ loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i]);
+
+ int frameSize = _stackLayout.calculateStackFrameSize();
+ // Work around bug in ARMv7Assembler.h where add32(imm, sp, sp) doesn't
+ // work well for large immediates.
+#if CPU(ARM_THUMB2)
+ move(TrustedImm32(frameSize), JSC::ARMRegisters::r3);
+ add32(JSC::ARMRegisters::r3, StackPointerRegister);
+#else
+ addPtr(TrustedImm32(frameSize), StackPointerRegister);
+#endif
+
+ pop(StackFrameRegister);
+ platformLeaveStandardStackFrame();
+}
+
+
+
+#define OP(op) \
+ { isel_stringIfy(op), op, 0, 0, 0 }
+#define OPCONTEXT(op) \
+ { isel_stringIfy(op), 0, op, 0, 0 }
+
+#define INLINE_OP(op, memOp, immOp) \
+ { isel_stringIfy(op), op, 0, memOp, immOp }
+#define INLINE_OPCONTEXT(op, memOp, immOp) \
+ { isel_stringIfy(op), 0, op, memOp, immOp }
+
+#define NULL_OP \
+ { 0, 0, 0, 0, 0 }
+
+const Assembler::BinaryOperationInfo Assembler::binaryOperations[IR::LastAluOp + 1] = {
+ NULL_OP, // OpInvalid
+ NULL_OP, // OpIfTrue
+ NULL_OP, // OpNot
+ NULL_OP, // OpUMinus
+ NULL_OP, // OpUPlus
+ NULL_OP, // OpCompl
+ NULL_OP, // OpIncrement
+ NULL_OP, // OpDecrement
+
+ INLINE_OP(__qmljs_bit_and, &Assembler::inline_and32, &Assembler::inline_and32), // OpBitAnd
+ INLINE_OP(__qmljs_bit_or, &Assembler::inline_or32, &Assembler::inline_or32), // OpBitOr
+ INLINE_OP(__qmljs_bit_xor, &Assembler::inline_xor32, &Assembler::inline_xor32), // OpBitXor
+
+ INLINE_OPCONTEXT(__qmljs_add, &Assembler::inline_add32, &Assembler::inline_add32), // OpAdd
+ INLINE_OP(__qmljs_sub, &Assembler::inline_sub32, &Assembler::inline_sub32), // OpSub
+ INLINE_OP(__qmljs_mul, &Assembler::inline_mul32, &Assembler::inline_mul32), // OpMul
+
+ OP(__qmljs_div), // OpDiv
+ OP(__qmljs_mod), // OpMod
+
+ INLINE_OP(__qmljs_shl, &Assembler::inline_shl32, &Assembler::inline_shl32), // OpLShift
+ INLINE_OP(__qmljs_shr, &Assembler::inline_shr32, &Assembler::inline_shr32), // OpRShift
+ INLINE_OP(__qmljs_ushr, &Assembler::inline_ushr32, &Assembler::inline_ushr32), // OpURShift
+
+ OP(__qmljs_gt), // OpGt
+ OP(__qmljs_lt), // OpLt
+ OP(__qmljs_ge), // OpGe
+ OP(__qmljs_le), // OpLe
+ OP(__qmljs_eq), // OpEqual
+ OP(__qmljs_ne), // OpNotEqual
+ OP(__qmljs_se), // OpStrictEqual
+ OP(__qmljs_sne), // OpStrictNotEqual
+
+ OPCONTEXT(__qmljs_instanceof), // OpInstanceof
+ OPCONTEXT(__qmljs_in), // OpIn
+
+ NULL_OP, // OpAnd
+ NULL_OP // OpOr
+};
+
+
+// Try to load the source expression into the destination FP register. This assumes that two
+// general purpose (integer) registers are available: the ScratchRegister and the
+// ReturnValueRegister. It returns a Jump if no conversion can be performed.
+Assembler::Jump Assembler::genTryDoubleConversion(IR::Expr *src, Assembler::FPRegisterID dest)
+{
+ switch (src->type) {
+ case IR::DoubleType:
+ moveDouble(toDoubleRegister(src, dest), dest);
+ return Assembler::Jump();
+ case IR::SInt32Type:
+ convertInt32ToDouble(toInt32Register(src, Assembler::ScratchRegister),
+ dest);
+ return Assembler::Jump();
+ case IR::UInt32Type:
+ convertUInt32ToDouble(toUInt32Register(src, Assembler::ScratchRegister),
+ dest, Assembler::ReturnValueRegister);
+ return Assembler::Jump();
+ case IR::BoolType:
+ // TODO?
+ return jump();
+ default:
+ break;
+ }
+
+ IR::Temp *sourceTemp = src->asTemp();
+ Q_ASSERT(sourceTemp);
+
+ // It's not a number type, so it cannot be in a register.
+ Q_ASSERT(sourceTemp->kind != IR::Temp::PhysicalRegister || sourceTemp->type == IR::BoolType);
+
+ Assembler::Pointer tagAddr = loadTempAddress(Assembler::ScratchRegister, sourceTemp);
+ tagAddr.offset += 4;
+ load32(tagAddr, Assembler::ScratchRegister);
+
+ // check if it's an int32:
+ Assembler::Jump isNoInt = branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::_Integer_Type));
+ convertInt32ToDouble(toInt32Register(src, Assembler::ScratchRegister), dest);
+ Assembler::Jump intDone = jump();
+
+ // not an int, check if it's a double:
+ isNoInt.link(this);
+#if QT_POINTER_SIZE == 8
+ and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
+ Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(0));
+#else
+ and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
+ Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::NotDouble_Mask));
+#endif
+ toDoubleRegister(src, dest);
+ intDone.link(this);
+
+ return isNoDbl;
+}
+
+#ifndef QT_NO_DEBUG
+namespace {
+inline bool isPregOrConst(IR::Expr *e)
+{
+ if (IR::Temp *t = e->asTemp())
+ return t->kind == IR::Temp::PhysicalRegister;
+ return e->asConst() != 0;
+}
+} // anonymous namespace
+#endif
+
+Assembler::Jump Assembler::branchDouble(bool invertCondition, IR::AluOp op,
+ IR::Expr *left, IR::Expr *right)
+{
+ Q_ASSERT(isPregOrConst(left));
+ Q_ASSERT(isPregOrConst(right));
+ Q_ASSERT(left->asConst() == 0 || right->asConst() == 0);
+
+ Assembler::DoubleCondition cond;
+ switch (op) {
+ case IR::OpGt: cond = Assembler::DoubleGreaterThan; break;
+ case IR::OpLt: cond = Assembler::DoubleLessThan; break;
+ case IR::OpGe: cond = Assembler::DoubleGreaterThanOrEqual; break;
+ case IR::OpLe: cond = Assembler::DoubleLessThanOrEqual; break;
+ case IR::OpEqual:
+ case IR::OpStrictEqual: cond = Assembler::DoubleEqual; break;
+ case IR::OpNotEqual:
+ case IR::OpStrictNotEqual: cond = Assembler::DoubleNotEqualOrUnordered; break; // No, the inversion of DoubleEqual is NOT DoubleNotEqual.
+ default:
+ Q_UNREACHABLE();
+ }
+ if (invertCondition)
+ cond = JSC::MacroAssembler::invert(cond);
+
+ return JSC::MacroAssembler::branchDouble(cond, toDoubleRegister(left), toDoubleRegister(right));
+}
+
+
+#endif
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/jit/qv4assembler_p.h
index 7dfe6a820a..bc379386d4 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -38,14 +38,14 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QV4ISEL_MASM_P_H
-#define QV4ISEL_MASM_P_H
+#ifndef QV4ASSEMBLER_P_H
+#define QV4ASSEMBLER_P_H
#include "private/qv4global_p.h"
-#include "qv4jsir_p.h"
-#include "qv4isel_p.h"
-#include "qv4isel_util_p.h"
-#include "private/qv4value_def_p.h"
+#include "private/qv4jsir_p.h"
+#include "private/qv4isel_p.h"
+#include "private/qv4isel_util_p.h"
+#include "private/qv4value_p.h"
#include "private/qv4lookup_p.h"
#include <QtCore/QHash>
@@ -60,9 +60,13 @@
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
-namespace MASM {
+namespace QV4 {
+namespace JIT {
+#define OP(op) \
+ { isel_stringIfy(op), op, 0, 0, 0 }
+#define OPCONTEXT(op) \
+ { isel_stringIfy(op), 0, op, 0, 0 }
class InstructionSelection;
@@ -124,7 +128,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowContext *, A, B, C)> {
class Assembler : public JSC::MacroAssembler
{
public:
- Assembler(InstructionSelection *isel, V4IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
+ Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
int maxArgCountForBuiltins);
#if CPU(X86)
@@ -140,8 +144,8 @@ public:
static const RegisterID ContextRegister = JSC::X86Registers::esi;
static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
static const RegisterID ScratchRegister = JSC::X86Registers::ecx;
- static const RegisterID IntegerOpRegister = JSC::X86Registers::eax;
static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
+ static const FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
static const int RegisterSize = 4;
@@ -170,7 +174,6 @@ public:
static const RegisterID ContextRegister = JSC::X86Registers::r14;
static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
static const RegisterID ScratchRegister = JSC::X86Registers::r10;
- static const RegisterID IntegerOpRegister = JSC::X86Registers::eax;
static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
static const FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
@@ -224,8 +227,8 @@ public:
static const RegisterID ContextRegister = JSC::ARMRegisters::r5;
static const RegisterID ReturnValueRegister = JSC::ARMRegisters::r0;
static const RegisterID ScratchRegister = JSC::ARMRegisters::r6;
- static const RegisterID IntegerOpRegister = JSC::ARMRegisters::r0;
static const FPRegisterID FPGpr0 = JSC::ARMRegisters::d0;
+ static const FPRegisterID FPGpr1 = JSC::ARMRegisters::d1;
static const int RegisterSize = 4;
@@ -316,7 +319,7 @@ public:
class StackLayout
{
public:
- StackLayout(V4IR::Function *function, int maxArgCountForBuiltins)
+ StackLayout(IR::Function *function, int maxArgCountForBuiltins)
: calleeSavedRegCount(Assembler::calleeSavedRegisterCount + 1)
, maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
@@ -351,7 +354,7 @@ public:
// space for the callee saved registers
int frameSize = RegisterSize * calleeSavedRegisterCount;
- frameSize += savedRegCount * sizeof(QV4::SafeValue); // these get written out as Values, not as native registers
+ frameSize += savedRegCount * sizeof(QV4::Value); // these get written out as Values, not as native registers
frameSize = WTF::roundUpToMultipleOf(StackAlignment, frameSize + stackSpaceAllocatedOtherwise);
frameSize -= stackSpaceAllocatedOtherwise;
@@ -361,8 +364,8 @@ public:
int calculateJSStackFrameSize() const
{
- const int locals = (localCount + sizeof(QV4::CallData)/sizeof(QV4::SafeValue) - 1 + maxOutgoingArgumentCount) + 1;
- int frameSize = locals * sizeof(QV4::SafeValue);
+ const int locals = (localCount + sizeof(QV4::CallData)/sizeof(QV4::Value) - 1 + maxOutgoingArgumentCount) + 1;
+ int frameSize = locals * sizeof(QV4::Value);
return frameSize;
}
@@ -372,7 +375,7 @@ public:
Q_ASSERT(idx < localCount);
Pointer addr = callDataAddress(0);
- addr.offset -= sizeof(QV4::SafeValue) * (idx + 1);
+ addr.offset -= sizeof(QV4::Value) * (idx + 1);
return addr;
}
@@ -384,11 +387,11 @@ public:
Q_ASSERT(argument < maxOutgoingArgumentCount);
const int index = maxOutgoingArgumentCount - argument;
- return Pointer(Assembler::LocalsRegister, sizeof(QV4::SafeValue) * (-index));
+ return Pointer(Assembler::LocalsRegister, sizeof(QV4::Value) * (-index));
}
Pointer callDataAddress(int offset = 0) const {
- return Pointer(Assembler::LocalsRegister, -(sizeof(QV4::CallData) + sizeof(QV4::SafeValue) * (maxOutgoingArgumentCount - 1)) + offset);
+ return Pointer(Assembler::LocalsRegister, -(sizeof(QV4::CallData) + sizeof(QV4::Value) * (maxOutgoingArgumentCount - 1)) + offset);
}
Address savedRegPointer(int offset) const
@@ -396,7 +399,7 @@ public:
Q_ASSERT(offset >= 0);
Q_ASSERT(offset < savedRegCount);
- const int off = offset * sizeof(QV4::SafeValue);
+ const int off = offset * sizeof(QV4::Value);
return Address(Assembler::StackFrameRegister, - calleeSavedRegisterSpace() - off);
}
@@ -426,7 +429,7 @@ public:
ConstantTable(Assembler *as): _as(as) {}
int add(const QV4::Primitive &v);
- ImplicitAddress loadValueAddress(V4IR::Const *c, RegisterID baseReg);
+ ImplicitAddress loadValueAddress(IR::Const *c, RegisterID baseReg);
ImplicitAddress loadValueAddress(const QV4::Primitive &v, RegisterID baseReg);
void finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel);
@@ -447,23 +450,23 @@ public:
const char* functionName;
};
struct PointerToValue {
- PointerToValue(V4IR::Expr *value)
+ PointerToValue(IR::Expr *value)
: value(value)
{}
- V4IR::Expr *value;
+ IR::Expr *value;
};
struct PointerToString {
explicit PointerToString(const QString &string) : string(string) {}
QString string;
};
struct Reference {
- Reference(V4IR::Temp *value) : value(value) {}
- V4IR::Temp *value;
+ Reference(IR::Temp *value) : value(value) {}
+ IR::Temp *value;
};
struct ReentryBlock {
- ReentryBlock(V4IR::BasicBlock *b) : block(b) {}
- V4IR::BasicBlock *block;
+ ReentryBlock(IR::BasicBlock *b) : block(b) {}
+ IR::BasicBlock *block;
};
void callAbsolute(const char* functionName, FunctionPtr function) {
@@ -483,27 +486,29 @@ public:
call(relativeCall.addr);
}
- void registerBlock(V4IR::BasicBlock*, V4IR::BasicBlock *nextBlock);
- V4IR::BasicBlock *nextBlock() const { return _nextBlock; }
- void jumpToBlock(V4IR::BasicBlock* current, V4IR::BasicBlock *target);
- void addPatch(V4IR::BasicBlock* targetBlock, Jump targetJump);
+ void registerBlock(IR::BasicBlock*, IR::BasicBlock *nextBlock);
+ IR::BasicBlock *nextBlock() const { return _nextBlock; }
+ void jumpToBlock(IR::BasicBlock* current, IR::BasicBlock *target);
+ void addPatch(IR::BasicBlock* targetBlock, Jump targetJump);
void addPatch(DataLabelPtr patch, Label target);
- void addPatch(DataLabelPtr patch, V4IR::BasicBlock *target);
- void generateCJumpOnNonZero(RegisterID reg, V4IR::BasicBlock *currentBlock,
- V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
+ void addPatch(DataLabelPtr patch, IR::BasicBlock *target);
+ void generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBlock,
+ IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
void generateCJumpOnCompare(RelationalCondition cond, RegisterID left, TrustedImm32 right,
- V4IR::BasicBlock *currentBlock, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock);
+ IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock);
void generateCJumpOnCompare(RelationalCondition cond, RegisterID left, RegisterID right,
- V4IR::BasicBlock *currentBlock, V4IR::BasicBlock *trueBlock,
- V4IR::BasicBlock *falseBlock);
+ IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock);
+ Jump genTryDoubleConversion(IR::Expr *src, Assembler::FPRegisterID dest);
+ Assembler::Jump branchDouble(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right);
- Pointer loadTempAddress(RegisterID baseReg, V4IR::Temp *t);
+ Pointer loadTempAddress(RegisterID baseReg, IR::Temp *t);
Pointer loadStringAddress(RegisterID reg, const QString &string);
void loadStringRef(RegisterID reg, const QString &string);
- Pointer stackSlotPointer(V4IR::Temp *t) const
+ Pointer stackSlotPointer(IR::Temp *t) const
{
- Q_ASSERT(t->kind == V4IR::Temp::StackSlot);
+ Q_ASSERT(t->kind == IR::Temp::StackSlot);
Q_ASSERT(t->scope == 0);
return Pointer(_stackLayout.stackSlotPointer(t->index));
@@ -514,20 +519,20 @@ public:
{
if (!arg.value)
return;
- if (V4IR::Temp *t = arg.value->asTemp()) {
- if (t->kind == V4IR::Temp::PhysicalRegister) {
+ if (IR::Temp *t = arg.value->asTemp()) {
+ if (t->kind == IR::Temp::PhysicalRegister) {
Pointer addr(_stackLayout.savedRegPointer(argumentNumber));
switch (t->type) {
- case V4IR::BoolType:
+ case IR::BoolType:
storeBool((RegisterID) t->index, addr);
break;
- case V4IR::SInt32Type:
+ case IR::SInt32Type:
storeInt32((RegisterID) t->index, addr);
break;
- case V4IR::UInt32Type:
+ case IR::UInt32Type:
storeUInt32((RegisterID) t->index, addr);
break;
- case V4IR::DoubleType:
+ case IR::DoubleType:
storeDouble((FPRegisterID) t->index, addr);
break;
default:
@@ -593,7 +598,7 @@ public:
}
#ifdef VALUE_FITS_IN_REGISTER
- void loadArgumentInRegister(V4IR::Temp* temp, RegisterID dest, int argumentNumber)
+ void loadArgumentInRegister(IR::Temp* temp, RegisterID dest, int argumentNumber)
{
Q_UNUSED(argumentNumber);
@@ -606,7 +611,7 @@ public:
}
}
- void loadArgumentInRegister(V4IR::Const* c, RegisterID dest, int argumentNumber)
+ void loadArgumentInRegister(IR::Const* c, RegisterID dest, int argumentNumber)
{
Q_UNUSED(argumentNumber);
@@ -614,7 +619,7 @@ public:
move(TrustedImm64(v.val), dest);
}
- void loadArgumentInRegister(V4IR::Expr* expr, RegisterID dest, int argumentNumber)
+ void loadArgumentInRegister(IR::Expr* expr, RegisterID dest, int argumentNumber)
{
Q_UNUSED(argumentNumber);
@@ -630,7 +635,7 @@ public:
}
}
#else
- void loadArgumentInRegister(V4IR::Expr*, RegisterID)
+ void loadArgumentInRegister(IR::Expr*, RegisterID)
{
assert(!"unimplemented: expression in loadArgument");
}
@@ -657,7 +662,7 @@ public:
void storeUInt32ReturnValue(RegisterID dest)
{
- Pointer tmp(StackPointerRegister, -int(sizeof(QV4::SafeValue)));
+ Pointer tmp(StackPointerRegister, -int(sizeof(QV4::Value)));
storeReturnValue(tmp);
toUInt32Register(tmp, dest);
}
@@ -669,7 +674,7 @@ public:
xor64(ScratchRegister, ReturnValueRegister);
move64ToDouble(ReturnValueRegister, dest);
#else
- Pointer tmp(StackPointerRegister, -int(sizeof(QV4::SafeValue)));
+ Pointer tmp(StackPointerRegister, -int(sizeof(QV4::Value)));
storeReturnValue(tmp);
loadDouble(tmp, dest);
#endif
@@ -698,15 +703,15 @@ public:
}
#endif
- void storeReturnValue(V4IR::Temp *temp)
+ void storeReturnValue(IR::Temp *temp)
{
if (!temp)
return;
- if (temp->kind == V4IR::Temp::PhysicalRegister) {
- if (temp->type == V4IR::DoubleType)
+ if (temp->kind == IR::Temp::PhysicalRegister) {
+ if (temp->type == IR::DoubleType)
storeReturnValue((FPRegisterID) temp->index);
- else if (temp->type == V4IR::UInt32Type)
+ else if (temp->type == IR::UInt32Type)
storeUInt32ReturnValue((RegisterID) temp->index);
else
storeReturnValue((RegisterID) temp->index);
@@ -801,9 +806,9 @@ public:
poke(TrustedImmPtr(name), StackSlot);
}
- void loadDouble(V4IR::Temp* temp, FPRegisterID dest)
+ void loadDouble(IR::Temp* temp, FPRegisterID dest)
{
- if (temp->kind == V4IR::Temp::PhysicalRegister) {
+ if (temp->kind == IR::Temp::PhysicalRegister) {
moveDouble((FPRegisterID) temp->index, dest);
return;
}
@@ -811,9 +816,9 @@ public:
loadDouble(ptr, dest);
}
- void storeDouble(FPRegisterID source, V4IR::Temp* temp)
+ void storeDouble(FPRegisterID source, IR::Temp* temp)
{
- if (temp->kind == V4IR::Temp::PhysicalRegister) {
+ if (temp->kind == IR::Temp::PhysicalRegister) {
moveDouble(source, (FPRegisterID) temp->index);
return;
}
@@ -853,12 +858,12 @@ public:
template <typename Result, typename Source>
void copyValue(Result result, Source source);
template <typename Result>
- void copyValue(Result result, V4IR::Expr* source);
+ void copyValue(Result result, IR::Expr* source);
// The scratch register is used to calculate the temp address for the source.
- void memcopyValue(Pointer target, V4IR::Temp *sourceTemp, RegisterID scratchRegister)
+ void memcopyValue(Pointer target, IR::Temp *sourceTemp, RegisterID scratchRegister)
{
- Q_ASSERT(sourceTemp->kind != V4IR::Temp::PhysicalRegister);
+ Q_ASSERT(sourceTemp->kind != IR::Temp::PhysicalRegister);
Q_ASSERT(target.base != scratchRegister);
JSC::MacroAssembler::loadDouble(loadTempAddress(scratchRegister, sourceTemp), FPGpr0);
JSC::MacroAssembler::storeDouble(FPGpr0, target);
@@ -882,7 +887,7 @@ public:
#endif
}
- void storeValue(QV4::Primitive value, V4IR::Temp* temp);
+ void storeValue(QV4::Primitive value, IR::Temp* temp);
void enterStandardStackFrame();
void leaveStandardStackFrame();
@@ -1039,8 +1044,8 @@ public:
ImmRegBinOp inlineImmRegOp;
};
- static const BinaryOperationInfo binaryOperations[QQmlJS::V4IR::LastAluOp + 1];
- static const BinaryOperationInfo &binaryOperation(V4IR::AluOp operation)
+ static const BinaryOperationInfo binaryOperations[IR::LastAluOp + 1];
+ static const BinaryOperationInfo &binaryOperation(IR::AluOp operation)
{ return binaryOperations[operation]; }
Jump inline_add32(Address addr, RegisterID reg)
@@ -1184,9 +1189,9 @@ public:
return Jump();
}
- Pointer toAddress(RegisterID tmpReg, V4IR::Expr *e, int offset)
+ Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset)
{
- if (V4IR::Const *c = e->asConst()) {
+ if (IR::Const *c = e->asConst()) {
Address addr = _stackLayout.savedRegPointer(offset);
Address tagAddr = addr;
tagAddr.offset += 4;
@@ -1197,9 +1202,9 @@ public:
return Pointer(addr);
}
- V4IR::Temp *t = e->asTemp();
+ IR::Temp *t = e->asTemp();
Q_ASSERT(t);
- if (t->kind != V4IR::Temp::PhysicalRegister)
+ if (t->kind != IR::Temp::PhysicalRegister)
return loadTempAddress(tmpReg, t);
@@ -1218,9 +1223,9 @@ public:
move(src, dest);
}
- void storeBool(RegisterID reg, V4IR::Temp *target)
+ void storeBool(RegisterID reg, IR::Temp *target)
{
- if (target->kind == V4IR::Temp::PhysicalRegister) {
+ if (target->kind == IR::Temp::PhysicalRegister) {
move(reg, (RegisterID) target->index);
} else {
Pointer addr = loadTempAddress(ScratchRegister, target);
@@ -1228,9 +1233,9 @@ public:
}
}
- void storeBool(bool value, V4IR::Temp *target) {
+ void storeBool(bool value, IR::Temp *target) {
TrustedImm32 trustedValue(value ? 1 : 0);
- if (target->kind == V4IR::Temp::PhysicalRegister) {
+ if (target->kind == IR::Temp::PhysicalRegister) {
move(trustedValue, (RegisterID) target->index);
} else {
move(trustedValue, ScratchRegister);
@@ -1250,9 +1255,9 @@ public:
store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag), addr);
}
- void storeInt32(RegisterID reg, V4IR::Temp *target)
+ void storeInt32(RegisterID reg, IR::Temp *target)
{
- if (target->kind == V4IR::Temp::PhysicalRegister) {
+ if (target->kind == IR::Temp::PhysicalRegister) {
move(reg, (RegisterID) target->index);
} else {
Pointer addr = loadTempAddress(ScratchRegister, target);
@@ -1277,9 +1282,9 @@ public:
done.link(this);
}
- void storeUInt32(RegisterID reg, V4IR::Temp *target)
+ void storeUInt32(RegisterID reg, IR::Temp *target)
{
- if (target->kind == V4IR::Temp::PhysicalRegister) {
+ if (target->kind == IR::Temp::PhysicalRegister) {
move(reg, (RegisterID) target->index);
} else {
Pointer addr = loadTempAddress(ScratchRegister, target);
@@ -1287,9 +1292,9 @@ public:
}
}
- FPRegisterID toDoubleRegister(V4IR::Expr *e, FPRegisterID target = FPGpr0)
+ FPRegisterID toDoubleRegister(IR::Expr *e, FPRegisterID target = FPGpr0)
{
- if (V4IR::Const *c = e->asConst()) {
+ if (IR::Const *c = e->asConst()) {
#if QT_POINTER_SIZE == 8
union {
double d;
@@ -1304,30 +1309,30 @@ public:
return target;
}
- V4IR::Temp *t = e->asTemp();
+ IR::Temp *t = e->asTemp();
Q_ASSERT(t);
- if (t->kind == V4IR::Temp::PhysicalRegister)
+ if (t->kind == IR::Temp::PhysicalRegister)
return (FPRegisterID) t->index;
loadDouble(t, target);
return target;
}
- RegisterID toBoolRegister(V4IR::Expr *e, RegisterID scratchReg)
+ RegisterID toBoolRegister(IR::Expr *e, RegisterID scratchReg)
{
return toInt32Register(e, scratchReg);
}
- RegisterID toInt32Register(V4IR::Expr *e, RegisterID scratchReg)
+ RegisterID toInt32Register(IR::Expr *e, RegisterID scratchReg)
{
- if (V4IR::Const *c = e->asConst()) {
+ if (IR::Const *c = e->asConst()) {
move(TrustedImm32(convertToValue(c).int_32), scratchReg);
return scratchReg;
}
- V4IR::Temp *t = e->asTemp();
+ IR::Temp *t = e->asTemp();
Q_ASSERT(t);
- if (t->kind == V4IR::Temp::PhysicalRegister)
+ if (t->kind == IR::Temp::PhysicalRegister)
return (RegisterID) t->index;
return toInt32Register(loadTempAddress(scratchReg, t), scratchReg);
@@ -1339,16 +1344,16 @@ public:
return scratchReg;
}
- RegisterID toUInt32Register(V4IR::Expr *e, RegisterID scratchReg)
+ RegisterID toUInt32Register(IR::Expr *e, RegisterID scratchReg)
{
- if (V4IR::Const *c = e->asConst()) {
+ if (IR::Const *c = e->asConst()) {
move(TrustedImm32(unsigned(c->value)), scratchReg);
return scratchReg;
}
- V4IR::Temp *t = e->asTemp();
+ IR::Temp *t = e->asTemp();
Q_ASSERT(t);
- if (t->kind == V4IR::Temp::PhysicalRegister)
+ if (t->kind == IR::Temp::PhysicalRegister)
return (RegisterID) t->index;
return toUInt32Register(loadTempAddress(scratchReg, t), scratchReg);
@@ -1387,14 +1392,14 @@ public:
ConstantTable &constantTable() { return _constTable; }
Label exceptionReturnLabel;
- V4IR::BasicBlock * catchBlock;
+ IR::BasicBlock * catchBlock;
QVector<Jump> exceptionPropagationJumps;
private:
const StackLayout _stackLayout;
ConstantTable _constTable;
- V4IR::Function *_function;
- QHash<V4IR::BasicBlock *, Label> _addrs;
- QHash<V4IR::BasicBlock *, QVector<Jump> > _patches;
+ IR::Function *_function;
+ QHash<IR::BasicBlock *, Label> _addrs;
+ QHash<IR::BasicBlock *, QVector<Jump> > _patches;
QList<CallToLink> _callsToLink;
struct DataLabelPatch {
@@ -1403,253 +1408,72 @@ private:
};
QList<DataLabelPatch> _dataLabelPatches;
- QHash<V4IR::BasicBlock *, QVector<DataLabelPtr> > _labelPatches;
- V4IR::BasicBlock *_nextBlock;
+ QHash<IR::BasicBlock *, QVector<DataLabelPtr> > _labelPatches;
+ IR::BasicBlock *_nextBlock;
QV4::ExecutableAllocator *_executableAllocator;
InstructionSelection *_isel;
};
-template <typename T> inline void prepareRelativeCall(const T &, Assembler *){}
-template <> inline void prepareRelativeCall(const RelativeCall &relativeCall, Assembler *as)
+template <typename Result, typename Source>
+void Assembler::copyValue(Result result, Source source)
{
- as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, lookups)),
- relativeCall.addr.base);
+#ifdef VALUE_FITS_IN_REGISTER
+ // Use ReturnValueRegister as "scratch" register because loadArgument
+ // and storeArgument are functions that may need a scratch register themselves.
+ loadArgumentInRegister(source, ReturnValueRegister, 0);
+ storeReturnValue(result);
+#else
+ loadDouble(source, FPGpr0);
+ storeDouble(FPGpr0, result);
+#endif
}
-class Q_QML_EXPORT InstructionSelection:
- protected V4IR::IRDecoder,
- public EvalInstructionSelection
+template <typename Result>
+void Assembler::copyValue(Result result, IR::Expr* source)
{
-public:
- InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
- ~InstructionSelection();
-
- virtual void run(int functionIndex);
-
- void *addConstantTable(QVector<QV4::Primitive> *values);
-protected:
- virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
-
- virtual void callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void callBuiltinTypeofMember(V4IR::Expr *base, const QString &name, V4IR::Temp *result);
- virtual void callBuiltinTypeofSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *result);
- virtual void callBuiltinTypeofName(const QString &name, V4IR::Temp *result);
- virtual void callBuiltinTypeofValue(V4IR::Expr *value, V4IR::Temp *result);
- virtual void callBuiltinDeleteMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result);
- virtual void callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Expr *index, V4IR::Temp *result);
- virtual void callBuiltinDeleteName(const QString &name, V4IR::Temp *result);
- virtual void callBuiltinDeleteValue(V4IR::Temp *result);
- virtual void callBuiltinThrow(V4IR::Expr *arg);
- virtual void callBuiltinReThrow();
- virtual void callBuiltinUnwindException(V4IR::Temp *);
- virtual void callBuiltinPushCatchScope(const QString &exceptionName);
- virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result);
- virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result);
- virtual void callBuiltinPushWithScope(V4IR::Temp *arg);
- virtual void callBuiltinPopScope();
- virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
- virtual void callBuiltinDefineGetterSetter(V4IR::Temp *object, const QString &name, V4IR::Temp *getter, V4IR::Temp *setter);
- virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Expr *value);
- virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args);
- virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result);
- virtual void callBuiltinConvertThisToObject();
- virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void convertType(V4IR::Temp *source, V4IR::Temp *target);
- virtual void loadThisObject(V4IR::Temp *temp);
- virtual void loadQmlIdArray(V4IR::Temp *temp);
- virtual void loadQmlImportedScripts(V4IR::Temp *temp);
- virtual void loadQmlContextObject(V4IR::Temp *temp);
- virtual void loadQmlScopeObject(V4IR::Temp *temp);
- virtual void loadQmlSingleton(const QString &name, V4IR::Temp *temp);
- virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);
- virtual void loadString(const QString &str, V4IR::Temp *targetTemp);
- virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp);
- virtual void getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp);
- virtual void setActivationProperty(V4IR::Expr *source, const QString &targetName);
- virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target);
- virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
- virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
- virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target);
- virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
- virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
- virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
- virtual void swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
- virtual void unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
- virtual void binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target);
-
- typedef Assembler::Address Address;
- typedef Assembler::Pointer Pointer;
-
-#if !defined(ARGUMENTS_IN_REGISTERS)
- Address addressForArgument(int index) const
- {
- // StackFrameRegister points to its old value on the stack, and above
- // it we have the return address, hence the need to step over two
- // values before reaching the first argument.
- return Address(Assembler::StackFrameRegister, (index + 2) * sizeof(void*));
- }
-#endif
-
- Pointer baseAddressForCallArguments()
- {
- return _as->stackLayout().argumentAddressForCall(0);
- }
-
- Pointer baseAddressForCallData()
- {
- return _as->stackLayout().callDataAddress();
- }
-
- virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
- virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
-
- virtual void visitJump(V4IR::Jump *);
- virtual void visitCJump(V4IR::CJump *);
- virtual void visitRet(V4IR::Ret *);
-
- Assembler::Jump genTryDoubleConversion(V4IR::Expr *src, Assembler::FPRegisterID dest);
- Assembler::Jump genInlineBinop(V4IR::AluOp oper, V4IR::Expr *leftSource,
- V4IR::Expr *rightSource, V4IR::Temp *target);
- void doubleBinop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource,
- V4IR::Temp *target);
- Assembler::Jump branchDouble(bool invertCondition, V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right);
- bool visitCJumpDouble(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right,
- V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse);
- void visitCJumpStrict(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
- bool visitCJumpStrictNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop,
- V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
- bool visitCJumpStrictBool(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
- bool visitCJumpNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop,
- V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
- void visitCJumpEqual(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
- bool int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource,
- V4IR::Temp *target);
-
-private:
- void convertTypeSlowPath(V4IR::Temp *source, V4IR::Temp *target);
- void convertTypeToDouble(V4IR::Temp *source, V4IR::Temp *target);
- void convertTypeToBool(V4IR::Temp *source, V4IR::Temp *target);
- void convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *target);
- void convertTypeToUInt32(V4IR::Temp *source, V4IR::Temp *target);
-
- void convertIntToDouble(V4IR::Temp *source, V4IR::Temp *target)
- {
- if (target->kind == V4IR::Temp::PhysicalRegister) {
- _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
- (Assembler::FPRegisterID) target->index);
- } else {
- _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
- Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
- }
- }
-
- void convertUIntToDouble(V4IR::Temp *source, V4IR::Temp *target)
- {
- Assembler::RegisterID tmpReg = Assembler::ScratchRegister;
- Assembler::RegisterID reg = _as->toInt32Register(source, tmpReg);
-
- if (target->kind == V4IR::Temp::PhysicalRegister) {
- _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) target->index, tmpReg);
- } else {
- _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
- Assembler::FPGpr0, tmpReg);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
- }
- }
-
- void convertIntToBool(V4IR::Temp *source, V4IR::Temp *target)
- {
- Assembler::RegisterID reg = target->kind == V4IR::Temp::PhysicalRegister
- ? (Assembler::RegisterID) target->index
- : Assembler::ScratchRegister;
-
- _as->move(_as->toInt32Register(source, reg), reg);
- _as->compare32(Assembler::NotEqual, reg, Assembler::TrustedImm32(0), reg);
- _as->storeBool(reg, target);
- }
-
- #define isel_stringIfyx(s) #s
- #define isel_stringIfy(s) isel_stringIfyx(s)
-
- #define generateFunctionCall(t, function, ...) \
- _as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__)
-
- int prepareVariableArguments(V4IR::ExprList* args);
- int prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject);
+ if (source->type == IR::BoolType) {
+ RegisterID reg = toInt32Register(source, ScratchRegister);
+ storeBool(reg, result);
+ } else if (source->type == IR::SInt32Type) {
+ RegisterID reg = toInt32Register(source, ScratchRegister);
+ storeInt32(reg, result);
+ } else if (source->type == IR::UInt32Type) {
+ RegisterID reg = toUInt32Register(source, ScratchRegister);
+ storeUInt32(reg, result);
+ } else if (source->type == IR::DoubleType) {
+ storeDouble(toDoubleRegister(source), result);
+ } else if (IR::Temp *temp = source->asTemp()) {
+#ifdef VALUE_FITS_IN_REGISTER
+ Q_UNUSED(temp);
- template <typename Retval, typename Arg1, typename Arg2>
- void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
- {
- Assembler::RegisterID lookupRegister;
-#if CPU(ARM)
- lookupRegister = JSC::ARMRegisters::r8;
+ // Use ReturnValueRegister as "scratch" register because loadArgument
+ // and storeArgument are functions that may need a scratch register themselves.
+ loadArgumentInRegister(source, ReturnValueRegister, 0);
+ storeReturnValue(result);
#else
- lookupRegister = Assembler::ReturnValueRegister;
+ loadDouble(temp, FPGpr0);
+ storeDouble(FPGpr0, result);
#endif
- Assembler::Pointer lookupAddr(lookupRegister, index * sizeof(QV4::Lookup));
-
- Assembler::Address getterSetter = lookupAddr;
- getterSetter.offset += getterSetterOffset;
-
- _as->generateFunctionCallImp(retval, "lookup getter/setter",
- RelativeCall(getterSetter), lookupAddr, arg1, arg2);
- }
-
- template <typename Arg1>
- void generateLookupCall(uint index, uint getterSetterOffset, Arg1 arg1)
- {
- generateLookupCall(index, getterSetterOffset, arg1, Assembler::VoidType());
- }
-
- /// This is a temporary method, and will be removed when registers are fully supported.
- void storeTarget(int argumentNumber, V4IR::Temp *target)
- {
- if (target->kind == V4IR::Temp::PhysicalRegister) {
- Address addr = _as->stackLayout().savedRegPointer(argumentNumber);
- if (target->type == V4IR::DoubleType)
- _as->loadDouble(addr, (Assembler::FPRegisterID) target->index);
- else if (target->type == V4IR::SInt32Type)
- generateFunctionCall((Assembler::RegisterID) target->index,
- QV4::__qmljs_value_to_int32,
- Assembler::Pointer(addr));
- else if (target->type == V4IR::UInt32Type)
- generateFunctionCall((Assembler::RegisterID) target->index,
- QV4::__qmljs_value_to_uint32,
- Assembler::Pointer(addr));
- else if (target->type == V4IR::BoolType)
- _as->load32(addr, (Assembler::RegisterID) target->index);
- else
- Q_ASSERT(!"WIP!");
- }
+ } else if (IR::Const *c = source->asConst()) {
+ QV4::Primitive v = convertToValue(c);
+ storeValue(v, result);
+ } else {
+ Q_UNREACHABLE();
}
+}
- V4IR::BasicBlock *_block;
- QSet<V4IR::Jump *> _removableJumps;
- Assembler* _as;
- CompilationUnit *compilationUnit;
- QQmlEnginePrivate *qmlEngine;
-};
-class Q_QML_EXPORT ISelFactory: public EvalISelFactory
+template <typename T> inline void prepareRelativeCall(const T &, Assembler *){}
+template <> inline void prepareRelativeCall(const RelativeCall &relativeCall, Assembler *as)
{
-public:
- virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
- { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
- virtual bool jitCompileRegexps() const
- { return true; }
-};
+ as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, lookups)),
+ relativeCall.addr.base);
+}
-} // end of namespace MASM
-} // end of namespace QQmlJS
+} // end of namespace JIT
+} // end of namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
new file mode 100644
index 0000000000..473f260be7
--- /dev/null
+++ b/src/qml/jit/qv4binop.cpp
@@ -0,0 +1,428 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qv4binop_p.h>
+#include <qv4assembler_p.h>
+
+#if ENABLE(ASSEMBLER)
+
+using namespace QV4;
+using namespace JIT;
+
+namespace {
+inline bool isPregOrConst(IR::Expr *e)
+{
+ if (IR::Temp *t = e->asTemp())
+ return t->kind == IR::Temp::PhysicalRegister;
+ return e->asConst() != 0;
+}
+} // anonymous namespace
+
+void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
+{
+ if (op != IR::OpMod
+ && lhs->type == IR::DoubleType && rhs->type == IR::DoubleType
+ && isPregOrConst(lhs) && isPregOrConst(rhs)) {
+ doubleBinop(lhs, rhs, target);
+ return;
+ }
+ if (lhs->type == IR::SInt32Type && rhs->type == IR::SInt32Type) {
+ if (int32Binop(lhs, rhs, target))
+ return;
+ }
+
+ Assembler::Jump done;
+ if (lhs->type != IR::StringType && rhs->type != IR::StringType)
+ done = genInlineBinop(lhs, rhs, target);
+
+ // TODO: inline var===null and var!==null
+ Assembler::BinaryOperationInfo info = Assembler::binaryOperation(op);
+
+ if (op == IR::OpAdd &&
+ (lhs->type == IR::StringType || rhs->type == IR::StringType)) {
+ const Assembler::BinaryOperationInfo stringAdd = OPCONTEXT(__qmljs_add_string);
+ info = stringAdd;
+ }
+
+ if (info.fallbackImplementation) {
+ as->generateFunctionCallImp(target, info.name, info.fallbackImplementation,
+ Assembler::PointerToValue(lhs),
+ Assembler::PointerToValue(rhs));
+ } else if (info.contextImplementation) {
+ as->generateFunctionCallImp(target, info.name, info.contextImplementation,
+ Assembler::ContextRegister,
+ Assembler::PointerToValue(lhs),
+ Assembler::PointerToValue(rhs));
+ } else {
+ assert(!"unreachable");
+ }
+
+ if (done.isSet())
+ done.link(as);
+
+}
+
+void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
+{
+ Q_ASSERT(lhs->asConst() == 0 || rhs->asConst() == 0);
+ Q_ASSERT(isPregOrConst(lhs));
+ Q_ASSERT(isPregOrConst(rhs));
+ Assembler::FPRegisterID targetReg;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::FPRegisterID) target->index;
+ else
+ targetReg = Assembler::FPGpr0;
+
+ switch (op) {
+ case IR::OpAdd:
+ as->addDouble(as->toDoubleRegister(lhs), as->toDoubleRegister(rhs),
+ targetReg);
+ break;
+ case IR::OpMul:
+ as->mulDouble(as->toDoubleRegister(lhs), as->toDoubleRegister(rhs),
+ targetReg);
+ break;
+ case IR::OpSub:
+#if CPU(X86) || CPU(X86_64)
+ if (IR::Temp *rightTemp = rhs->asTemp()) {
+ if (rightTemp->kind == IR::Temp::PhysicalRegister && rightTemp->index == targetReg) {
+ as->moveDouble(targetReg, Assembler::FPGpr0);
+ as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
+ as->subDouble(Assembler::FPGpr0, targetReg);
+ break;
+ }
+ } else if (rhs->asConst() && targetReg == Assembler::FPGpr0) {
+ Q_ASSERT(lhs->asTemp());
+ Q_ASSERT(lhs->asTemp()->kind == IR::Temp::PhysicalRegister);
+ as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
+ Assembler::FPRegisterID reg = (Assembler::FPRegisterID) lhs->asTemp()->index;
+ as->moveDouble(as->toDoubleRegister(rhs, reg), reg);
+ as->subDouble(reg, targetReg);
+ break;
+ }
+#endif
+
+ as->subDouble(as->toDoubleRegister(lhs), as->toDoubleRegister(rhs),
+ targetReg);
+ break;
+ case IR::OpDiv:
+#if CPU(X86) || CPU(X86_64)
+ if (IR::Temp *rightTemp = rhs->asTemp()) {
+ if (rightTemp->kind == IR::Temp::PhysicalRegister && rightTemp->index == targetReg) {
+ as->moveDouble(targetReg, Assembler::FPGpr0);
+ as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
+ as->divDouble(Assembler::FPGpr0, targetReg);
+ break;
+ }
+ } else if (rhs->asConst() && targetReg == Assembler::FPGpr0) {
+ Q_ASSERT(lhs->asTemp());
+ Q_ASSERT(lhs->asTemp()->kind == IR::Temp::PhysicalRegister);
+ as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
+ Assembler::FPRegisterID reg = (Assembler::FPRegisterID) lhs->asTemp()->index;
+ as->moveDouble(as->toDoubleRegister(rhs, reg), reg);
+ as->divDouble(reg, targetReg);
+ break;
+ }
+#endif
+ as->divDouble(as->toDoubleRegister(lhs), as->toDoubleRegister(rhs),
+ targetReg);
+ break;
+ default: {
+ Q_ASSERT(target->type == IR::BoolType);
+ Assembler::Jump trueCase = as->branchDouble(false, op, lhs, rhs);
+ as->storeBool(false, target);
+ Assembler::Jump done = as->jump();
+ trueCase.link(as);
+ as->storeBool(true, target);
+ done.link(as);
+ } return;
+ }
+
+ if (target->kind != IR::Temp::PhysicalRegister)
+ as->storeDouble(Assembler::FPGpr0, target);
+}
+
+
+bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+{
+ Q_ASSERT(leftSource->type == IR::SInt32Type);
+ Assembler::RegisterID targetReg;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ switch (op) {
+ case IR::OpBitAnd: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+ if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
+ && target->kind == IR::Temp::PhysicalRegister
+ && target->index == rightSource->asTemp()->index) {
+ as->and32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
+ (Assembler::RegisterID) target->index);
+ return true;
+ }
+
+ as->and32(as->toInt32Register(leftSource, targetReg),
+ as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpBitOr: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+ if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
+ && target->kind == IR::Temp::PhysicalRegister
+ && target->index == rightSource->asTemp()->index) {
+ as->or32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
+ (Assembler::RegisterID) target->index);
+ return true;
+ }
+
+ as->or32(as->toInt32Register(leftSource, targetReg),
+ as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpBitXor: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+ if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
+ && target->kind == IR::Temp::PhysicalRegister
+ && target->index == rightSource->asTemp()->index) {
+ as->xor32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
+ (Assembler::RegisterID) target->index);
+ return true;
+ }
+
+ as->xor32(as->toInt32Register(leftSource, targetReg),
+ as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpLShift: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+
+ if (IR::Const *c = rightSource->asConst()) {
+ as->lshift32(as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
+ Assembler::TrustedImm32(int(c->value) & 0x1f), targetReg);
+ } else {
+ as->move(as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ Assembler::ScratchRegister);
+ if (!rightSource->asConst())
+ as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
+ as->lshift32(as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister, targetReg);
+ }
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpRShift: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+
+ if (IR::Const *c = rightSource->asConst()) {
+ as->rshift32(as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
+ Assembler::TrustedImm32(int(c->value) & 0x1f), targetReg);
+ } else {
+ as->move(as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ Assembler::ScratchRegister);
+ as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
+ as->rshift32(as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister, targetReg);
+ }
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpURShift:
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+
+ if (IR::Const *c = rightSource->asConst()) {
+ as->urshift32(as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
+ Assembler::TrustedImm32(int(c->value) & 0x1f), targetReg);
+ } else {
+ as->move(as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ Assembler::ScratchRegister);
+ as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
+ as->urshift32(as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister, targetReg);
+ }
+ as->storeUInt32(targetReg, target);
+ return true;
+ case IR::OpAdd: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+
+ Assembler::RegisterID targetReg;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ as->add32(as->toInt32Register(leftSource, targetReg),
+ as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpSub: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+
+ if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
+ && target->kind == IR::Temp::PhysicalRegister
+ && target->index == rightSource->asTemp()->index) {
+ Assembler::RegisterID targetReg = (Assembler::RegisterID) target->index;
+ as->move(targetReg, Assembler::ScratchRegister);
+ as->move(as->toInt32Register(leftSource, targetReg), targetReg);
+ as->sub32(Assembler::ScratchRegister, targetReg);
+ as->storeInt32(targetReg, target);
+ return true;
+ }
+
+ Assembler::RegisterID targetReg;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ as->move(as->toInt32Register(leftSource, targetReg), targetReg);
+ as->sub32(as->toInt32Register(rightSource, Assembler::ScratchRegister), targetReg);
+ as->storeInt32(targetReg, target);
+ } return true;
+ case IR::OpMul: {
+ Q_ASSERT(rightSource->type == IR::SInt32Type);
+
+ Assembler::RegisterID targetReg;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ as->mul32(as->toInt32Register(leftSource, targetReg),
+ as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ as->storeInt32(targetReg, target);
+ } return true;
+ default:
+ return false;
+ }
+}
+
+static inline Assembler::FPRegisterID getFreeFPReg(IR::Expr *shouldNotOverlap, unsigned hint)
+{
+ if (IR::Temp *t = shouldNotOverlap->asTemp())
+ if (t->type == IR::DoubleType)
+ if (t->kind == IR::Temp::PhysicalRegister)
+ if (t->index == hint)
+ return Assembler::FPRegisterID(hint + 1);
+ return Assembler::FPRegisterID(hint);
+}
+
+Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+{
+ Assembler::Jump done;
+
+ // Try preventing a call for a few common binary operations. This is used in two cases:
+ // - no register allocation was performed (not available for the platform, or the IR was
+ // not transformed into SSA)
+ // - type inference found that either or both operands can be of non-number type, and the
+ // register allocator will have prepared for a call (meaning: all registers that do not
+ // hold operands are spilled to the stack, which makes them available here)
+ // Note: FPGPr0 can still not be used, because uint32->double conversion uses it as a scratch
+ // register.
+ switch (op) {
+ case IR::OpAdd: {
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+
+ as->addDouble(rReg, lReg);
+ as->storeDouble(lReg, target);
+ done = as->jump();
+
+ if (leftIsNoDbl.isSet())
+ leftIsNoDbl.link(as);
+ if (rightIsNoDbl.isSet())
+ rightIsNoDbl.link(as);
+ } break;
+ case IR::OpMul: {
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+
+ as->mulDouble(rReg, lReg);
+ as->storeDouble(lReg, target);
+ done = as->jump();
+
+ if (leftIsNoDbl.isSet())
+ leftIsNoDbl.link(as);
+ if (rightIsNoDbl.isSet())
+ rightIsNoDbl.link(as);
+ } break;
+ case IR::OpSub: {
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+
+ as->subDouble(rReg, lReg);
+ as->storeDouble(lReg, target);
+ done = as->jump();
+
+ if (leftIsNoDbl.isSet())
+ leftIsNoDbl.link(as);
+ if (rightIsNoDbl.isSet())
+ rightIsNoDbl.link(as);
+ } break;
+ case IR::OpDiv: {
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+
+ as->divDouble(rReg, lReg);
+ as->storeDouble(lReg, target);
+ done = as->jump();
+
+ if (leftIsNoDbl.isSet())
+ leftIsNoDbl.link(as);
+ if (rightIsNoDbl.isSet())
+ rightIsNoDbl.link(as);
+ } break;
+ default:
+ break;
+ }
+
+ return done;
+}
+
+#endif
diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h
new file mode 100644
index 0000000000..d29b370f37
--- /dev/null
+++ b/src/qml/jit/qv4binop_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4BINOP_P_H
+#define QV4BINOP_P_H
+
+#include <qv4jsir_p.h>
+#include <qv4isel_masm_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if ENABLE(ASSEMBLER)
+
+namespace QV4 {
+namespace JIT {
+
+struct Binop {
+ Binop(Assembler *assembler, IR::AluOp operation)
+ : as(assembler)
+ , op(operation)
+ {}
+
+ void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target);
+ void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target);
+ bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+
+ Assembler *as;
+ IR::AluOp op;
+};
+
+}
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
new file mode 100644
index 0000000000..706130e995
--- /dev/null
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -0,0 +1,1771 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4isel_masm_p.h"
+#include "qv4runtime_p.h"
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+#include "qv4regexpobject_p.h"
+#include "qv4lookup_p.h"
+#include "qv4function_p.h"
+#include "qv4ssa_p.h"
+#include "qv4regalloc_p.h"
+#include "qv4assembler_p.h"
+#include "qv4unop_p.h"
+#include "qv4binop_p.h"
+
+#include <assembler/LinkBuffer.h>
+#include <WTFStubs.h>
+
+#include <iostream>
+#include <cassert>
+
+#if ENABLE(ASSEMBLER)
+
+#if USE(UDIS86)
+# include <udis86.h>
+#endif
+
+using namespace QV4;
+using namespace QV4::JIT;
+
+
+namespace {
+inline bool isPregOrConst(IR::Expr *e)
+{
+ if (IR::Temp *t = e->asTemp())
+ return t->kind == IR::Temp::PhysicalRegister;
+ return e->asConst() != 0;
+}
+} // anonymous namespace
+
+#if OS(LINUX) || OS(MAC_OS_X)
+static void printDisassembledOutputWithCalls(const char* output, const QHash<void*, const char*>& functions)
+{
+ QByteArray processedOutput(output);
+ for (QHash<void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
+ it != end; ++it) {
+ QByteArray ptrString = QByteArray::number(quintptr(it.key()), 16);
+ ptrString.prepend("0x");
+ processedOutput = processedOutput.replace(ptrString, it.value());
+ }
+ fprintf(stderr, "%s\n", processedOutput.constData());
+}
+#endif
+
+JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
+{
+ Label endOfCode = label();
+
+ {
+ QHashIterator<IR::BasicBlock *, QVector<Jump> > it(_patches);
+ while (it.hasNext()) {
+ it.next();
+ IR::BasicBlock *block = it.key();
+ Label target = _addrs.value(block);
+ assert(target.isSet());
+ foreach (Jump jump, it.value())
+ jump.linkTo(target, this);
+ }
+ }
+
+ JSC::JSGlobalData dummy(_executableAllocator);
+ JSC::LinkBuffer linkBuffer(dummy, this, 0);
+
+ QHash<void*, const char*> functions;
+ foreach (CallToLink ctl, _callsToLink) {
+ linkBuffer.link(ctl.call, ctl.externalFunction);
+ functions[ctl.externalFunction.value()] = ctl.functionName;
+ }
+
+ foreach (const DataLabelPatch &p, _dataLabelPatches)
+ linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target));
+
+ // link exception handlers
+ foreach(Jump jump, exceptionPropagationJumps)
+ linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel));
+
+ {
+ QHashIterator<IR::BasicBlock *, QVector<DataLabelPtr> > it(_labelPatches);
+ while (it.hasNext()) {
+ it.next();
+ IR::BasicBlock *block = it.key();
+ Label target = _addrs.value(block);
+ assert(target.isSet());
+ foreach (DataLabelPtr label, it.value())
+ linkBuffer.patch(label, linkBuffer.locationOf(target));
+ }
+ }
+ _constTable.finalize(linkBuffer, _isel);
+
+ *codeSize = linkBuffer.offsetOf(endOfCode);
+
+ JSC::MacroAssemblerCodeRef codeRef;
+
+ static bool showCode = !qgetenv("QV4_SHOW_ASM").isNull();
+ if (showCode) {
+#if OS(LINUX) && !defined(Q_OS_ANDROID)
+ char* disasmOutput = 0;
+ size_t disasmLength = 0;
+ FILE* disasmStream = open_memstream(&disasmOutput, &disasmLength);
+ WTF::setDataFile(disasmStream);
+#elif OS(MAC_OS_X)
+ struct MemStream {
+ QByteArray buf;
+ static int write(void *cookie, const char *buf, int len) {
+ MemStream *stream = reinterpret_cast<MemStream *>(cookie);
+ stream->buf.append(buf, len);
+ return len;
+ }
+ };
+ MemStream memStream;
+
+ FILE* disasmStream = fwopen(&memStream, MemStream::write);
+ WTF::setDataFile(disasmStream);
+#endif
+
+ QByteArray name = _function->name->toUtf8();
+ if (name.isEmpty()) {
+ name = QByteArray::number(quintptr(_function), 16);
+ name.prepend("IR::Function(0x");
+ name.append(")");
+ }
+ codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
+
+ WTF::setDataFile(stderr);
+#if (OS(LINUX) && !defined(Q_OS_ANDROID)) || OS(MAC_OS_X)
+ fclose(disasmStream);
+# if OS(MAC_OS_X)
+ char *disasmOutput = memStream.buf.data();
+# endif
+# if CPU(X86) || CPU(X86_64) || CPU(ARM)
+ QHash<void*, String*> idents;
+ printDisassembledOutputWithCalls(disasmOutput, functions);
+# endif
+# if OS(LINUX)
+ free(disasmOutput);
+# endif
+#endif
+ } else {
+ codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
+ }
+
+ return codeRef;
+}
+
+InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator)
+ : EvalInstructionSelection(execAllocator, module, jsGenerator)
+ , _block(0)
+ , _as(0)
+ , qmlEngine(qmlEngine)
+{
+ compilationUnit = new CompilationUnit;
+ compilationUnit->codeRefs.resize(module->functions.size());
+ compilationUnit->codeSizes.resize(module->functions.size());
+}
+
+InstructionSelection::~InstructionSelection()
+{
+ delete _as;
+}
+
+#if (CPU(X86_64) && (OS(MAC_OS_X) || OS(LINUX))) || (CPU(X86) && OS(LINUX))
+# define REGALLOC_IS_SUPPORTED
+static QVector<int> getIntRegisters()
+{
+# if CPU(X86) && OS(LINUX) // x86 with linux
+ static const QVector<int> intRegisters = QVector<int>()
+ << JSC::X86Registers::edx
+ << JSC::X86Registers::ebx;
+# else // x86_64 with linux or with macos
+ static const QVector<int> intRegisters = QVector<int>()
+ << JSC::X86Registers::edi
+ << JSC::X86Registers::esi
+ << JSC::X86Registers::edx
+ << JSC::X86Registers::r9
+ << JSC::X86Registers::r8
+ << JSC::X86Registers::r13
+ << JSC::X86Registers::r15;
+# endif
+ return intRegisters;
+}
+
+static QVector<int> getFpRegisters()
+{
+// linux/x86_64, linux/x86, and macos/x86_64:
+ static const QVector<int> fpRegisters = QVector<int>()
+ << JSC::X86Registers::xmm2
+ << JSC::X86Registers::xmm3
+ << JSC::X86Registers::xmm4
+ << JSC::X86Registers::xmm5
+ << JSC::X86Registers::xmm6
+ << JSC::X86Registers::xmm7;
+ return fpRegisters;
+}
+
+#elif CPU(ARM) && OS(LINUX)
+ // Note: this is not generic for all ARM platforms. Specifically, r9 is platform dependent
+ // (e.g. iOS reserves it). See the ARM GNU Linux abi for details.
+# define REGALLOC_IS_SUPPORTED
+static QVector<int> getIntRegisters()
+{
+ static const QVector<int> intRegisters = QVector<int>()
+ << JSC::ARMRegisters::r1
+ << JSC::ARMRegisters::r2
+ << JSC::ARMRegisters::r8
+ << JSC::ARMRegisters::r9
+ << JSC::ARMRegisters::r10
+ << JSC::ARMRegisters::r11;
+ return intRegisters;
+}
+
+static QVector<int> getFpRegisters()
+{
+ static const QVector<int> fpRegisters = QVector<int>()
+ << JSC::ARMRegisters::d1
+ << JSC::ARMRegisters::d2
+ << JSC::ARMRegisters::d3
+ << JSC::ARMRegisters::d4
+ << JSC::ARMRegisters::d5
+ << JSC::ARMRegisters::d6;
+ return fpRegisters;
+}
+#endif
+
+void InstructionSelection::run(int functionIndex)
+{
+ IR::Function *function = irModule->functions[functionIndex];
+ QVector<Lookup> lookups;
+ qSwap(_function, function);
+
+ IR::Optimizer opt(_function);
+ opt.run(qmlEngine);
+
+#ifdef REGALLOC_IS_SUPPORTED
+ static const bool withRegisterAllocator = qgetenv("QV4_NO_REGALLOC").isEmpty();
+ if (opt.isInSSA() && withRegisterAllocator) {
+ RegisterAllocator(getIntRegisters(), getFpRegisters()).run(_function, opt);
+ } else
+#endif // REGALLOC_IS_SUPPORTED
+ {
+ if (opt.isInSSA())
+ // No register allocator available for this platform, or env. var was set, so:
+ opt.convertOutOfSSA();
+ ConvertTemps().toStackSlots(_function);
+ }
+ IR::Optimizer::showMeTheCode(_function);
+ QSet<IR::Jump *> removableJumps = opt.calculateOptionalJumps();
+ qSwap(_removableJumps, removableJumps);
+
+ Assembler* oldAssembler = _as;
+ _as = new Assembler(this, _function, executableAllocator, 6); // 6 == max argc for calls to built-ins with an argument array
+
+ _as->enterStandardStackFrame();
+
+#ifdef ARGUMENTS_IN_REGISTERS
+ _as->move(_as->registerForArgument(0), Assembler::ContextRegister);
+#else
+ _as->loadPtr(addressForArgument(0), Assembler::ContextRegister);
+#endif
+
+ const int locals = _as->stackLayout().calculateJSStackFrameSize();
+ _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
+ _as->addPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
+
+ int lastLine = -1;
+ for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
+ IR::BasicBlock *nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
+ _block = _function->basicBlocks[i];
+ _as->registerBlock(_block, nextBlock);
+
+ foreach (IR::Stmt *s, _block->statements) {
+ if (s->location.isValid()) {
+ if (int(s->location.startLine) != lastLine) {
+ Assembler::Address lineAddr(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, lineNumber));
+ _as->store32(Assembler::TrustedImm32(s->location.startLine), lineAddr);
+ lastLine = s->location.startLine;
+ }
+ }
+ s->accept(this);
+ }
+ }
+
+ if (!_as->exceptionReturnLabel.isSet())
+ visitRet(0);
+
+ JSC::MacroAssemblerCodeRef codeRef =_as->link(&compilationUnit->codeSizes[functionIndex]);
+ compilationUnit->codeRefs[functionIndex] = codeRef;
+
+ qSwap(_function, function);
+ delete _as;
+ _as = oldAssembler;
+ qSwap(_removableJumps, removableJumps);
+}
+
+void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
+{
+ compilationUnit->constantValues.append(*values);
+ values->clear();
+
+ QVector<QV4::Primitive> &finalValues = compilationUnit->constantValues.last();
+ finalValues.squeeze();
+ return finalValues.data();
+}
+
+QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
+{
+ return compilationUnit;
+}
+
+void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+{
+ prepareCallData(args, 0);
+
+ if (useFastLookups && func->global) {
+ uint index = registerGlobalGetterLookup(*func->id);
+ generateFunctionCall(result, __qmljs_call_global_lookup,
+ Assembler::ContextRegister,
+ Assembler::TrustedImm32(index),
+ baseAddressForCallData());
+ } else {
+ generateFunctionCall(result, __qmljs_call_activation_property,
+ Assembler::ContextRegister,
+ Assembler::PointerToString(*func->id),
+ baseAddressForCallData());
+ }
+}
+
+void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
+ IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_builtin_typeof_member, Assembler::ContextRegister,
+ Assembler::PointerToValue(base), Assembler::PointerToString(name));
+}
+
+void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
+ IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_builtin_typeof_element,
+ Assembler::ContextRegister,
+ Assembler::PointerToValue(base), Assembler::PointerToValue(index));
+}
+
+void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_builtin_typeof_name, Assembler::ContextRegister,
+ Assembler::PointerToString(name));
+}
+
+void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_builtin_typeof, Assembler::ContextRegister,
+ Assembler::PointerToValue(value));
+}
+
+void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_delete_member, Assembler::ContextRegister,
+ Assembler::Reference(base), Assembler::PointerToString(name));
+}
+
+void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index,
+ IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_delete_subscript, Assembler::ContextRegister,
+ Assembler::Reference(base), Assembler::PointerToValue(index));
+}
+
+void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_delete_name, Assembler::ContextRegister,
+ Assembler::PointerToString(name));
+}
+
+void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
+{
+ _as->storeValue(Primitive::fromBoolean(false), result);
+}
+
+void InstructionSelection::callBuiltinThrow(IR::Expr *arg)
+{
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_throw, Assembler::ContextRegister,
+ Assembler::PointerToValue(arg));
+}
+
+void InstructionSelection::callBuiltinReThrow()
+{
+ _as->jumpToExceptionHandler();
+}
+
+void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_builtin_unwind_exception, Assembler::ContextRegister);
+
+}
+
+void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName)
+{
+ Assembler::Pointer s = _as->loadStringAddress(Assembler::ScratchRegister, exceptionName);
+ generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_push_catch_scope, Assembler::ContextRegister, s);
+}
+
+void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result)
+{
+ Q_ASSERT(arg);
+ Q_ASSERT(result);
+
+ generateFunctionCall(result, __qmljs_foreach_iterator_object, Assembler::ContextRegister, Assembler::Reference(arg));
+}
+
+void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
+{
+ Q_ASSERT(arg);
+ Q_ASSERT(result);
+
+ generateFunctionCall(result, __qmljs_foreach_next_property_name, Assembler::Reference(arg));
+}
+
+void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
+{
+ Q_ASSERT(arg);
+
+ generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_push_with_scope, Assembler::Reference(arg), Assembler::ContextRegister);
+}
+
+void InstructionSelection::callBuiltinPopScope()
+{
+ generateFunctionCall(Assembler::ContextRegister, __qmljs_builtin_pop_scope, Assembler::ContextRegister);
+}
+
+void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name)
+{
+ generateFunctionCall(Assembler::Void, __qmljs_builtin_declare_var, Assembler::ContextRegister,
+ Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
+}
+
+void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter)
+{
+ Q_ASSERT(object);
+ Q_ASSERT(getter);
+ Q_ASSERT(setter);
+ generateFunctionCall(Assembler::Void, __qmljs_builtin_define_getter_setter, Assembler::ContextRegister,
+ Assembler::Reference(object), Assembler::PointerToString(name), Assembler::PointerToValue(getter), Assembler::PointerToValue(setter));
+}
+
+void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name,
+ IR::Expr *value)
+{
+ Q_ASSERT(object);
+ Q_ASSERT(value->asTemp() || value->asConst());
+
+ generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property,
+ Assembler::ContextRegister, Assembler::Reference(object),
+ Assembler::PointerToString(name),
+ Assembler::PointerToValue(value));
+}
+
+void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
+{
+ Q_ASSERT(result);
+
+ int length = prepareVariableArguments(args);
+ generateFunctionCall(result, __qmljs_builtin_define_array, Assembler::ContextRegister,
+ baseAddressForCallArguments(), Assembler::TrustedImm32(length));
+}
+
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args)
+{
+ Q_ASSERT(result);
+
+ int argc = 0;
+
+ const int classId = registerJSClass(args);
+
+ IR::ExprList *it = args;
+ while (it) {
+ it = it->next;
+
+ bool isData = it->expr->asConst()->value;
+ it = it->next;
+
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+
+ if (!isData) {
+ it = it->next;
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr);
+ }
+
+ it = it->next;
+ }
+
+ generateFunctionCall(result, __qmljs_builtin_define_object_literal, Assembler::ContextRegister,
+ baseAddressForCallArguments(), Assembler::TrustedImm32(classId));
+}
+
+void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result)
+{
+ generateFunctionCall(result, __qmljs_builtin_setup_arguments_object, Assembler::ContextRegister);
+}
+
+void InstructionSelection::callBuiltinConvertThisToObject()
+{
+ generateFunctionCall(Assembler::Void, __qmljs_builtin_convert_this_to_object, Assembler::ContextRegister);
+}
+
+void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+{
+ Q_ASSERT(value);
+
+ prepareCallData(args, 0);
+ generateFunctionCall(result, __qmljs_call_value, Assembler::ContextRegister,
+ Assembler::Reference(value),
+ baseAddressForCallData());
+}
+
+void InstructionSelection::loadThisObject(IR::Temp *temp)
+{
+ _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, callData)), Assembler::ScratchRegister);
+#if defined(VALUE_FITS_IN_REGISTER)
+ _as->load64(Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)),
+ Assembler::ReturnValueRegister);
+ _as->storeReturnValue(temp);
+#else
+ _as->copyValue(temp, Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)));
+#endif
+}
+
+void InstructionSelection::loadQmlIdArray(IR::Temp *temp)
+{
+ generateFunctionCall(temp, __qmljs_get_id_array, Assembler::ContextRegister);
+}
+
+void InstructionSelection::loadQmlImportedScripts(IR::Temp *temp)
+{
+ generateFunctionCall(temp, __qmljs_get_imported_scripts, Assembler::ContextRegister);
+}
+
+void InstructionSelection::loadQmlContextObject(IR::Temp *temp)
+{
+ generateFunctionCall(temp, __qmljs_get_context_object, Assembler::ContextRegister);
+}
+
+void InstructionSelection::loadQmlScopeObject(IR::Temp *temp)
+{
+ generateFunctionCall(temp, __qmljs_get_scope_object, Assembler::ContextRegister);
+}
+
+void InstructionSelection::loadQmlSingleton(const QString &name, IR::Temp *temp)
+{
+ generateFunctionCall(temp, __qmljs_get_qml_singleton, Assembler::ContextRegister, Assembler::PointerToString(name));
+}
+
+void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
+{
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp->type == IR::DoubleType) {
+ Q_ASSERT(sourceConst->type == IR::DoubleType);
+ _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::SInt32Type) {
+ Q_ASSERT(sourceConst->type == IR::SInt32Type);
+ _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::UInt32Type) {
+ Q_ASSERT(sourceConst->type == IR::UInt32Type);
+ _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::BoolType) {
+ Q_ASSERT(sourceConst->type == IR::BoolType);
+ _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
+ (Assembler::RegisterID) targetTemp->index);
+ } else {
+ Q_UNREACHABLE();
+ }
+ } else {
+ _as->storeValue(convertToValue(sourceConst), targetTemp);
+ }
+}
+
+void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
+{
+ Pointer srcAddr = _as->loadStringAddress(Assembler::ReturnValueRegister, str);
+ _as->loadPtr(srcAddr, Assembler::ReturnValueRegister);
+ Pointer destAddr = _as->loadTempAddress(Assembler::ScratchRegister, targetTemp);
+#if QT_POINTER_SIZE == 8
+ _as->store64(Assembler::ReturnValueRegister, destAddr);
+#else
+ _as->store32(Assembler::ReturnValueRegister, destAddr);
+ destAddr.offset += 4;
+ _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type), destAddr);
+#endif
+}
+
+void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+{
+ int id = registerRegExp(sourceRegexp);
+ generateFunctionCall(targetTemp, __qmljs_lookup_runtime_regexp, Assembler::ContextRegister, Assembler::TrustedImm32(id));
+}
+
+void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Temp *temp)
+{
+ if (useFastLookups && name->global) {
+ uint index = registerGlobalGetterLookup(*name->id);
+ generateLookupCall(temp, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
+ return;
+ }
+ generateFunctionCall(temp, __qmljs_get_activation_property, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
+}
+
+void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
+{
+ // ### should use a lookup call here
+ generateFunctionCall(Assembler::Void, __qmljs_set_activation_property,
+ Assembler::ContextRegister, Assembler::PointerToString(targetName), Assembler::PointerToValue(source));
+}
+
+void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
+{
+ int id = closure->value;
+ generateFunctionCall(target, __qmljs_init_closure, Assembler::ContextRegister, Assembler::TrustedImm32(id));
+}
+
+void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Temp *target)
+{
+ if (useFastLookups) {
+ uint index = registerGetterLookup(name);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), Assembler::PointerToValue(base), Assembler::Void);
+ } else {
+ generateFunctionCall(target, __qmljs_get_property, Assembler::ContextRegister,
+ Assembler::PointerToValue(base), Assembler::PointerToString(name));
+ }
+}
+
+void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target)
+{
+ if (attachedPropertiesId != 0)
+ generateFunctionCall(target, __qmljs_get_attached_property, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
+ else
+ generateFunctionCall(target, __qmljs_get_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
+ Assembler::TrustedImm32(captureRequired));
+}
+
+void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
+ const QString &targetName)
+{
+ if (useFastLookups) {
+ uint index = registerSetterLookup(targetName);
+ generateLookupCall(Assembler::Void, index, qOffsetOf(QV4::Lookup, setter),
+ Assembler::PointerToValue(targetBase),
+ Assembler::PointerToValue(source));
+ } else {
+ generateFunctionCall(Assembler::Void, __qmljs_set_property, Assembler::ContextRegister,
+ Assembler::PointerToValue(targetBase), Assembler::PointerToString(targetName),
+ Assembler::PointerToValue(source));
+ }
+}
+
+void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
+{
+ generateFunctionCall(Assembler::Void, __qmljs_set_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+}
+
+void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+{
+ if (useFastLookups) {
+ uint lookup = registerIndexedGetterLookup();
+ generateLookupCall(target, lookup, qOffsetOf(QV4::Lookup, indexedGetter),
+ Assembler::PointerToValue(base),
+ Assembler::PointerToValue(index));
+ return;
+ }
+
+ generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
+ Assembler::PointerToValue(base), Assembler::PointerToValue(index));
+}
+
+void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex)
+{
+ if (useFastLookups) {
+ uint lookup = registerIndexedSetterLookup();
+ generateLookupCall(Assembler::Void, lookup, qOffsetOf(QV4::Lookup, indexedSetter),
+ Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
+ Assembler::PointerToValue(source));
+ return;
+ }
+ generateFunctionCall(Assembler::Void, __qmljs_set_element, Assembler::ContextRegister,
+ Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
+ Assembler::PointerToValue(source));
+}
+
+void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+{
+ if (*sourceTemp == *targetTemp)
+ return;
+
+ if (sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ if (sourceTemp->type == IR::DoubleType)
+ _as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
+ (Assembler::FPRegisterID) targetTemp->index);
+ else
+ _as->move((Assembler::RegisterID) sourceTemp->index,
+ (Assembler::RegisterID) targetTemp->index);
+ return;
+ } else {
+ switch (sourceTemp->type) {
+ case IR::DoubleType:
+ _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, targetTemp);
+ break;
+ case IR::SInt32Type:
+ _as->storeInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ break;
+ case IR::UInt32Type:
+ _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ break;
+ case IR::BoolType:
+ _as->storeBool((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ break;
+ default:
+ Q_ASSERT(!"Unreachable");
+ break;
+ }
+ return;
+ }
+ } else if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ switch (targetTemp->type) {
+ case IR::DoubleType:
+ Q_ASSERT(sourceTemp->type == IR::DoubleType);
+ _as->toDoubleRegister(sourceTemp, (Assembler::FPRegisterID) targetTemp->index);
+ return;
+ case IR::BoolType:
+ Q_ASSERT(sourceTemp->type == IR::BoolType);
+ _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ return;
+ case IR::SInt32Type:
+ Q_ASSERT(sourceTemp->type == IR::SInt32Type);
+ _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ return;
+ case IR::UInt32Type:
+ Q_ASSERT(sourceTemp->type == IR::UInt32Type);
+ _as->toUInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ return;
+ default:
+ Q_ASSERT(!"Unreachable");
+ break;
+ }
+ }
+
+ // The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
+ _as->memcopyValue(_as->loadTempAddress(Assembler::ReturnValueRegister, targetTemp), sourceTemp,
+ Assembler::ScratchRegister);
+}
+
+void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+{
+ if (sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ Q_ASSERT(sourceTemp->type == targetTemp->type);
+
+ if (sourceTemp->type == IR::DoubleType) {
+ _as->moveDouble((Assembler::FPRegisterID) targetTemp->index, Assembler::FPGpr0);
+ _as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
+ (Assembler::FPRegisterID) targetTemp->index);
+ _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) sourceTemp->index);
+ } else {
+ _as->swap((Assembler::RegisterID) sourceTemp->index,
+ (Assembler::RegisterID) targetTemp->index);
+ }
+ return;
+ }
+ } else if (sourceTemp->kind == IR::Temp::StackSlot) {
+ if (targetTemp->kind == IR::Temp::StackSlot) {
+ // Note: a swap for two stack-slots can involve different types.
+ Assembler::Pointer sAddr = _as->stackSlotPointer(sourceTemp);
+ Assembler::Pointer tAddr = _as->stackSlotPointer(targetTemp);
+ // use the implementation in JSC::MacroAssembler, as it doesn't do bit swizzling
+ _as->JSC::MacroAssembler::loadDouble(sAddr, Assembler::FPGpr0);
+ _as->JSC::MacroAssembler::loadDouble(tAddr, Assembler::FPGpr1);
+ _as->JSC::MacroAssembler::storeDouble(Assembler::FPGpr1, sAddr);
+ _as->JSC::MacroAssembler::storeDouble(Assembler::FPGpr0, tAddr);
+ return;
+ }
+ }
+
+ IR::Temp *stackTemp = sourceTemp->kind == IR::Temp::StackSlot ? sourceTemp : targetTemp;
+ IR::Temp *registerTemp = sourceTemp->kind == IR::Temp::PhysicalRegister ? sourceTemp
+ : targetTemp;
+ Assembler::Pointer addr = _as->stackSlotPointer(stackTemp);
+ if (registerTemp->type == IR::DoubleType) {
+ _as->loadDouble(addr, Assembler::FPGpr0);
+ _as->storeDouble((Assembler::FPRegisterID) registerTemp->index, addr);
+ _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) registerTemp->index);
+ } else if (registerTemp->type == IR::UInt32Type) {
+ _as->toUInt32Register(addr, Assembler::ScratchRegister);
+ _as->storeUInt32((Assembler::RegisterID) registerTemp->index, addr);
+ _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
+ } else {
+ _as->load32(addr, Assembler::ScratchRegister);
+ _as->store32((Assembler::RegisterID) registerTemp->index, addr);
+ if (registerTemp->type != stackTemp->type) {
+ addr.offset += 4;
+ quint32 tag;
+ switch (registerTemp->type) {
+ case IR::BoolType:
+ tag = QV4::Value::_Boolean_Type;
+ break;
+ case IR::SInt32Type:
+ tag = QV4::Value::_Integer_Type;
+ break;
+ default:
+ tag = QV4::Value::Undefined_Type;
+ Q_UNREACHABLE();
+ }
+ _as->store32(Assembler::TrustedImm32(tag), addr);
+ }
+ _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
+ }
+}
+
+#define setOp(op, opName, operation) \
+ do { op = operation; opName = isel_stringIfy(operation); } while (0)
+#define setOpContext(op, opName, operation) \
+ do { opContext = operation; opName = isel_stringIfy(operation); } while (0)
+
+void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp)
+{
+ QV4::JIT::Unop unop(_as, oper);
+ unop.generate(sourceTemp, targetTemp);
+}
+
+
+void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+{
+ QV4::JIT::Binop binop(_as, oper);
+ binop.generate(leftSource, rightSource, target);
+}
+
+void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
+ IR::Temp *result)
+{
+ assert(base != 0);
+
+ prepareCallData(args, base);
+
+ if (useFastLookups) {
+ uint index = registerGetterLookup(name);
+ generateFunctionCall(result, __qmljs_call_property_lookup,
+ Assembler::ContextRegister,
+ Assembler::TrustedImm32(index),
+ baseAddressForCallData());
+ } else
+ {
+ generateFunctionCall(result, __qmljs_call_property, Assembler::ContextRegister,
+ Assembler::PointerToString(name),
+ baseAddressForCallData());
+ }
+}
+
+void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
+ IR::Temp *result)
+{
+ assert(base != 0);
+
+ prepareCallData(args, base);
+ generateFunctionCall(result, __qmljs_call_element, Assembler::ContextRegister,
+ Assembler::PointerToValue(index),
+ baseAddressForCallData());
+}
+
+void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
+{
+ switch (target->type) {
+ case IR::DoubleType:
+ convertTypeToDouble(source, target);
+ break;
+ case IR::BoolType:
+ convertTypeToBool(source, target);
+ break;
+ case IR::SInt32Type:
+ convertTypeToSInt32(source, target);
+ break;
+ case IR::UInt32Type:
+ convertTypeToUInt32(source, target);
+ break;
+ default:
+ convertTypeSlowPath(source, target);
+ break;
+ }
+}
+
+void InstructionSelection::convertTypeSlowPath(IR::Temp *source, IR::Temp *target)
+{
+ Q_ASSERT(target->type != IR::BoolType);
+
+ if (target->type & IR::NumberType)
+ unop(IR::OpUPlus, source, target);
+ else
+ copyValue(source, target);
+}
+
+void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *target)
+{
+ switch (source->type) {
+ case IR::SInt32Type:
+ case IR::BoolType:
+ case IR::NullType:
+ convertIntToDouble(source, target);
+ break;
+ case IR::UInt32Type:
+ convertUIntToDouble(source, target);
+ break;
+ case IR::UndefinedType:
+ _as->loadDouble(_as->loadTempAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
+ _as->storeDouble(Assembler::FPGpr0, target);
+ break;
+ case IR::StringType:
+ case IR::VarType: {
+ // load the tag:
+ Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ tagAddr.offset += 4;
+ _as->load32(tagAddr, Assembler::ScratchRegister);
+
+ // check if it's an int32:
+ Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::_Integer_Type));
+ convertIntToDouble(source, target);
+ Assembler::Jump intDone = _as->jump();
+
+ // not an int, check if it's NOT a double:
+ isNoInt.link(_as);
+#if QT_POINTER_SIZE == 8
+ _as->and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
+ Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(0));
+#else
+ _as->and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
+ Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::NotDouble_Mask));
+#endif
+
+ generateFunctionCall(target, __qmljs_value_to_double, Assembler::PointerToValue(source));
+ Assembler::Jump noDoubleDone = _as->jump();
+
+ // it is a double:
+ isDbl.link(_as);
+ Assembler::Pointer addr2 = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ if (target->kind == IR::Temp::StackSlot) {
+#if QT_POINTER_SIZE == 8
+ _as->load64(addr2, Assembler::ScratchRegister);
+ _as->store64(Assembler::ScratchRegister, _as->stackSlotPointer(target));
+#else
+ _as->loadDouble(addr2, Assembler::FPGpr0);
+ _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+#endif
+ } else {
+ _as->loadDouble(addr2, (Assembler::FPRegisterID) target->index);
+ }
+
+ noDoubleDone.link(_as);
+ intDone.link(_as);
+ } break;
+ default:
+ convertTypeSlowPath(source, target);
+ break;
+ }
+}
+
+void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
+{
+ switch (source->type) {
+ case IR::SInt32Type:
+ case IR::UInt32Type:
+ convertIntToBool(source, target);
+ break;
+ case IR::DoubleType: {
+ // The source is in a register if the register allocator is used. If the register
+ // allocator was not used, then that means that we can use any register for to
+ // load the double into.
+ Assembler::FPRegisterID reg;
+ if (source->kind == IR::Temp::PhysicalRegister)
+ reg = (Assembler::FPRegisterID) source->index;
+ else
+ reg = _as->toDoubleRegister(source, (Assembler::FPRegisterID) 1);
+ Assembler::Jump nonZero = _as->branchDoubleNonZero(reg, Assembler::FPGpr0);
+
+ // it's 0, so false:
+ _as->storeBool(false, target);
+ Assembler::Jump done = _as->jump();
+
+ // it's non-zero, so true:
+ nonZero.link(_as);
+ _as->storeBool(true, target);
+
+ // done:
+ done.link(_as);
+ } break;
+ case IR::UndefinedType:
+ case IR::NullType:
+ _as->storeBool(false, target);
+ break;
+ case IR::StringType:
+ case IR::VarType:
+ default:
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_to_boolean,
+ Assembler::PointerToValue(source));
+ _as->storeBool(Assembler::ReturnValueRegister, target);
+ break;
+ }
+}
+
+void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *target)
+{
+ switch (source->type) {
+ case IR::VarType: {
+
+#if QT_POINTER_SIZE == 8
+ Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ _as->load64(addr, Assembler::ScratchRegister);
+ _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+
+ // check if it's a number
+ _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ScratchRegister);
+ Assembler::Jump isInt = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(1));
+ Assembler::Jump fallback = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
+
+ // it's a double
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
+ _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
+ Assembler::Jump success =
+ _as->branchTruncateDoubleToInt32(Assembler::FPGpr0, Assembler::ReturnValueRegister,
+ Assembler::BranchIfTruncateSuccessful);
+
+ // not an int:
+ fallback.link(_as);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+ _as->loadTempAddress(Assembler::ScratchRegister, source));
+
+ isInt.link(_as);
+ success.link(_as);
+ if (target->kind == IR::Temp::StackSlot) {
+ Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
+ _as->store32(Assembler::ReturnValueRegister, targetAddr);
+ targetAddr.offset += 4;
+ _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
+ } else {
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+ }
+#else
+ // load the tag:
+ Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tagAddr = addr;
+ tagAddr.offset += 4;
+ _as->load32(tagAddr, Assembler::ReturnValueRegister);
+
+ // check if it's an int32:
+ Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
+ Assembler::TrustedImm32(Value::_Integer_Type));
+ if (target->kind == IR::Temp::StackSlot) {
+ _as->load32(addr, Assembler::ScratchRegister);
+ Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
+ _as->store32(Assembler::ScratchRegister, targetAddr);
+ targetAddr.offset += 4;
+ _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
+ } else {
+ _as->load32(addr, (Assembler::RegisterID) target->index);
+ }
+ Assembler::Jump intDone = _as->jump();
+
+ // not an int:
+ fallback.link(_as);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+ _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+
+ intDone.link(_as);
+#endif
+
+ } break;
+ case IR::DoubleType: {
+ Assembler::Jump success =
+ _as->branchTruncateDoubleToInt32(_as->toDoubleRegister(source),
+ Assembler::ReturnValueRegister,
+ Assembler::BranchIfTruncateSuccessful);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_int32,
+ Assembler::PointerToValue(source));
+ success.link(_as);
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+ } break;
+ case IR::UInt32Type:
+ _as->storeInt32(_as->toUInt32Register(source, Assembler::ReturnValueRegister), target);
+ break;
+ case IR::NullType:
+ case IR::UndefinedType:
+ _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+ break;
+ case IR::BoolType:
+ _as->storeInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
+ break;
+ case IR::StringType:
+ default:
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+ _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+ break;
+ } // switch (source->type)
+}
+
+void InstructionSelection::convertTypeToUInt32(IR::Temp *source, IR::Temp *target)
+{
+ switch (source->type) {
+ case IR::VarType: {
+ // load the tag:
+ Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ tagAddr.offset += 4;
+ _as->load32(tagAddr, Assembler::ScratchRegister);
+
+ // check if it's an int32:
+ Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::_Integer_Type));
+ Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ _as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
+ Assembler::Jump intDone = _as->jump();
+
+ // not an int:
+ isNoInt.link(_as);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
+ _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+
+ intDone.link(_as);
+ } break;
+ case IR::DoubleType: {
+ Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
+ Assembler::Jump success =
+ _as->branchTruncateDoubleToUint32(reg, Assembler::ReturnValueRegister,
+ Assembler::BranchIfTruncateSuccessful);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_uint32,
+ Assembler::PointerToValue(source));
+ success.link(_as);
+ _as->storeUInt32(Assembler::ReturnValueRegister, target);
+ } break;
+ case IR::NullType:
+ case IR::UndefinedType:
+ _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
+ _as->storeUInt32(Assembler::ReturnValueRegister, target);
+ break;
+ case IR::StringType:
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
+ Assembler::PointerToValue(source));
+ _as->storeUInt32(Assembler::ReturnValueRegister, target);
+ break;
+ case IR::SInt32Type:
+ case IR::BoolType:
+ _as->storeUInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
+ break;
+ default:
+ break;
+ } // switch (source->type)
+}
+
+void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+{
+ assert(func != 0);
+ prepareCallData(args, 0);
+
+ if (useFastLookups && func->global) {
+ uint index = registerGlobalGetterLookup(*func->id);
+ generateFunctionCall(result, __qmljs_construct_global_lookup,
+ Assembler::ContextRegister,
+ Assembler::TrustedImm32(index), baseAddressForCallData());
+ return;
+ }
+
+ generateFunctionCall(result, __qmljs_construct_activation_property,
+ Assembler::ContextRegister,
+ Assembler::PointerToString(*func->id),
+ baseAddressForCallData());
+}
+
+
+void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
+{
+ prepareCallData(args, base);
+ if (useFastLookups) {
+ uint index = registerGetterLookup(name);
+ generateFunctionCall(result, __qmljs_construct_property_lookup,
+ Assembler::ContextRegister,
+ Assembler::TrustedImm32(index),
+ baseAddressForCallData());
+ return;
+ }
+
+ generateFunctionCall(result, __qmljs_construct_property, Assembler::ContextRegister,
+ Assembler::PointerToString(name),
+ baseAddressForCallData());
+}
+
+void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+{
+ assert(value != 0);
+
+ prepareCallData(args, 0);
+ generateFunctionCall(result, __qmljs_construct_value,
+ Assembler::ContextRegister,
+ Assembler::Reference(value),
+ baseAddressForCallData());
+}
+
+void InstructionSelection::visitJump(IR::Jump *s)
+{
+ if (!_removableJumps.contains(s))
+ _as->jumpToBlock(_block, s->target);
+}
+
+void InstructionSelection::visitCJump(IR::CJump *s)
+{
+ if (IR::Temp *t = s->cond->asTemp()) {
+ Assembler::RegisterID reg;
+ if (t->kind == IR::Temp::PhysicalRegister) {
+ Q_ASSERT(t->type == IR::BoolType);
+ reg = (Assembler::RegisterID) t->index;
+ } else if (t->kind == IR::Temp::StackSlot && t->type == IR::BoolType) {
+ reg = Assembler::ReturnValueRegister;
+ _as->toInt32Register(t, reg);
+ } else {
+ Address temp = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Address tag = temp;
+ tag.offset += qOffsetOf(QV4::Value, tag);
+ Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
+
+ Address data = temp;
+ data.offset += qOffsetOf(QV4::Value, int_32);
+ _as->load32(data, Assembler::ReturnValueRegister);
+ Assembler::Jump testBoolean = _as->jump();
+
+ booleanConversion.link(_as);
+ reg = Assembler::ReturnValueRegister;
+ generateFunctionCall(reg, __qmljs_to_boolean, Assembler::Reference(t));
+
+ testBoolean.link(_as);
+ }
+
+ _as->generateCJumpOnNonZero(reg, _block, s->iftrue, s->iffalse);
+ return;
+ } else if (IR::Const *c = s->cond->asConst()) {
+ // TODO: SSA optimization for constant condition evaluation should remove this.
+ // See also visitCJump() in RegAllocInfo.
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_to_boolean,
+ Assembler::PointerToValue(c));
+ _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
+ return;
+ } else if (IR::Binop *b = s->cond->asBinop()) {
+ if (b->left->type == IR::DoubleType && b->right->type == IR::DoubleType
+ && visitCJumpDouble(b->op, b->left, b->right, s->iftrue, s->iffalse))
+ return;
+
+ if (b->op == IR::OpStrictEqual || b->op == IR::OpStrictNotEqual) {
+ visitCJumpStrict(b, s->iftrue, s->iffalse);
+ return;
+ }
+ if (b->op == IR::OpEqual || b->op == IR::OpNotEqual) {
+ visitCJumpEqual(b, s->iftrue, s->iffalse);
+ return;
+ }
+
+ CmpOp op = 0;
+ CmpOpContext opContext = 0;
+ const char *opName = 0;
+ switch (b->op) {
+ default: Q_UNREACHABLE(); assert(!"todo"); break;
+ case IR::OpGt: setOp(op, opName, __qmljs_cmp_gt); break;
+ case IR::OpLt: setOp(op, opName, __qmljs_cmp_lt); break;
+ case IR::OpGe: setOp(op, opName, __qmljs_cmp_ge); break;
+ case IR::OpLe: setOp(op, opName, __qmljs_cmp_le); break;
+ case IR::OpEqual: setOp(op, opName, __qmljs_cmp_eq); break;
+ case IR::OpNotEqual: setOp(op, opName, __qmljs_cmp_ne); break;
+ case IR::OpStrictEqual: setOp(op, opName, __qmljs_cmp_se); break;
+ case IR::OpStrictNotEqual: setOp(op, opName, __qmljs_cmp_sne); break;
+ case IR::OpInstanceof: setOpContext(op, opName, __qmljs_cmp_instanceof); break;
+ case IR::OpIn: setOpContext(op, opName, __qmljs_cmp_in); break;
+ } // switch
+
+ // TODO: in SSA optimization, do constant expression evaluation.
+ // The case here is, for example:
+ // if (true === true) .....
+ // Of course, after folding the CJUMP to a JUMP, dead-code (dead-basic-block)
+ // elimination (which isn't there either) would remove the whole else block.
+ if (opContext)
+ _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, opContext,
+ Assembler::ContextRegister,
+ Assembler::PointerToValue(b->left),
+ Assembler::PointerToValue(b->right));
+ else
+ _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, op,
+ Assembler::PointerToValue(b->left),
+ Assembler::PointerToValue(b->right));
+
+ _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
+ return;
+ }
+ Q_UNREACHABLE();
+}
+
+void InstructionSelection::visitRet(IR::Ret *s)
+{
+ if (!s) {
+ // this only happens if the method doesn't have a return statement and can
+ // only exit through an exception
+ } else if (IR::Temp *t = s->expr->asTemp()) {
+#if CPU(X86) || CPU(ARM)
+
+# if CPU(X86)
+ Assembler::RegisterID lowReg = JSC::X86Registers::eax;
+ Assembler::RegisterID highReg = JSC::X86Registers::edx;
+# else // CPU(ARM)
+ Assembler::RegisterID lowReg = JSC::ARMRegisters::r0;
+ Assembler::RegisterID highReg = JSC::ARMRegisters::r1;
+# endif
+
+ if (t->kind == IR::Temp::PhysicalRegister) {
+ switch (t->type) {
+ case IR::DoubleType:
+ _as->moveDoubleToInts((Assembler::FPRegisterID) t->index, lowReg, highReg);
+ break;
+ case IR::UInt32Type: {
+ Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
+ Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
+ _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
+ _as->moveDoubleToInts(Assembler::FPGpr0, lowReg, highReg);
+ Assembler::Jump done = _as->jump();
+ intRange.link(_as);
+ _as->move(srcReg, lowReg);
+ _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), highReg);
+ done.link(_as);
+ } break;
+ case IR::SInt32Type:
+ _as->move((Assembler::RegisterID) t->index, lowReg);
+ _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), highReg);
+ break;
+ case IR::BoolType:
+ _as->move((Assembler::RegisterID) t->index, lowReg);
+ _as->move(Assembler::TrustedImm32(QV4::Value::_Boolean_Type), highReg);
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ } else {
+ Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ _as->load32(addr, lowReg);
+ addr.offset += 4;
+ _as->load32(addr, highReg);
+ }
+#else
+ if (t->kind == IR::Temp::PhysicalRegister) {
+ if (t->type == IR::DoubleType) {
+ _as->moveDoubleTo64((Assembler::FPRegisterID) t->index,
+ Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask),
+ Assembler::ScratchRegister);
+ _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ } else if (t->type == IR::UInt32Type) {
+ Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
+ Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
+ _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
+ _as->moveDoubleTo64(Assembler::FPGpr0, Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
+ _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ Assembler::Jump done = _as->jump();
+ intRange.link(_as);
+ _as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister);
+ quint64 tag = QV4::Value::_Integer_Type;
+ _as->or64(Assembler::TrustedImm64(tag << 32),
+ Assembler::ReturnValueRegister);
+ done.link(_as);
+ } else {
+ _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, Assembler::ReturnValueRegister);
+ quint64 tag;
+ switch (t->type) {
+ case IR::SInt32Type:
+ tag = QV4::Value::_Integer_Type;
+ break;
+ case IR::BoolType:
+ tag = QV4::Value::_Boolean_Type;
+ break;
+ default:
+ tag = QV4::Value::Undefined_Type;
+ Q_UNREACHABLE();
+ }
+ _as->or64(Assembler::TrustedImm64(tag << 32),
+ Assembler::ReturnValueRegister);
+ }
+ } else {
+ _as->copyValue(Assembler::ReturnValueRegister, t);
+ }
+#endif
+ } else if (IR::Const *c = s->expr->asConst()) {
+ QV4::Primitive retVal = convertToValue(c);
+#if CPU(X86)
+ _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+#elif CPU(ARM)
+ _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
+ _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+#else
+ _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
+#endif
+ } else {
+ Q_UNREACHABLE();
+ Q_UNUSED(s);
+ }
+
+ _as->exceptionReturnLabel = _as->label();
+
+ const int locals = _as->stackLayout().calculateJSStackFrameSize();
+ _as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
+ _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
+
+ _as->leaveStandardStackFrame();
+ _as->ret();
+}
+
+int InstructionSelection::prepareVariableArguments(IR::ExprList* args)
+{
+ int argc = 0;
+ for (IR::ExprList *it = args; it; it = it->next) {
+ ++argc;
+ }
+
+ int i = 0;
+ for (IR::ExprList *it = args; it; it = it->next, ++i) {
+ IR::Expr *arg = it->expr;
+ Q_ASSERT(arg != 0);
+ Pointer dst(_as->stackLayout().argumentAddressForCall(i));
+ if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister)
+ _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
+ else
+ _as->copyValue(dst, arg);
+ }
+
+ return argc;
+}
+
+int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObject)
+{
+ int argc = 0;
+ for (IR::ExprList *it = args; it; it = it->next) {
+ ++argc;
+ }
+
+ Pointer p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, tag));
+ _as->store32(Assembler::TrustedImm32(QV4::Value::_Integer_Type), p);
+ p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, argc));
+ _as->store32(Assembler::TrustedImm32(argc), p);
+ p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, thisObject));
+ if (!thisObject)
+ _as->storeValue(QV4::Primitive::undefinedValue(), p);
+ else
+ _as->copyValue(p, thisObject);
+
+ int i = 0;
+ for (IR::ExprList *it = args; it; it = it->next, ++i) {
+ IR::Expr *arg = it->expr;
+ Q_ASSERT(arg != 0);
+ Pointer dst(_as->stackLayout().argumentAddressForCall(i));
+ if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister)
+ _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
+ else
+ _as->copyValue(dst, arg);
+ }
+ return argc;
+}
+
+
+QT_BEGIN_NAMESPACE
+namespace QV4 {
+bool operator==(const Primitive &v1, const Primitive &v2)
+{
+ return v1.rawValue() == v2.rawValue();
+}
+} // QV4 namespace
+QT_END_NAMESPACE
+
+int Assembler::ConstantTable::add(const Primitive &v)
+{
+ int idx = _values.indexOf(v);
+ if (idx == -1) {
+ idx = _values.size();
+ _values.append(v);
+ }
+ return idx;
+}
+
+Assembler::ImplicitAddress Assembler::ConstantTable::loadValueAddress(IR::Const *c,
+ RegisterID baseReg)
+{
+ return loadValueAddress(convertToValue(c), baseReg);
+}
+
+Assembler::ImplicitAddress Assembler::ConstantTable::loadValueAddress(const Primitive &v,
+ RegisterID baseReg)
+{
+ _toPatch.append(_as->moveWithPatch(TrustedImmPtr(0), baseReg));
+ ImplicitAddress addr(baseReg);
+ addr.offset = add(v) * sizeof(QV4::Primitive);
+ Q_ASSERT(addr.offset >= 0);
+ return addr;
+}
+
+void Assembler::ConstantTable::finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel)
+{
+ void *tablePtr = isel->addConstantTable(&_values);
+
+ foreach (DataLabelPtr label, _toPatch)
+ linkBuffer.patch(label, tablePtr);
+}
+
+bool InstructionSelection::visitCJumpDouble(IR::AluOp op, IR::Expr *left, IR::Expr *right,
+ IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
+{
+ if (!isPregOrConst(left) || !isPregOrConst(right))
+ return false;
+
+ if (_as->nextBlock() == iftrue) {
+ Assembler::Jump target = _as->branchDouble(true, op, left, right);
+ _as->addPatch(iffalse, target);
+ } else {
+ Assembler::Jump target = _as->branchDouble(false, op, left, right);
+ _as->addPatch(iftrue, target);
+ _as->jumpToBlock(_block, iffalse);
+ }
+ return true;
+}
+
+void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ Q_ASSERT(binop->op == IR::OpStrictEqual || binop->op == IR::OpStrictNotEqual);
+
+ if (visitCJumpStrictNullUndefined(IR::NullType, binop, trueBlock, falseBlock))
+ return;
+ if (visitCJumpStrictNullUndefined(IR::UndefinedType, binop, trueBlock, falseBlock))
+ return;
+ if (visitCJumpStrictBool(binop, trueBlock, falseBlock))
+ return;
+
+ IR::Expr *left = binop->left;
+ IR::Expr *right = binop->right;
+
+ _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "__qmljs_cmp_se", __qmljs_cmp_se,
+ Assembler::PointerToValue(left), Assembler::PointerToValue(right));
+ _as->generateCJumpOnCompare(binop->op == IR::OpStrictEqual ? Assembler::NotEqual : Assembler::Equal,
+ Assembler::ReturnValueRegister, Assembler::TrustedImm32(0),
+ _block, trueBlock, falseBlock);
+}
+
+// Only load the non-null temp.
+bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+ IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ Q_ASSERT(nullOrUndef == IR::NullType || nullOrUndef == IR::UndefinedType);
+
+ IR::Expr *varSrc = 0;
+ if (binop->left->type == IR::VarType && binop->right->type == nullOrUndef)
+ varSrc = binop->left;
+ else if (binop->left->type == nullOrUndef && binop->right->type == IR::VarType)
+ varSrc = binop->right;
+ if (!varSrc)
+ return false;
+
+ if (varSrc->asTemp() && varSrc->asTemp()->kind == IR::Temp::PhysicalRegister) {
+ _as->jumpToBlock(_block, falseBlock);
+ return true;
+ }
+
+ if (IR::Const *c = varSrc->asConst()) {
+ if (c->type == nullOrUndef)
+ _as->jumpToBlock(_block, trueBlock);
+ else
+ _as->jumpToBlock(_block, falseBlock);
+ return true;
+ }
+
+ IR::Temp *t = varSrc->asTemp();
+ Q_ASSERT(t);
+
+ Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ tagAddr.offset += 4;
+ const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
+ _as->load32(tagAddr, tagReg);
+
+ Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
+ : Assembler::NotEqual;
+ const Assembler::TrustedImm32 tag(nullOrUndef == IR::NullType ? int(QV4::Value::_Null_Type)
+ : int(QV4::Value::Undefined_Type));
+ _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
+ return true;
+}
+
+bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ IR::Expr *boolSrc = 0, *otherSrc = 0;
+ if (binop->left->type == IR::BoolType) {
+ boolSrc = binop->left;
+ otherSrc = binop->right;
+ } else if (binop->right->type == IR::BoolType) {
+ boolSrc = binop->right;
+ otherSrc = binop->left;
+ } else {
+ // neither operands are statically typed as bool, so bail out.
+ return false;
+ }
+
+ Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
+ : Assembler::NotEqual;
+
+ if (otherSrc->type == IR::BoolType) { // both are boolean
+ Assembler::RegisterID one = _as->toBoolRegister(boolSrc, Assembler::ReturnValueRegister);
+ Assembler::RegisterID two = _as->toBoolRegister(otherSrc, Assembler::ScratchRegister);
+ _as->generateCJumpOnCompare(cond, one, two, _block, trueBlock, falseBlock);
+ return true;
+ }
+
+ if (otherSrc->type != IR::VarType) {
+ _as->jumpToBlock(_block, falseBlock);
+ return true;
+ }
+
+ IR::Temp *otherTemp = otherSrc->asTemp();
+ Q_ASSERT(otherTemp); // constants cannot have "var" type
+ Q_ASSERT(otherTemp->kind != IR::Temp::PhysicalRegister);
+
+ Assembler::Pointer otherAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, otherTemp);
+ otherAddr.offset += 4; // tag address
+
+ // check if the tag of the var operand is indicates 'boolean'
+ _as->load32(otherAddr, Assembler::ScratchRegister);
+ Assembler::Jump noBool = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(QV4::Value::_Boolean_Type));
+ if (binop->op == IR::OpStrictEqual)
+ _as->addPatch(falseBlock, noBool);
+ else
+ _as->addPatch(trueBlock, noBool);
+
+ // ok, both are boolean, so let's load them and compare them.
+ otherAddr.offset -= 4; // int_32 address
+ _as->load32(otherAddr, Assembler::ReturnValueRegister);
+ Assembler::RegisterID boolReg = _as->toBoolRegister(boolSrc, Assembler::ScratchRegister);
+ _as->generateCJumpOnCompare(cond, boolReg, Assembler::ReturnValueRegister, _block, trueBlock,
+ falseBlock);
+ return true;
+}
+
+bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+ IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ Q_ASSERT(nullOrUndef == IR::NullType || nullOrUndef == IR::UndefinedType);
+
+ IR::Expr *varSrc = 0;
+ if (binop->left->type == IR::VarType && binop->right->type == nullOrUndef)
+ varSrc = binop->left;
+ else if (binop->left->type == nullOrUndef && binop->right->type == IR::VarType)
+ varSrc = binop->right;
+ if (!varSrc)
+ return false;
+
+ if (varSrc->asTemp() && varSrc->asTemp()->kind == IR::Temp::PhysicalRegister) {
+ _as->jumpToBlock(_block, falseBlock);
+ return true;
+ }
+
+ if (IR::Const *c = varSrc->asConst()) {
+ if (c->type == nullOrUndef)
+ _as->jumpToBlock(_block, trueBlock);
+ else
+ _as->jumpToBlock(_block, falseBlock);
+ return true;
+ }
+
+ IR::Temp *t = varSrc->asTemp();
+ Q_ASSERT(t);
+
+ Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ tagAddr.offset += 4;
+ const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
+ _as->load32(tagAddr, tagReg);
+
+ if (binop->op == IR::OpNotEqual)
+ qSwap(trueBlock, falseBlock);
+ Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::_Null_Type)));
+ Assembler::Jump isUndefined = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Undefined_Type)));
+ _as->addPatch(trueBlock, isNull);
+ _as->addPatch(trueBlock, isUndefined);
+ _as->jumpToBlock(_block, falseBlock);
+
+ return true;
+}
+
+
+void InstructionSelection::visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+{
+ Q_ASSERT(binop->op == IR::OpEqual || binop->op == IR::OpNotEqual);
+
+ if (visitCJumpNullUndefined(IR::NullType, binop, trueBlock, falseBlock))
+ return;
+
+ IR::Expr *left = binop->left;
+ IR::Expr *right = binop->right;
+
+ _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "__qmljs_cmp_eq", __qmljs_cmp_eq,
+ Assembler::PointerToValue(left), Assembler::PointerToValue(right));
+ _as->generateCJumpOnCompare(binop->op == IR::OpEqual ? Assembler::NotEqual : Assembler::Equal,
+ Assembler::ReturnValueRegister, Assembler::TrustedImm32(0),
+ _block, trueBlock, falseBlock);
+}
+
+
+#endif // ENABLE(ASSEMBLER)
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
new file mode 100644
index 0000000000..69317cb062
--- /dev/null
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4ISEL_MASM_P_H
+#define QV4ISEL_MASM_P_H
+
+#include "private/qv4global_p.h"
+#include "private/qv4jsir_p.h"
+#include "private/qv4isel_p.h"
+#include "private/qv4isel_util_p.h"
+#include "private/qv4value_p.h"
+#include "private/qv4lookup_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QStack>
+#include <config.h>
+#include <wtf/Vector.h>
+
+#include "qv4assembler_p.h"
+
+#if ENABLE(ASSEMBLER)
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace JIT {
+
+class Q_QML_EXPORT InstructionSelection:
+ protected IR::IRDecoder,
+ public EvalInstructionSelection
+{
+public:
+ InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ ~InstructionSelection();
+
+ virtual void run(int functionIndex);
+
+ void *addConstantTable(QVector<QV4::Primitive> *values);
+protected:
+ virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
+
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result);
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result);
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result);
+ virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result);
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result);
+ virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result);
+ virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result);
+ virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result);
+ virtual void callBuiltinDeleteValue(IR::Temp *result);
+ virtual void callBuiltinThrow(IR::Expr *arg);
+ virtual void callBuiltinReThrow();
+ virtual void callBuiltinUnwindException(IR::Temp *);
+ virtual void callBuiltinPushCatchScope(const QString &exceptionName);
+ virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result);
+ virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
+ virtual void callBuiltinPushWithScope(IR::Temp *arg);
+ virtual void callBuiltinPopScope();
+ virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
+ virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter);
+ virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Expr *value);
+ virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, IR::ExprList *args);
+ virtual void callBuiltinSetupArgumentObject(IR::Temp *result);
+ virtual void callBuiltinConvertThisToObject();
+ virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result);
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result);
+ virtual void convertType(IR::Temp *source, IR::Temp *target);
+ virtual void loadThisObject(IR::Temp *temp);
+ virtual void loadQmlIdArray(IR::Temp *temp);
+ virtual void loadQmlImportedScripts(IR::Temp *temp);
+ virtual void loadQmlContextObject(IR::Temp *temp);
+ virtual void loadQmlScopeObject(IR::Temp *temp);
+ virtual void loadQmlSingleton(const QString &name, IR::Temp *temp);
+ virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp);
+ virtual void loadString(const QString &str, IR::Temp *targetTemp);
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp);
+ virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp);
+ virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
+ virtual void initClosure(IR::Closure *closure, IR::Temp *target);
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target);
+ virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target);
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target);
+ virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
+ virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp);
+ virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp);
+ virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp);
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+
+ typedef Assembler::Address Address;
+ typedef Assembler::Pointer Pointer;
+
+#if !defined(ARGUMENTS_IN_REGISTERS)
+ Address addressForArgument(int index) const
+ {
+ // StackFrameRegister points to its old value on the stack, and above
+ // it we have the return address, hence the need to step over two
+ // values before reaching the first argument.
+ return Address(Assembler::StackFrameRegister, (index + 2) * sizeof(void*));
+ }
+#endif
+
+ Pointer baseAddressForCallArguments()
+ {
+ return _as->stackLayout().argumentAddressForCall(0);
+ }
+
+ Pointer baseAddressForCallData()
+ {
+ return _as->stackLayout().callDataAddress();
+ }
+
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result);
+ virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result);
+ virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
+
+ virtual void visitJump(IR::Jump *);
+ virtual void visitCJump(IR::CJump *);
+ virtual void visitRet(IR::Ret *);
+
+ bool visitCJumpDouble(IR::AluOp op, IR::Expr *left, IR::Expr *right,
+ IR::BasicBlock *iftrue, IR::BasicBlock *iffalse);
+ void visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+ bool visitCJumpStrictNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+ IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+ bool visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+ bool visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+ IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+ void visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+
+private:
+ void convertTypeSlowPath(IR::Temp *source, IR::Temp *target);
+ void convertTypeToDouble(IR::Temp *source, IR::Temp *target);
+ void convertTypeToBool(IR::Temp *source, IR::Temp *target);
+ void convertTypeToSInt32(IR::Temp *source, IR::Temp *target);
+ void convertTypeToUInt32(IR::Temp *source, IR::Temp *target);
+
+ void convertIntToDouble(IR::Temp *source, IR::Temp *target)
+ {
+ if (target->kind == IR::Temp::PhysicalRegister) {
+ _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
+ (Assembler::FPRegisterID) target->index);
+ } else {
+ _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
+ Assembler::FPGpr0);
+ _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ }
+ }
+
+ void convertUIntToDouble(IR::Temp *source, IR::Temp *target)
+ {
+ Assembler::RegisterID tmpReg = Assembler::ScratchRegister;
+ Assembler::RegisterID reg = _as->toInt32Register(source, tmpReg);
+
+ if (target->kind == IR::Temp::PhysicalRegister) {
+ _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) target->index, tmpReg);
+ } else {
+ _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
+ Assembler::FPGpr0, tmpReg);
+ _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ }
+ }
+
+ void convertIntToBool(IR::Temp *source, IR::Temp *target)
+ {
+ Assembler::RegisterID reg = target->kind == IR::Temp::PhysicalRegister
+ ? (Assembler::RegisterID) target->index
+ : Assembler::ScratchRegister;
+
+ _as->move(_as->toInt32Register(source, reg), reg);
+ _as->compare32(Assembler::NotEqual, reg, Assembler::TrustedImm32(0), reg);
+ _as->storeBool(reg, target);
+ }
+
+ #define isel_stringIfyx(s) #s
+ #define isel_stringIfy(s) isel_stringIfyx(s)
+
+ #define generateFunctionCall(t, function, ...) \
+ _as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__)
+
+ int prepareVariableArguments(IR::ExprList* args);
+ int prepareCallData(IR::ExprList* args, IR::Expr *thisObject);
+
+ template <typename Retval, typename Arg1, typename Arg2, typename Arg3>
+ void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Assembler::RegisterID lookupRegister;
+#if CPU(ARM)
+ lookupRegister = JSC::ARMRegisters::r8;
+#else
+ lookupRegister = Assembler::ReturnValueRegister;
+#endif
+ Assembler::Pointer lookupAddr(lookupRegister, index * sizeof(QV4::Lookup));
+
+ Assembler::Address getterSetter = lookupAddr;
+ getterSetter.offset += getterSetterOffset;
+
+ _as->generateFunctionCallImp(retval, "lookup getter/setter",
+ RelativeCall(getterSetter), lookupAddr, arg1, arg2, arg3);
+ }
+
+ template <typename Retval, typename Arg1, typename Arg2>
+ void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
+ {
+ generateLookupCall(retval, index, getterSetterOffset, arg1, arg2, Assembler::VoidType());
+ }
+
+ IR::BasicBlock *_block;
+ QSet<IR::Jump *> _removableJumps;
+ Assembler* _as;
+
+ CompilationUnit *compilationUnit;
+ QQmlEnginePrivate *qmlEngine;
+};
+
+class Q_QML_EXPORT ISelFactory: public EvalISelFactory
+{
+public:
+ virtual ~ISelFactory() {}
+ virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
+ { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
+ virtual bool jitCompileRegexps() const
+ { return true; }
+};
+
+} // end of namespace JIT
+} // end of namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // QV4ISEL_MASM_P_H
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index ea2338acad..4ff03611fa 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "qv4regalloc_p.h"
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <algorithm>
@@ -60,10 +60,13 @@ struct Use {
}
QT_BEGIN_NAMESPACE
-using namespace QQmlJS::V4IR;
-namespace QQmlJS {
-namespace MASM {
+Q_DECLARE_TYPEINFO(Use, Q_MOVABLE_TYPE);
+
+using namespace QV4::IR;
+
+namespace QV4 {
+namespace JIT {
class RegAllocInfo: public IRDecoder
{
@@ -92,7 +95,7 @@ class RegAllocInfo: public IRDecoder
public:
RegAllocInfo(): _currentStmt(0) {}
- void collect(Function *function)
+ void collect(IR::Function *function)
{
foreach (BasicBlock *bb, function->basicBlocks) {
foreach (Stmt *s, bb->statements) {
@@ -191,33 +194,33 @@ public:
#endif // DEBUG_REGALLOC
protected: // IRDecoder
- virtual void callBuiltinInvalid(V4IR::Name *, V4IR::ExprList *, V4IR::Temp *) {}
- virtual void callBuiltinTypeofMember(V4IR::Expr *, const QString &, V4IR::Temp *) {}
- virtual void callBuiltinTypeofSubscript(V4IR::Expr *, V4IR::Expr *, V4IR::Temp *) {}
- virtual void callBuiltinTypeofName(const QString &, V4IR::Temp *) {}
- virtual void callBuiltinTypeofValue(V4IR::Expr *, V4IR::Temp *) {}
- virtual void callBuiltinDeleteMember(V4IR::Temp *, const QString &, V4IR::Temp *) {}
- virtual void callBuiltinDeleteSubscript(V4IR::Temp *, V4IR::Expr *, V4IR::Temp *) {}
- virtual void callBuiltinDeleteName(const QString &, V4IR::Temp *) {}
- virtual void callBuiltinDeleteValue(V4IR::Temp *) {}
- virtual void callBuiltinThrow(V4IR::Expr *) {}
+ virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Temp *) {}
+ virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Temp *) {}
+ virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Temp *) {}
+ virtual void callBuiltinTypeofName(const QString &, IR::Temp *) {}
+ virtual void callBuiltinTypeofValue(IR::Expr *, IR::Temp *) {}
+ virtual void callBuiltinDeleteMember(IR::Temp *, const QString &, IR::Temp *) {}
+ virtual void callBuiltinDeleteSubscript(IR::Temp *, IR::Expr *, IR::Temp *) {}
+ virtual void callBuiltinDeleteName(const QString &, IR::Temp *) {}
+ virtual void callBuiltinDeleteValue(IR::Temp *) {}
+ virtual void callBuiltinThrow(IR::Expr *) {}
virtual void callBuiltinReThrow() {}
- virtual void callBuiltinUnwindException(V4IR::Temp *) {}
+ virtual void callBuiltinUnwindException(IR::Temp *) {}
virtual void callBuiltinPushCatchScope(const QString &) {};
- virtual void callBuiltinForeachIteratorObject(V4IR::Temp *, V4IR::Temp *) {}
- virtual void callBuiltinForeachNextProperty(V4IR::Temp *, V4IR::Temp *) {}
- virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *, V4IR::Temp *) {}
- virtual void callBuiltinPushWithScope(V4IR::Temp *) {}
+ virtual void callBuiltinForeachIteratorObject(IR::Temp *, IR::Temp *) {}
+ virtual void callBuiltinForeachNextProperty(IR::Temp *, IR::Temp *) {}
+ virtual void callBuiltinForeachNextPropertyname(IR::Temp *, IR::Temp *) {}
+ virtual void callBuiltinPushWithScope(IR::Temp *) {}
virtual void callBuiltinPopScope() {}
virtual void callBuiltinDeclareVar(bool , const QString &) {}
- virtual void callBuiltinDefineGetterSetter(V4IR::Temp *, const QString &, V4IR::Temp *, V4IR::Temp *) {}
- virtual void callBuiltinDefineProperty(V4IR::Temp *, const QString &, V4IR::Expr *) {}
- virtual void callBuiltinDefineArray(V4IR::Temp *, V4IR::ExprList *) {}
- virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *, V4IR::ExprList *) {}
- virtual void callBuiltinSetupArgumentObject(V4IR::Temp *) {}
+ virtual void callBuiltinDefineGetterSetter(IR::Temp *, const QString &, IR::Temp *, IR::Temp *) {}
+ virtual void callBuiltinDefineProperty(IR::Temp *, const QString &, IR::Expr *) {}
+ virtual void callBuiltinDefineArray(IR::Temp *, IR::ExprList *) {}
+ virtual void callBuiltinDefineObjectLiteral(IR::Temp *, IR::ExprList *) {}
+ virtual void callBuiltinSetupArgumentObject(IR::Temp *) {}
virtual void callBuiltinConvertThisToObject() {}
- virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
+ virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
{
addDef(result);
addUses(value, Use::CouldHaveRegister);
@@ -225,8 +228,8 @@ protected: // IRDecoder
addCall();
}
- virtual void callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args,
- V4IR::Temp *result)
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
+ IR::Temp *result)
{
Q_UNUSED(name)
@@ -236,8 +239,8 @@ protected: // IRDecoder
addCall();
}
- virtual void callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args,
- V4IR::Temp *result)
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
+ IR::Temp *result)
{
addDef(result);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -246,7 +249,7 @@ protected: // IRDecoder
addCall();
}
- virtual void convertType(V4IR::Temp *source, V4IR::Temp *target)
+ virtual void convertType(IR::Temp *source, IR::Temp *target)
{
addDef(target);
@@ -317,14 +320,14 @@ protected: // IRDecoder
addHint(target, source);
}
- virtual void constructActivationProperty(V4IR::Name *, V4IR::ExprList *args, V4IR::Temp *result)
+ virtual void constructActivationProperty(IR::Name *, IR::ExprList *args, IR::Temp *result)
{
addDef(result);
addUses(args, Use::CouldHaveRegister);
addCall();
}
- virtual void constructProperty(V4IR::Temp *base, const QString &, V4IR::ExprList *args, V4IR::Temp *result)
+ virtual void constructProperty(IR::Temp *base, const QString &, IR::ExprList *args, IR::Temp *result)
{
addDef(result);
addUses(base, Use::CouldHaveRegister);
@@ -332,7 +335,7 @@ protected: // IRDecoder
addCall();
}
- virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
+ virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
{
addDef(result);
addUses(value, Use::CouldHaveRegister);
@@ -340,18 +343,18 @@ protected: // IRDecoder
addCall();
}
- virtual void loadThisObject(V4IR::Temp *temp)
+ virtual void loadThisObject(IR::Temp *temp)
{
addDef(temp);
}
- virtual void loadQmlIdArray(V4IR::Temp *temp)
+ virtual void loadQmlIdArray(IR::Temp *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlImportedScripts(V4IR::Temp *temp)
+ virtual void loadQmlImportedScripts(IR::Temp *temp)
{
addDef(temp);
addCall();
@@ -379,21 +382,21 @@ protected: // IRDecoder
addCall();
}
- virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp)
+ virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
{
Q_UNUSED(sourceConst);
addDef(targetTemp);
}
- virtual void loadString(const QString &str, V4IR::Temp *targetTemp)
+ virtual void loadString(const QString &str, IR::Temp *targetTemp)
{
Q_UNUSED(str);
addDef(targetTemp);
}
- virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
{
Q_UNUSED(sourceRegexp);
@@ -401,19 +404,19 @@ protected: // IRDecoder
addCall();
}
- virtual void getActivationProperty(const V4IR::Name *, V4IR::Temp *temp)
+ virtual void getActivationProperty(const IR::Name *, IR::Temp *temp)
{
addDef(temp);
addCall();
}
- virtual void setActivationProperty(V4IR::Expr *source, const QString &)
+ virtual void setActivationProperty(IR::Expr *source, const QString &)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target)
+ virtual void initClosure(IR::Closure *closure, IR::Temp *target)
{
Q_UNUSED(closure);
@@ -421,35 +424,35 @@ protected: // IRDecoder
addCall();
}
- virtual void getProperty(V4IR::Expr *base, const QString &, V4IR::Temp *target)
+ virtual void getProperty(IR::Expr *base, const QString &, IR::Temp *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &)
+ virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
addUses(targetBase->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int /*propertyIndex*/)
+ virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int /*propertyIndex*/)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
addUses(targetBase->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void getQObjectProperty(V4IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, V4IR::Temp *target)
+ virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, IR::Temp *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -457,7 +460,7 @@ protected: // IRDecoder
addCall();
}
- virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex)
+ virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
addUses(targetBase->asTemp(), Use::CouldHaveRegister);
@@ -465,14 +468,14 @@ protected: // IRDecoder
addCall();
}
- virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
+ virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
{
addDef(targetTemp);
addUses(sourceTemp, Use::CouldHaveRegister);
addHint(targetTemp, sourceTemp);
}
- virtual void swapValues(V4IR::Temp *, V4IR::Temp *)
+ virtual void swapValues(IR::Temp *, IR::Temp *)
{
// Inserted by the register allocator, so it cannot occur here.
Q_UNREACHABLE();
@@ -483,7 +486,7 @@ protected: // IRDecoder
addDef(targetTemp);
bool needsCall = true;
- if (oper == OpNot && sourceTemp->type == V4IR::BoolType && targetTemp->type == V4IR::BoolType)
+ if (oper == OpNot && sourceTemp->type == IR::BoolType && targetTemp->type == IR::BoolType)
needsCall = false;
#if 0 // TODO: change masm to generate code
@@ -558,8 +561,8 @@ protected: // IRDecoder
}
}
- virtual void visitJump(V4IR::Jump *) {}
- virtual void visitCJump(V4IR::CJump *s)
+ virtual void visitJump(IR::Jump *) {}
+ virtual void visitCJump(IR::CJump *s)
{
if (Temp *t = s->cond->asTemp()) {
#if 0 // TODO: change masm to generate code
@@ -579,10 +582,10 @@ protected: // IRDecoder
}
}
- virtual void visitRet(V4IR::Ret *s)
+ virtual void visitRet(IR::Ret *s)
{ addUses(s->expr->asTemp(), Use::CouldHaveRegister); }
- virtual void visitPhi(V4IR::Phi *s)
+ virtual void visitPhi(IR::Phi *s)
{
addDef(s->targetTemp, true);
foreach (Expr *e, s->d->incoming) {
@@ -594,7 +597,7 @@ protected: // IRDecoder
}
protected:
- virtual void callBuiltin(V4IR::Call *c, V4IR::Temp *result)
+ virtual void callBuiltin(IR::Call *c, IR::Temp *result)
{
addDef(result);
addUses(c->base->asTemp(), Use::CouldHaveRegister);
@@ -653,26 +656,26 @@ private:
}
};
-} // MASM namespace
-} // MOTH namespace
+} // JIT namespace
+} // QV4 namespace
QT_END_NAMESPACE
QT_USE_NAMESPACE
-using namespace QT_PREPEND_NAMESPACE(QQmlJS::MASM);
-using namespace QT_PREPEND_NAMESPACE(QQmlJS::V4IR);
-using namespace QT_PREPEND_NAMESPACE(QQmlJS);
+using namespace QT_PREPEND_NAMESPACE(QV4::JIT);
+using namespace QT_PREPEND_NAMESPACE(QV4::IR);
+using namespace QT_PREPEND_NAMESPACE(QV4);
namespace {
class ResolutionPhase: protected StmtVisitor, protected ExprVisitor {
const QVector<LifeTimeInterval> &_intervals;
QVector<const LifeTimeInterval *> _unprocessed;
- Function *_function;
+ IR::Function *_function;
#if !defined(QT_NO_DEBUG)
RegAllocInfo *_info;
#endif
- const QHash<V4IR::Temp, int> &_assignedSpillSlots;
- QHash<V4IR::Temp, const LifeTimeInterval *> _intervalForTemp;
+ const QHash<IR::Temp, int> &_assignedSpillSlots;
+ QHash<IR::Temp, const LifeTimeInterval *> _intervalForTemp;
const QVector<int> &_intRegs;
const QVector<int> &_fpRegs;
@@ -684,8 +687,8 @@ class ResolutionPhase: protected StmtVisitor, protected ExprVisitor {
QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtEnd;
public:
- ResolutionPhase(const QVector<LifeTimeInterval> &intervals, Function *function, RegAllocInfo *info,
- const QHash<V4IR::Temp, int> &assignedSpillSlots,
+ ResolutionPhase(const QVector<LifeTimeInterval> &intervals, IR::Function *function, RegAllocInfo *info,
+ const QHash<IR::Temp, int> &assignedSpillSlots,
const QVector<int> &intRegs, const QVector<int> &fpRegs)
: _intervals(intervals)
, _function(function)
@@ -1038,8 +1041,8 @@ protected:
}
virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
@@ -1081,7 +1084,7 @@ RegisterAllocator::~RegisterAllocator()
{
}
-void RegisterAllocator::run(Function *function, const Optimizer &opt)
+void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
{
_activeSpillSlots.resize(function->tempCount);
@@ -1138,7 +1141,7 @@ static inline LifeTimeInterval createFixedInterval(int reg, bool isFP, int range
{
Temp t;
t.init(Temp::PhysicalRegister, reg, 0);
- t.type = isFP ? V4IR::DoubleType : V4IR::SInt32Type;
+ t.type = isFP ? IR::DoubleType : IR::SInt32Type;
LifeTimeInterval i;
i.setTemp(t);
i.setReg(reg);
diff --git a/src/qml/compiler/qv4regalloc_p.h b/src/qml/jit/qv4regalloc_p.h
index 53d09f6252..030fb4bf50 100644
--- a/src/qml/compiler/qv4regalloc_p.h
+++ b/src/qml/jit/qv4regalloc_p.h
@@ -49,25 +49,25 @@
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
-namespace MASM {
+namespace QV4 {
+namespace JIT {
class RegAllocInfo;
class RegisterAllocator
{
- typedef V4IR::LifeTimeInterval LifeTimeInterval;
+ typedef IR::LifeTimeInterval LifeTimeInterval;
- const QVector<int> &_normalRegisters;
- const QVector<int> &_fpRegisters;
+ QVector<int> _normalRegisters;
+ QVector<int> _fpRegisters;
QScopedPointer<RegAllocInfo> _info;
QVector<LifeTimeInterval> _fixedRegisterRanges, _fixedFPRegisterRanges;
QVector<LifeTimeInterval> _unhandled, _active, _inactive, _handled;
- QHash<V4IR::Temp, int> _lastAssignedRegister;
- QHash<V4IR::Temp, int> _assignedSpillSlots;
+ QHash<IR::Temp, int> _lastAssignedRegister;
+ QHash<IR::Temp, int> _assignedSpillSlots;
QVector<int> _activeSpillSlots;
Q_DISABLE_COPY(RegisterAllocator)
@@ -76,7 +76,7 @@ public:
RegisterAllocator(const QVector<int> &normalRegisters, const QVector<int> &fpRegisters);
~RegisterAllocator();
- void run(V4IR::Function *function, const V4IR::Optimizer &opt);
+ void run(IR::Function *function, const IR::Optimizer &opt);
private:
void prepareRanges();
@@ -87,17 +87,17 @@ private:
int lastUse) const;
int nextIntersection(const LifeTimeInterval &current, const LifeTimeInterval &another,
const int position) const;
- int nextUse(const V4IR::Temp &t, int startPosition) const;
+ int nextUse(const IR::Temp &t, int startPosition) const;
void split(LifeTimeInterval &current, int beforePosition, bool skipOptionalRegisterUses =false);
void splitInactiveAtEndOfLifetimeHole(int reg, bool isFPReg, int position);
- void assignSpillSlot(const V4IR::Temp &t, int startPos, int endPos);
- void resolve(V4IR::Function *function, const V4IR::Optimizer &opt);
+ void assignSpillSlot(const IR::Temp &t, int startPos, int endPos);
+ void resolve(IR::Function *function, const IR::Optimizer &opt);
void dump() const;
};
-} // end of namespace MASM
-} // end of namespace QQmlJS
+} // end of namespace JIT
+} // end of namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp
new file mode 100644
index 0000000000..514002adf5
--- /dev/null
+++ b/src/qml/jit/qv4unop.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qv4unop_p.h>
+#include <qv4assembler_p.h>
+
+#if ENABLE(ASSEMBLER)
+
+using namespace QV4;
+using namespace JIT;
+
+#define stringIfyx(s) #s
+#define stringIfy(s) stringIfyx(s)
+#define setOp(operation) \
+ do { call = operation; name = stringIfy(operation); } while (0)
+
+void Unop::generate(IR::Temp *source, IR::Temp *target)
+{
+ UnaryOpName call = 0;
+ const char *name = 0;
+ switch (op) {
+ case IR::OpNot:
+ generateNot(source, target);
+ return;
+ case IR::OpUMinus:
+ generateUMinus(source, target);
+ return;
+ case IR::OpUPlus: setOp(__qmljs_uplus); break;
+ case IR::OpCompl:
+ generateCompl(source, target);
+ return;
+ case IR::OpIncrement: setOp(__qmljs_increment); break;
+ case IR::OpDecrement: setOp(__qmljs_decrement); break;
+ default:
+ Q_UNREACHABLE();
+ } // switch
+
+ if (call) {
+ as->generateFunctionCallImp(target, name, call, Assembler::PointerToValue(source));
+ }
+}
+
+void Unop::generateUMinus(IR::Temp *source, IR::Temp *target)
+{
+ if (source->type == IR::SInt32Type) {
+ Assembler::RegisterID tReg = Assembler::ScratchRegister;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) target->index;
+ Assembler::RegisterID sReg = as->toInt32Register(source, tReg);
+ as->move(sReg, tReg);
+ as->neg32(tReg);
+ if (target->kind != IR::Temp::PhysicalRegister)
+ as->storeInt32(tReg, target);
+ return;
+ }
+
+ as->generateFunctionCallImp(target, "__qmljs_uminus", __qmljs_uminus, Assembler::PointerToValue(source));
+}
+
+void Unop::generateNot(IR::Temp *source, IR::Temp *target)
+{
+ if (source->type == IR::BoolType) {
+ Assembler::RegisterID tReg = Assembler::ScratchRegister;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) target->index;
+ as->xor32(Assembler::TrustedImm32(0x1), as->toInt32Register(source, tReg), tReg);
+ if (target->kind != IR::Temp::PhysicalRegister)
+ as->storeBool(tReg, target);
+ return;
+ } else if (source->type == IR::SInt32Type) {
+ Assembler::RegisterID tReg = Assembler::ScratchRegister;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) target->index;
+ as->compare32(Assembler::Equal,
+ as->toInt32Register(source, Assembler::ScratchRegister), Assembler::TrustedImm32(0),
+ tReg);
+ if (target->kind != IR::Temp::PhysicalRegister)
+ as->storeBool(tReg, target);
+ return;
+ } else if (source->type == IR::DoubleType) {
+ // ###
+ }
+ // ## generic implementation testing for int/bool
+
+ as->generateFunctionCallImp(target, "__qmljs_not", __qmljs_not, Assembler::PointerToValue(source));
+}
+
+void Unop::generateCompl(IR::Temp *source, IR::Temp *target)
+{
+ if (source->type == IR::SInt32Type) {
+ Assembler::RegisterID tReg = Assembler::ScratchRegister;
+ if (target->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) target->index;
+ as->xor32(Assembler::TrustedImm32(0xffffffff), as->toInt32Register(source, tReg), tReg);
+ if (target->kind != IR::Temp::PhysicalRegister)
+ as->storeInt32(tReg, target);
+ return;
+ }
+ as->generateFunctionCallImp(target, "__qmljs_compl", __qmljs_compl, Assembler::PointerToValue(source));
+}
+
+#endif
diff --git a/src/imports/dialogs/qquickdialogassets_p.h b/src/qml/jit/qv4unop_p.h
index 406b68a66d..a8c62182ad 100644
--- a/src/imports/dialogs/qquickdialogassets_p.h
+++ b/src/qml/jit/qv4unop_p.h
@@ -38,28 +38,42 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#ifndef QV4UNOP_P_H
+#define QV4UNOP_P_H
-#ifndef QQUICKDIALOGASSETS_P_H
-#define QQUICKDIALOGASSETS_P_H
-
-#include <private/qtquickglobal_p.h>
-#include <QtGui/qpa/qplatformdialoghelper.h>
-#include "qquickabstractmessagedialog_p.h"
+#include <qv4jsir_p.h>
+#include <qv4isel_masm_p.h>
QT_BEGIN_NAMESPACE
-class QQuickStandardButton
-{
- Q_GADGET
- Q_ENUMS(QQuickAbstractMessageDialog::StandardButton)
-};
+#if ENABLE(ASSEMBLER)
+
+namespace QV4 {
+namespace JIT {
+
+class Assembler;
+
+struct Unop {
+ Unop(Assembler *assembler, IR::AluOp operation)
+ : as(assembler)
+ , op(operation)
+ {}
-class QQuickStandardIcon
-{
- Q_GADGET
- Q_ENUMS(QQuickAbstractMessageDialog::Icon)
+ void generate(IR::Temp *source, IR::Temp *target);
+
+ void generateUMinus(IR::Temp *source, IR::Temp *target);
+ void generateNot(IR::Temp *source, IR::Temp *target);
+ void generateCompl(IR::Temp *source, IR::Temp *target);
+
+ Assembler *as;
+ IR::AluOp op;
};
+}
+}
+
+#endif
+
QT_END_NAMESPACE
-#endif // QQUICKDIALOGASSETS_P_H
+#endif
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 4cc3796541..38a8e40cb2 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -45,7 +45,7 @@
#include "qjsengine.h"
#include "qjsvalue.h"
#include "qjsvalue_p.h"
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4dateobject_p.h"
@@ -1028,7 +1028,7 @@ bool QJSValue::hasProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->__hasProperty__(s);
+ return o->hasProperty(s);
}
/*!
@@ -1049,7 +1049,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->__getOwnProperty__(s);
+ return o->hasOwnProperty(s);
}
/*!
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index d8da664cc6..41856b1e98 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -55,7 +55,7 @@
#include <qjsvalue.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4string_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index ed011ef691..e3358b29bd 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -109,7 +109,7 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->it.flags = QV4::ObjectIterator::NoFlags;
- it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
+ it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
}
/*!
@@ -150,6 +150,7 @@ bool QJSValueIterator::next()
return false;
d_ptr->currentName = d_ptr->nextName;
d_ptr->currentIndex = d_ptr->nextIndex;
+ d_ptr->currentProperty = d_ptr->nextProperty;
d_ptr->currentAttributes = d_ptr->nextAttributes;
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
@@ -157,7 +158,7 @@ bool QJSValueIterator::next()
return false;
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
+ it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
}
@@ -187,27 +188,19 @@ QString QJSValueIterator::name() const
*/
QJSValue QJSValueIterator::value() const
{
- if (!QJSValuePrivate::get(d_ptr->value)->value.isObject())
- return QJSValue();
-
QV4::ExecutionEngine *engine = d_ptr->iterator.engine();
if (!engine)
return QJSValue();
-
QV4::Scope scope(engine);
- QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- QV4::ScopedObject o(scope, it->it.object);
+ QV4::ScopedObject obj(scope, QJSValuePrivate::get(d_ptr->value)->value);
+ if (!obj)
+ return QJSValue();
QV4::ExecutionContext *ctx = engine->currentContext();
- QV4::ScopedValue v(scope);
- if (!!d_ptr->currentName) {
- QV4::ScopedString n(scope, d_ptr->currentName);
- v = o->get(n);
- } else if (d_ptr->currentIndex != UINT_MAX) {
- v = o->getIndexed(d_ptr->currentIndex);
- } else {
+ if (!d_ptr->currentName && d_ptr->currentIndex == UINT_MAX)
return QJSValue();
- }
+
+ QV4::ScopedValue v(scope, obj->getValue(obj, &d_ptr->currentProperty, d_ptr->currentAttributes));
if (scope.hasException()) {
ctx->catchException();
return QJSValue();
@@ -240,7 +233,7 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
d_ptr->iterator = v4->newForEachIteratorObject(v4->currentContext(), o)->asReturnedValue();
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->it.flags = QV4::ObjectIterator::NoFlags;
- it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
+ it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
return *this;
}
diff --git a/src/qml/jsapi/qjsvalueiterator_p.h b/src/qml/jsapi/qjsvalueiterator_p.h
index b7a9b4a190..882c779c00 100644
--- a/src/qml/jsapi/qjsvalueiterator_p.h
+++ b/src/qml/jsapi/qjsvalueiterator_p.h
@@ -56,11 +56,13 @@ public:
QJSValue value;
QV4::PersistentValue iterator;
+ QV4::Property currentProperty;
QV4::PropertyAttributes currentAttributes;
- QV4::SafeString currentName;
+ QV4::StringValue currentName;
uint currentIndex;
+ QV4::Property nextProperty;
QV4::PropertyAttributes nextAttributes;
- QV4::SafeString nextName;
+ QV4::StringValue nextName;
uint nextIndex;
};
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 94983f51e5..ac26794506 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -6,6 +6,7 @@ SOURCES += \
$$PWD/qv4context.cpp \
$$PWD/qv4runtime.cpp \
$$PWD/qv4value.cpp \
+ $$PWD/qv4persistent.cpp \
$$PWD/qv4debugging.cpp \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
@@ -14,6 +15,7 @@ SOURCES += \
$$PWD/qv4managed.cpp \
$$PWD/qv4internalclass.cpp \
$$PWD/qv4sparsearray.cpp \
+ $$PWD/qv4arraydata.cpp \
$$PWD/qv4arrayobject.cpp \
$$PWD/qv4argumentsobject.cpp \
$$PWD/qv4booleanobject.cpp \
@@ -40,7 +42,8 @@ SOURCES += \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
$$PWD/qv4qmlextensions.cpp \
- $$PWD/qv4vme_moth.cpp
+ $$PWD/qv4vme_moth.cpp \
+ $$PWD/qv4profiling.cpp
HEADERS += \
$$PWD/qv4global_p.h \
@@ -48,8 +51,9 @@ HEADERS += \
$$PWD/qv4context_p.h \
$$PWD/qv4runtime_p.h \
$$PWD/qv4math_p.h \
+ $$PWD/qv4value_inl_p.h \
$$PWD/qv4value_p.h \
- $$PWD/qv4value_def_p.h \
+ $$PWD/qv4persistent_p.h \
$$PWD/qv4debugging_p.h \
$$PWD/qv4lookup_p.h \
$$PWD/qv4identifier_p.h \
@@ -58,6 +62,7 @@ HEADERS += \
$$PWD/qv4managed_p.h \
$$PWD/qv4internalclass_p.h \
$$PWD/qv4sparsearray_p.h \
+ $$PWD/qv4arraydata_p.h \
$$PWD/qv4arrayobject_p.h \
$$PWD/qv4argumentsobject_p.h \
$$PWD/qv4booleanobject_p.h \
@@ -87,7 +92,8 @@ HEADERS += \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
$$PWD/qv4qmlextensions_p.h \
- $$PWD/qv4vme_moth_p.h
+ $$PWD/qv4vme_moth_p.h \
+ $$PWD/qv4profiling_p.h
# Use SSE2 floating point math on 32 bit instead of the default
# 387 to make test results pass on 32 and on 64 bit builds.
diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h
index e51c6dff00..a76c327b04 100644
--- a/src/qml/jsruntime/qv4alloca_p.h
+++ b/src/qml/jsruntime/qv4alloca_p.h
@@ -49,10 +49,8 @@
# ifndef __GNUC__
# define alloca _alloca
# endif
-#else
-#if !defined(__FreeBSD__) && !defined(__DragonFly__)
+#elif !defined(Q_OS_BSD4) || defined(Q_OS_DARWIN)
# include <alloca.h>
#endif
-#endif
#endif
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 629c255b48..5dedd59770 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -44,20 +44,19 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(ArgumentsObject);
+DEFINE_OBJECT_VTABLE(ArgumentsObject);
ArgumentsObject::ArgumentsObject(CallContext *context)
: Object(context->strictMode ? context->engine->strictArgumentsObjectClass : context->engine->argumentsObjectClass)
, context(context)
, fullyCreated(false)
{
- type = Type_ArgumentsObject;
- flags &= ~SimpleArray;
-
ExecutionEngine *v4 = context->engine;
Scope scope(v4);
ScopedObject protectThis(scope, this);
+ setArrayType(ArrayData::Complex);
+
if (context->strictMode) {
Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
@@ -66,20 +65,18 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
memberData[CallerPropertyIndex] = pd;
arrayReserve(context->callData->argc);
- for (int i = 0; i < context->callData->argc; ++i)
- arrayData[i].value = context->callData->args[i];
- arrayDataLen = context->callData->argc;
+ arrayPut(0, context->callData->args, context->callData->argc);
fullyCreated = true;
} else {
+ hasAccessorProperty = 1;
Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
memberData[CalleePropertyIndex].value = context->function->asReturnedValue();
- isNonStrictArgumentsObject = true;
}
Q_ASSERT(LengthPropertyIndex == internalClass->find(context->engine->id_length));
Property *lp = memberData + ArrayObject::LengthPropertyIndex;
lp->value = Primitive::fromInt32(context->realArgumentCount);
- Q_ASSERT(internalClass->vtable == &static_vtbl);
+ Q_ASSERT(internalClass->vtable == staticVTable());
}
void ArgumentsObject::destroy(Managed *that)
@@ -94,19 +91,15 @@ void ArgumentsObject::fullyCreate()
uint numAccessors = qMin((int)context->function->formalParameterCount, context->realArgumentCount);
uint argCount = qMin(context->realArgumentCount, context->callData->argc);
- arrayReserve(argCount);
- ensureArrayAttributes();
+ ArrayData::realloc(this, ArrayData::Sparse, 0, argCount, true);
context->engine->requireArgumentsAccessors(numAccessors);
for (uint i = 0; i < (uint)numAccessors; ++i) {
mappedArguments.append(context->callData->args[i]);
- arrayData[i] = context->engine->argumentsAccessors.at(i);
- arrayAttributes[i] = Attr_Accessor;
- }
- for (uint i = numAccessors; i < argCount; ++i) {
- arrayData[i] = Property::fromValue(context->callData->args[i]);
- arrayAttributes[i] = Attr_Data;
+ arraySet(i, context->engine->argumentsAccessors.at(i), Attr_Accessor);
}
- arrayDataLen = argCount;
+ arrayPut(numAccessors, context->callData->args + numAccessors, argCount - numAccessors);
+ for (uint i = numAccessors; i < argCount; ++i)
+ setArrayAttributes(i, Attr_Data);
fullyCreated = true;
}
@@ -116,27 +109,25 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
fullyCreate();
Scope scope(ctx);
- uint pidx = propertyIndexFromArrayIndex(index);
- Property *pd = arrayData + pidx;
+ Property *pd = arrayData->getProperty(index);
Property map;
PropertyAttributes mapAttrs;
bool isMapped = false;
if (pd && index < (uint)mappedArguments.size())
- isMapped = arrayAttributes && arrayAttributes[pidx].isAccessor() && pd->getter() == context->engine->argumentsAccessors.at(index).getter();
+ isMapped = arrayData->attributes(index).isAccessor() && pd->getter() == context->engine->argumentsAccessors.at(index).getter();
if (isMapped) {
map = *pd;
- mapAttrs = arrayAttributes[pidx];
- arrayAttributes[pidx] = Attr_Data;
+ mapAttrs = arrayData->attributes(index);
+ setArrayAttributes(index, Attr_Data);
+ pd = arrayData->getProperty(index);
pd->value = mappedArguments.at(index);
}
- isNonStrictArgumentsObject = false;
bool strict = ctx->strictMode;
ctx->strictMode = false;
- bool result = Object::__defineOwnProperty__(ctx, index, desc, attrs);
+ bool result = Object::defineOwnProperty2(ctx, index, desc, attrs);
ctx->strictMode = strict;
- isNonStrictArgumentsObject = true;
if (isMapped && attrs.isData()) {
ScopedCallData callData(scope, 1);
@@ -145,8 +136,9 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
map.setter()->call(callData);
if (attrs.isWritable()) {
+ setArrayAttributes(index, mapAttrs);
+ pd = arrayData->getProperty(index);
*pd = map;
- arrayAttributes[pidx] = mapAttrs;
}
}
@@ -206,7 +198,7 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
return Attr_Accessor;
}
-DEFINE_MANAGED_VTABLE(ArgumentsGetterFunction);
+DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
{
@@ -221,7 +213,7 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
return o->context->argument(g->index);
}
-DEFINE_MANAGED_VTABLE(ArgumentsSetterFunction);
+DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
{
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index d306fae92b..b50c4f081d 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -50,12 +50,12 @@ namespace QV4 {
struct ArgumentsGetterFunction: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
uint index;
ArgumentsGetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) {
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static ReturnedValue call(Managed *that, CallData *d);
@@ -63,12 +63,12 @@ struct ArgumentsGetterFunction: FunctionObject
struct ArgumentsSetterFunction: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
uint index;
ArgumentsSetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) {
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static ReturnedValue call(Managed *that, CallData *callData);
@@ -76,13 +76,18 @@ struct ArgumentsSetterFunction: FunctionObject
struct ArgumentsObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(ArgumentsObject)
CallContext *context;
bool fullyCreated;
- QVector<SafeValue> mappedArguments;
+ QVector<Value> mappedArguments;
ArgumentsObject(CallContext *context);
~ArgumentsObject() {}
+ static bool isNonStrictArgumentsObject(Managed *m) {
+ return m->internalClass->vtable->type == Type_ArgumentsObject &&
+ !static_cast<ArgumentsObject *>(m)->context->strictMode;
+ }
enum {
LengthPropertyIndex = 0,
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
new file mode 100644
index 0000000000..44727cba17
--- /dev/null
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -0,0 +1,771 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qv4arraydata_p.h"
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+#include "qv4mm_p.h"
+
+using namespace QV4;
+
+const ArrayVTable SimpleArrayData::static_vtbl =
+{
+ DEFINE_MANAGED_VTABLE_INT(SimpleArrayData),
+ SimpleArrayData::Simple,
+ SimpleArrayData::reallocate,
+ SimpleArrayData::get,
+ SimpleArrayData::put,
+ SimpleArrayData::putArray,
+ SimpleArrayData::del,
+ SimpleArrayData::setAttribute,
+ SimpleArrayData::attribute,
+ SimpleArrayData::push_front,
+ SimpleArrayData::pop_front,
+ SimpleArrayData::truncate,
+ SimpleArrayData::length
+};
+
+const ArrayVTable SparseArrayData::static_vtbl =
+{
+ DEFINE_MANAGED_VTABLE_INT(SparseArrayData),
+ ArrayData::Sparse,
+ SparseArrayData::reallocate,
+ SparseArrayData::get,
+ SparseArrayData::put,
+ SparseArrayData::putArray,
+ SparseArrayData::del,
+ SparseArrayData::setAttribute,
+ SparseArrayData::attribute,
+ SparseArrayData::push_front,
+ SparseArrayData::pop_front,
+ SparseArrayData::truncate,
+ SparseArrayData::length
+};
+
+
+void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes)
+{
+ ArrayData *d = o->arrayData;
+
+ uint oldAlloc = 0;
+ uint toCopy = 0;
+ if (alloc < 8)
+ alloc = 8;
+
+ if (d) {
+ bool hasAttrs = d->attrs;
+ enforceAttributes |= hasAttrs;
+
+ if (!offset && alloc <= d->alloc && newType == d->type && hasAttrs == enforceAttributes)
+ return;
+
+ oldAlloc = d->alloc;
+ if (d->type < Sparse) {
+ offset = qMax(offset, static_cast<SimpleArrayData *>(d)->offset);
+ toCopy = static_cast<SimpleArrayData *>(d)->len;
+ } else {
+ Q_ASSERT(!offset);
+ toCopy = d->alloc;
+ newType = Sparse;
+ }
+ }
+ if (enforceAttributes && newType == Simple)
+ newType = Complex;
+
+ alloc = qMax(alloc, 2*oldAlloc) + offset;
+ size_t size = alloc*sizeof(Value);
+ if (enforceAttributes)
+ size += alloc*sizeof(PropertyAttributes);
+
+ if (newType < Sparse) {
+ size += sizeof(SimpleArrayData);
+ SimpleArrayData *newData = static_cast<SimpleArrayData *>(o->engine()->memoryManager->allocManaged(size));
+ new (newData) SimpleArrayData(o->engine());
+ newData->alloc = alloc - offset;
+ newData->type = newType;
+ newData->data = reinterpret_cast<Value *>(newData + 1) + offset;
+ newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) + offset : 0;
+ newData->offset = offset;
+ newData->len = d ? static_cast<SimpleArrayData *>(d)->len : 0;
+ o->arrayData = newData;
+ } else {
+ size += sizeof(SparseArrayData);
+ SparseArrayData *newData = static_cast<SparseArrayData *>(o->engine()->memoryManager->allocManaged(size));
+ new (newData) SparseArrayData(o->engine());
+ newData->alloc = alloc;
+ newData->type = newType;
+ newData->data = reinterpret_cast<Value *>(newData + 1);
+ newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) : 0;
+ o->arrayData = newData;
+ }
+
+ if (d) {
+ memcpy(o->arrayData->data, d->data, sizeof(Value)*toCopy);
+ if (enforceAttributes) {
+ if (d->attrs)
+ memcpy(o->arrayData->attrs, d->attrs, sizeof(PropertyAttributes)*toCopy);
+ else
+ for (uint i = 0; i < toCopy; ++i)
+ o->arrayData->attrs[i] = Attr_Data;
+ }
+ }
+
+ if (newType != Sparse)
+ return;
+
+ SparseArrayData *newData = static_cast<SparseArrayData *>(o->arrayData);
+ if (d && d->type == Sparse) {
+ SparseArrayData *old = static_cast<SparseArrayData *>(d);
+ newData->sparse = old->sparse;
+ old->sparse = 0;
+ newData->freeList = old->freeList;
+ return;
+ }
+
+ newData->sparse = new SparseArray;
+ uint *lastFree = &newData->freeList;
+ for (uint i = 0; i < toCopy; ++i) {
+ if (!newData->data[i].isEmpty()) {
+ SparseArrayNode *n = newData->sparse->insert(i);
+ n->value = i;
+ } else {
+ *lastFree = i;
+ newData->data[i].tag = Value::Empty_Type;
+ lastFree = &newData->data[i].uint_32;
+ }
+ }
+ for (uint i = toCopy; i < newData->alloc; ++i) {
+ *lastFree = i;
+ newData->data[i].tag = Value::Empty_Type;
+ lastFree = &newData->data[i].uint_32;
+ }
+ *lastFree = newData->alloc;
+
+ // ### Could explicitly free the old data
+}
+
+
+void SimpleArrayData::getHeadRoom(Object *o)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ Q_ASSERT(dd);
+ Q_ASSERT(!dd->offset);
+ uint offset = qMax(dd->len >> 2, (uint)16);
+ realloc(o, Simple, offset, 0, false);
+}
+
+ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
+{
+ realloc(o, Simple, 0, n, enforceAttributes);
+ return o->arrayData;
+}
+
+void ArrayData::ensureAttributes(Object *o)
+{
+ if (o->arrayData && o->arrayData->attrs)
+ return;
+
+ ArrayData::realloc(o, Simple, 0, 0, true);
+}
+
+
+void SimpleArrayData::destroy(Managed *)
+{
+}
+
+void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
+ uint l = dd->len;
+ for (uint i = 0; i < l; ++i)
+ dd->data[i].mark(e);
+}
+
+ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index)
+{
+ const SimpleArrayData *dd = static_cast<const SimpleArrayData *>(d);
+ if (index >= dd->len)
+ return Primitive::emptyValue().asReturnedValue();
+ return dd->data[index].asReturnedValue();
+}
+
+bool SimpleArrayData::put(Object *o, uint index, ValueRef value)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
+ // ### honour attributes
+ dd->data[index] = value;
+ if (index >= dd->len) {
+ if (dd->attrs)
+ dd->attrs[index] = Attr_Data;
+ dd->len = index + 1;
+ }
+ return true;
+}
+
+bool SimpleArrayData::del(Object *o, uint index)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ if (index >= dd->len)
+ return true;
+
+ if (!dd->attrs || dd->attrs[index].isConfigurable()) {
+ dd->data[index] = Primitive::emptyValue();
+ if (dd->attrs)
+ dd->attrs[index] = Attr_Data;
+ return true;
+ }
+ if (dd->data[index].isEmpty())
+ return true;
+ return false;
+}
+
+void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
+{
+ o->arrayData->attrs[index] = attrs;
+}
+
+PropertyAttributes SimpleArrayData::attribute(const ArrayData *d, uint index)
+{
+ return d->attrs[index];
+}
+
+void SimpleArrayData::push_front(Object *o, Value *values, uint n)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ Q_ASSERT(!dd->attrs);
+ for (int i = n - 1; i >= 0; --i) {
+ if (!dd->offset) {
+ getHeadRoom(o);
+ dd = static_cast<SimpleArrayData *>(o->arrayData);
+ }
+
+
+ --dd->offset;
+ --dd->data;
+ ++dd->len;
+ ++dd->alloc;
+ *dd->data = values[i].asReturnedValue();
+ }
+
+}
+
+ReturnedValue SimpleArrayData::pop_front(Object *o)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ Q_ASSERT(!dd->attrs);
+ if (!dd->len)
+ return Encode::undefined();
+
+ ReturnedValue v = dd->data[0].isEmpty() ? Encode::undefined() : dd->data[0].asReturnedValue();
+ ++dd->offset;
+ ++dd->data;
+ --dd->len;
+ --dd->alloc;
+ return v;
+}
+
+uint SimpleArrayData::truncate(Object *o, uint newLen)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ if (dd->len < newLen)
+ return newLen;
+
+ if (dd->attrs) {
+ Value *it = dd->data + dd->len;
+ const Value *begin = dd->data + newLen;
+ while (--it >= begin) {
+ if (!it->isEmpty() && !dd->attrs[it - dd->data].isConfigurable()) {
+ newLen = it - dd->data + 1;
+ break;
+ }
+ *it = Primitive::emptyValue();
+ }
+ }
+ dd->len = newLen;
+ return newLen;
+}
+
+uint SimpleArrayData::length(const ArrayData *d)
+{
+ return static_cast<const SimpleArrayData *>(d)->len;
+}
+
+bool SimpleArrayData::putArray(Object *o, uint index, Value *values, uint n)
+{
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ if (index + n > dd->alloc) {
+ reallocate(o, index + n + 1, false);
+ dd = static_cast<SimpleArrayData *>(o->arrayData);
+ }
+ for (uint i = dd->len; i < index; ++i)
+ dd->data[i] = Primitive::emptyValue();
+ for (uint i = 0; i < n; ++i)
+ dd->data[index + i] = values[i];
+ dd->len = qMax(dd->len, index + n);
+ return true;
+}
+
+void SparseArrayData::free(ArrayData *d, uint idx)
+{
+ Q_ASSERT(d && d->type == ArrayData::Sparse);
+ SparseArrayData *dd = static_cast<SparseArrayData *>(d);
+ Value *v = dd->data + idx;
+ if (dd->attrs && dd->attrs[idx].isAccessor()) {
+ // double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
+ v[1].tag = Value::Empty_Type;
+ v[1].uint_32 = dd->freeList;
+ v[0].tag = Value::Empty_Type;
+ v[0].uint_32 = idx + 1;
+ } else {
+ v->tag = Value::Empty_Type;
+ v->uint_32 = dd->freeList;
+ }
+ dd->freeList = idx;
+ if (dd->attrs)
+ dd->attrs[idx].clear();
+}
+
+
+void SparseArrayData::destroy(Managed *d)
+{
+ SparseArrayData *dd = static_cast<SparseArrayData *>(d);
+ delete dd->sparse;
+}
+
+void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e)
+{
+ SparseArrayData *dd = static_cast<SparseArrayData *>(d);
+ uint l = dd->alloc;
+ for (uint i = 0; i < l; ++i)
+ dd->data[i].mark(e);
+}
+
+ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
+{
+ realloc(o, Sparse, 0, n, enforceAttributes);
+ return o->arrayData;
+}
+
+// double slots are required for accessor properties
+uint SparseArrayData::allocate(Object *o, bool doubleSlot)
+{
+ Q_ASSERT(o->arrayData->type == ArrayData::Sparse);
+ SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData);
+ if (doubleSlot) {
+ uint *last = &dd->freeList;
+ while (1) {
+ if (*last + 1 >= dd->alloc) {
+ reallocate(o, o->arrayData->alloc + 2, true);
+ dd = static_cast<SparseArrayData *>(o->arrayData);
+ last = &dd->freeList;
+ }
+
+ if (dd->data[*last].uint_32 == (*last + 1)) {
+ // found two slots in a row
+ uint idx = *last;
+ *last = dd->data[*last + 1].uint_32;
+ o->arrayData->attrs[idx] = Attr_Accessor;
+ return idx;
+ }
+ last = &dd->data[*last].uint_32;
+ }
+ } else {
+ if (dd->alloc == dd->freeList) {
+ reallocate(o, o->arrayData->alloc + 2, false);
+ dd = static_cast<SparseArrayData *>(o->arrayData);
+ }
+ uint idx = dd->freeList;
+ dd->freeList = dd->data[idx].uint_32;
+ if (dd->attrs)
+ dd->attrs[idx] = Attr_Data;
+ return idx;
+ }
+}
+
+ReturnedValue SparseArrayData::get(const ArrayData *d, uint index)
+{
+ SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse->findNode(index);
+ if (!n)
+ return Primitive::emptyValue().asReturnedValue();
+ return d->data[n->value].asReturnedValue();
+}
+
+bool SparseArrayData::put(Object *o, uint index, ValueRef value)
+{
+ if (value->isEmpty())
+ return true;
+
+ SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index);
+ Q_ASSERT(n->value == UINT_MAX || !o->arrayData->attrs || !o->arrayData->attrs[n->value].isAccessor());
+ if (n->value == UINT_MAX)
+ n->value = allocate(o);
+ o->arrayData->data[n->value] = value;
+ if (o->arrayData->attrs)
+ o->arrayData->attrs[n->value] = Attr_Data;
+ return true;
+}
+
+bool SparseArrayData::del(Object *o, uint index)
+{
+ SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData);
+ SparseArrayNode *n = dd->sparse->findNode(index);
+ if (!n)
+ return true;
+
+ uint pidx = n->value;
+ Q_ASSERT(!dd->data[pidx].isEmpty());
+
+ bool isAccessor = false;
+ if (dd->attrs) {
+ if (!dd->attrs[pidx].isConfigurable())
+ return false;
+
+ isAccessor = dd->attrs[pidx].isAccessor();
+ dd->attrs[pidx] = Attr_Data;
+ }
+
+ if (isAccessor) {
+ // free up both indices
+ dd->data[pidx + 1].tag = Value::Undefined_Type;
+ dd->data[pidx + 1].uint_32 = static_cast<SparseArrayData *>(dd)->freeList;
+ dd->data[pidx].tag = Value::Undefined_Type;
+ dd->data[pidx].uint_32 = pidx + 1;
+ } else {
+ dd->data[pidx].tag = Value::Undefined_Type;
+ dd->data[pidx].uint_32 = static_cast<SparseArrayData *>(dd)->freeList;
+ }
+
+ dd->freeList = pidx;
+ dd->sparse->erase(n);
+ return true;
+}
+
+void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
+{
+ SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData);
+ SparseArrayNode *n = d->sparse->insert(index);
+ if (n->value == UINT_MAX) {
+ n->value = allocate(o, attrs.isAccessor());
+ d = static_cast<SparseArrayData *>(o->arrayData);
+ }
+ else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
+ // need to convert the slot
+ free(d, n->value);
+ n->value = allocate(o, attrs.isAccessor());
+ }
+ o->arrayData->attrs[n->value] = attrs;
+}
+
+PropertyAttributes SparseArrayData::attribute(const ArrayData *d, uint index)
+{
+ SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse->insert(index);
+ if (!n)
+ return PropertyAttributes();
+ return d->attrs[n->value];
+}
+
+void SparseArrayData::push_front(Object *o, Value *values, uint n)
+{
+ Q_ASSERT(!o->arrayData->attrs);
+ for (int i = n - 1; i >= 0; --i) {
+ uint idx = allocate(o);
+ o->arrayData->data[idx] = values[i];
+ static_cast<SparseArrayData *>(o->arrayData)->sparse->push_front(idx);
+ }
+}
+
+ReturnedValue SparseArrayData::pop_front(Object *o)
+{
+ Q_ASSERT(!o->arrayData->attrs);
+ uint idx = static_cast<SparseArrayData *>(o->arrayData)->sparse->pop_front();
+ ReturnedValue v;
+ if (idx != UINT_MAX) {
+ v = o->arrayData->data[idx].asReturnedValue();
+ free(o->arrayData, idx);
+ } else {
+ v = Encode::undefined();
+ }
+ return v;
+}
+
+uint SparseArrayData::truncate(Object *o, uint newLen)
+{
+ SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData);
+ SparseArrayNode *begin = d->sparse->lowerBound(newLen);
+ if (begin != d->sparse->end()) {
+ SparseArrayNode *it = d->sparse->end()->previousNode();
+ while (1) {
+ if (d->attrs) {
+ if (!d->attrs[it->value].isConfigurable()) {
+ newLen = it->key() + 1;
+ break;
+ }
+ }
+ free(d, it->value);
+ bool brk = (it == begin);
+ SparseArrayNode *prev = it->previousNode();
+ static_cast<SparseArrayData *>(d)->sparse->erase(it);
+ if (brk)
+ break;
+ it = prev;
+ }
+ }
+ return newLen;
+}
+
+uint SparseArrayData::length(const ArrayData *d)
+{
+ const SparseArrayData *dd = static_cast<const SparseArrayData *>(d);
+ if (!dd->sparse)
+ return 0;
+ SparseArrayNode *n = dd->sparse->end();
+ n = n->previousNode();
+ return n ? n->key() + 1 : 0;
+}
+
+bool SparseArrayData::putArray(Object *o, uint index, Value *values, uint n)
+{
+ for (uint i = 0; i < n; ++i)
+ put(o, index + i, values[i]);
+ return true;
+}
+
+
+uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n)
+{
+ Q_ASSERT(!obj->arrayData->hasAttributes());
+
+ if (!n)
+ return obj->getLength();
+
+ const ArrayData *other = otherObj->arrayData;
+
+ if (other->isSparse())
+ obj->initSparseArray();
+
+ uint oldSize = obj->getLength();
+
+ if (other->isSparse()) {
+ if (otherObj->hasAccessorProperty && other->hasAttributes()) {
+ Scope scope(obj->engine());
+ ScopedValue v(scope);
+ for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse->begin();
+ it != static_cast<const SparseArrayData *>(other)->sparse->end(); it = it->nextNode()) {
+ v = otherObj->getValue(reinterpret_cast<Property *>(other->data + it->value), other->attrs[it->value]);
+ obj->arraySet(oldSize + it->key(), v);
+ }
+ } else {
+ for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse->begin();
+ it != static_cast<const SparseArrayData *>(other)->sparse->end(); it = it->nextNode())
+ obj->arraySet(oldSize + it->key(), other->data[it->value]);
+ }
+ } else {
+ obj->arrayPut(oldSize, other->data, n);
+ }
+
+ return oldSize + n;
+}
+
+Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
+{
+ if (!isAccessor && o->arrayData->type != ArrayData::Sparse) {
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(o->arrayData);
+ if (index < 0x1000 || index < d->len + (d->len >> 2)) {
+ if (index >= o->arrayData->alloc) {
+ o->arrayReserve(index + 1);
+ d = static_cast<SimpleArrayData *>(o->arrayData);
+ }
+ if (index >= d->len) {
+ // mark possible hole in the array
+ for (uint i = d->len; i < index; ++i)
+ d->data[i] = Primitive::emptyValue();
+ d->len = index + 1;
+ }
+ return reinterpret_cast<Property *>(o->arrayData->data + index);
+ }
+ }
+
+ o->initSparseArray();
+ SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index);
+ if (n->value == UINT_MAX)
+ n->value = SparseArrayData::allocate(o, isAccessor);
+ return reinterpret_cast<Property *>(o->arrayData->data + n->value);
+}
+
+
+class ArrayElementLessThan
+{
+public:
+ inline ArrayElementLessThan(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn)
+ : m_context(context), thisObject(thisObject), m_comparefn(comparefn) {}
+
+ bool operator()(const Value &v1, const Value &v2) const;
+
+private:
+ ExecutionContext *m_context;
+ ObjectRef thisObject;
+ const ValueRef m_comparefn;
+};
+
+
+bool ArrayElementLessThan::operator()(const Value &v1, const Value &v2) const
+{
+ Scope scope(m_context);
+
+ if (v1.isUndefined() || v1.isEmpty())
+ return false;
+ if (v2.isUndefined() || v2.isEmpty())
+ return true;
+ ScopedObject o(scope, m_comparefn);
+ if (o) {
+ Scope scope(o->engine());
+ ScopedValue result(scope);
+ ScopedCallData callData(scope, 2);
+ callData->thisObject = Primitive::undefinedValue();
+ callData->args[0] = v1;
+ callData->args[1] = v2;
+ result = __qmljs_call_value(m_context, m_comparefn, callData);
+
+ return result->toNumber() < 0;
+ }
+ ScopedString p1s(scope, v1.toString(m_context));
+ ScopedString p2s(scope, v2.toString(m_context));
+ return p1s->toQString() < p2s->toQString();
+}
+
+void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint len)
+{
+ if (!len)
+ return;
+
+ if (!thisObject->arrayData->length())
+ return;
+
+ if (!(comparefn->isUndefined() || comparefn->asObject())) {
+ context->throwTypeError();
+ return;
+ }
+
+ // The spec says the sorting goes through a series of get,put and delete operations.
+ // this implies that the attributes don't get sorted around.
+
+ if (thisObject->arrayData->type == ArrayData::Sparse) {
+ // since we sort anyway, we can simply iterate over the entries in the sparse
+ // array and append them one by one to a regular one.
+ SparseArrayData *sparse = static_cast<SparseArrayData *>(thisObject->arrayData);
+
+ if (!sparse->sparse->nEntries())
+ return;
+
+ thisObject->arrayData = 0;
+ ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse->nEntries(), sparse->attrs ? true : false);
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData);
+
+ SparseArrayNode *n = sparse->sparse->begin();
+ uint i = 0;
+ if (sparse->attrs) {
+ while (n != sparse->sparse->end()) {
+ if (n->value >= len)
+ break;
+
+ PropertyAttributes a = sparse->attrs ? sparse->attrs[n->value] : Attr_Data;
+ d->data[i] = thisObject->getValue(reinterpret_cast<Property *>(sparse->data + n->value), a);
+ d->attrs[i] = a.isAccessor() ? Attr_Data : a;
+
+ n = n->nextNode();
+ ++i;
+ }
+ } else {
+ while (n != sparse->sparse->end()) {
+ if (n->value >= len)
+ break;
+ d->data[i] = sparse->data[n->value];
+ n = n->nextNode();
+ ++i;
+ }
+ }
+ d->len = i;
+ if (len > i)
+ len = i;
+ if (n != sparse->sparse->end()) {
+ // have some entries outside the sort range that we need to ignore when sorting
+ thisObject->initSparseArray();
+ while (n != sparse->sparse->end()) {
+ PropertyAttributes a = sparse->attrs ? sparse->attrs[n->value] : Attr_Data;
+ thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->data + n->value), a);
+
+ n = n->nextNode();
+ }
+
+ }
+ // ### explicitly delete sparse
+ } else {
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData);
+ if (len > d->len)
+ len = d->len;
+
+ // sort empty values to the end
+ for (uint i = 0; i < len; i++) {
+ if (thisObject->arrayData->data[i].isEmpty()) {
+ while (--len > i)
+ if (!thisObject->arrayData->data[len].isEmpty())
+ break;
+ Q_ASSERT(!thisObject->arrayData->attrs || !thisObject->arrayData->attrs[len].isAccessor());
+ thisObject->arrayData->data[i] = thisObject->arrayData->data[len];
+ thisObject->arrayData->data[len] = Primitive::emptyValue();
+ }
+ }
+
+ if (!len)
+ return;
+ }
+
+
+ ArrayElementLessThan lessThan(context, thisObject, comparefn);
+
+ Value *begin = thisObject->arrayData->data;
+ std::sort(begin, begin + len, lessThan);
+
+#ifdef CHECK_SPARSE_ARRAYS
+ thisObject->initSparseArray();
+#endif
+
+}
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
new file mode 100644
index 0000000000..f127c75fb0
--- /dev/null
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4ARRAYDATA_H
+#define QV4ARRAYDATA_H
+
+#include "qv4global_p.h"
+#include "qv4managed_p.h"
+#include "qv4property_p.h"
+#include "qv4sparsearray_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+#define V4_ARRAYDATA \
+ public: \
+ Q_MANAGED_CHECK \
+ static const QV4::ArrayVTable static_vtbl; \
+ static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ template <typename T> \
+ QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+
+struct ArrayData;
+
+struct ArrayVTable
+{
+ ManagedVTable managedVTable;
+ uint type;
+ ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
+ ReturnedValue (*get)(const ArrayData *d, uint index);
+ bool (*put)(Object *o, uint index, ValueRef value);
+ bool (*putArray)(Object *o, uint index, Value *values, uint n);
+ bool (*del)(Object *o, uint index);
+ void (*setAttribute)(Object *o, uint index, PropertyAttributes attrs);
+ PropertyAttributes (*attribute)(const ArrayData *d, uint index);
+ void (*push_front)(Object *o, Value *values, uint n);
+ ReturnedValue (*pop_front)(Object *o);
+ uint (*truncate)(Object *o, uint newLen);
+ uint (*length)(const ArrayData *d);
+};
+
+
+struct Q_QML_EXPORT ArrayData : public Managed
+{
+ ArrayData(InternalClass *ic)
+ : Managed(ic)
+ {
+ }
+
+ enum Type {
+ Simple = 0,
+ Complex = 1,
+ Sparse = 2,
+ Custom = 3
+ };
+
+ uint alloc;
+ Type type;
+ PropertyAttributes *attrs;
+ Value *data;
+
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); }
+ bool isSparse() const { return this && type == Sparse; }
+
+ uint length() const {
+ if (!this)
+ return 0;
+ return vtable()->length(this);
+ }
+
+ bool hasAttributes() const {
+ return this && attrs;
+ }
+ PropertyAttributes attributes(int i) const {
+ Q_ASSERT(this);
+ return attrs ? vtable()->attribute(this, i) : Attr_Data;
+ }
+
+ bool isEmpty(uint i) const {
+ if (!this)
+ return true;
+ return (vtable()->get(this, i) == Primitive::emptyValue().asReturnedValue());
+ }
+
+ ReturnedValue get(uint i) const {
+ if (!this)
+ return Primitive::emptyValue().asReturnedValue();
+ return vtable()->get(this, i);
+ }
+ inline Property *getProperty(uint index) const;
+
+ static void ensureAttributes(Object *o);
+ static void realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes);
+
+ static void sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint dataLen);
+ static uint append(Object *obj, const ArrayObject *otherObj, uint n);
+ static Property *insert(Object *o, uint index, bool isAccessor = false);
+};
+
+struct Q_QML_EXPORT SimpleArrayData : public ArrayData
+{
+ V4_ARRAYDATA
+
+ SimpleArrayData(ExecutionEngine *engine)
+ : ArrayData(engine->emptyClass)
+ { setVTable(staticVTable()); }
+
+ uint len;
+ uint offset;
+
+ static void getHeadRoom(Object *o);
+ static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
+
+ static void destroy(Managed *d);
+ static void markObjects(Managed *d, ExecutionEngine *e);
+
+ static ReturnedValue get(const ArrayData *d, uint index);
+ static bool put(Object *o, uint index, ValueRef value);
+ static bool putArray(Object *o, uint index, Value *values, uint n);
+ static bool del(Object *o, uint index);
+ static void setAttribute(Object *o, uint index, PropertyAttributes attrs);
+ static PropertyAttributes attribute(const ArrayData *d, uint index);
+ static void push_front(Object *o, Value *values, uint n);
+ static ReturnedValue pop_front(Object *o);
+ static uint truncate(Object *o, uint newLen);
+ static uint length(const ArrayData *d);
+};
+
+struct Q_QML_EXPORT SparseArrayData : public ArrayData
+{
+ V4_ARRAYDATA
+
+ SparseArrayData(ExecutionEngine *engine)
+ : ArrayData(engine->emptyClass)
+ { setVTable(staticVTable()); }
+
+ uint freeList;
+ SparseArray *sparse;
+
+ static uint allocate(Object *o, bool doubleSlot = false);
+ static void free(ArrayData *d, uint idx);
+
+ static void destroy(Managed *d);
+ static void markObjects(Managed *d, ExecutionEngine *e);
+
+ static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
+ static ReturnedValue get(const ArrayData *d, uint index);
+ static bool put(Object *o, uint index, ValueRef value);
+ static bool putArray(Object *o, uint index, Value *values, uint n);
+ static bool del(Object *o, uint index);
+ static void setAttribute(Object *o, uint index, PropertyAttributes attrs);
+ static PropertyAttributes attribute(const ArrayData *d, uint index);
+ static void push_front(Object *o, Value *values, uint n);
+ static ReturnedValue pop_front(Object *o);
+ static uint truncate(Object *o, uint newLen);
+ static uint length(const ArrayData *d);
+};
+
+
+inline Property *ArrayData::getProperty(uint index) const
+{
+ if (!this)
+ return 0;
+ if (type != Sparse) {
+ const SimpleArrayData *that = static_cast<const SimpleArrayData *>(this);
+ if (index >= that->len || data[index].isEmpty())
+ return 0;
+ return reinterpret_cast<Property *>(data + index);
+ } else {
+ SparseArrayNode *n = static_cast<const SparseArrayData *>(this)->sparse->findNode(index);
+ if (!n)
+ return 0;
+ return reinterpret_cast<Property *>(data + n->value);
+ }
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index d4829e587e..efe1dff19c 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -46,12 +46,12 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(ArrayCtor);
+DEFINE_OBJECT_VTABLE(ArrayCtor);
ArrayCtor::ArrayCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Array"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
@@ -72,9 +72,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
} else {
len = callData->argc;
a->arrayReserve(len);
- for (unsigned int i = 0; i < len; ++i)
- a->arrayData[i].value = callData->args[i];
- a->arrayDataLen = len;
+ a->arrayPut(0, callData->args, len);
}
a->setArrayLengthUnchecked(len);
@@ -122,15 +120,6 @@ void ArrayPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1);
}
-uint ArrayPrototype::getLength(ExecutionContext *ctx, ObjectRef o)
-{
- if (o->isArrayObject())
- return o->arrayLength();
- Scope scope(ctx);
- ScopedValue v(scope, o->get(ctx->engine->id_length));
- return v->toUInt32();
-}
-
ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
{
bool isArray = ctx->callData->argc && ctx->callData->args[0].asArrayObject();
@@ -180,15 +169,17 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
eltAsObj = ctx->callData->args[i];
elt = ctx->callData->args[i];
if (elt) {
- result->arrayConcat(elt.getPointer());
+ uint n = elt->getLength();
+ uint newLen = ArrayData::append(result.getPointer(), elt.getPointer(), n);
+ result->setArrayLengthUnchecked(newLen);
} else if (eltAsObj && eltAsObj->isListType()) {
- const uint startIndex = getLength(ctx, result);
- for (int i = 0, len = getLength(ctx, eltAsObj); i < len; ++i) {
+ const uint startIndex = result->getLength();
+ for (int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
entry = eltAsObj->getIndexed(i);
result->putIndexed(startIndex + i, entry);
}
} else {
- result->arraySet(getLength(ctx, result), ctx->callData->args[i]);
+ result->arraySet(result->getLength(), ctx->callData->args[i]);
}
}
@@ -218,7 +209,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
// ### FIXME
if (ArrayObject *a = self->asArrayObject()) {
ScopedValue e(scope);
- for (uint i = 0; i < a->arrayLength(); ++i) {
+ for (uint i = 0; i < a->getLength(); ++i) {
if (i)
R += r4;
@@ -260,7 +251,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
if (!len) {
if (!instance->isArrayObject())
@@ -288,7 +279,10 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+
+ instance->arrayCreate();
+
+ uint len = instance->getLength();
if (len + ctx->callData->argc < len) {
// ughh...
@@ -308,21 +302,11 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
return Encode(newLen);
}
- if (!instance->protoHasArray() && instance->arrayDataLen <= len && (instance->flags & SimpleArray)) {
- for (int i = 0; i < ctx->callData->argc; ++i) {
- if (!instance->sparseArray) {
- if (len >= instance->arrayAlloc)
- instance->arrayReserve(len + 1);
- instance->arrayData[len].value = ctx->callData->args[i];
- if (instance->arrayAttributes)
- instance->arrayAttributes[len] = Attr_Data;
- instance->arrayDataLen = len + 1;
- } else {
- uint j = instance->allocArrayValue(ctx->callData->args[i]);
- instance->sparseArray->push_back(j, len);
- }
- ++len;
- }
+ if (!ctx->callData->argc) {
+ ;
+ } else if (!instance->protoHasArray() && instance->arrayData->length() <= len && instance->arrayType() == ArrayData::Simple) {
+ instance->arrayData->vtable()->putArray(instance.getPointer(), len, ctx->callData->args, ctx->callData->argc);
+ len = instance->arrayData->length();
} else {
for (int i = 0; i < ctx->callData->argc; ++i)
instance->putIndexed(len + i, ctx->callData->args[i]);
@@ -342,7 +326,7 @@ ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint length = getLength(ctx, instance);
+ uint length = instance->getLength();
int lo = 0, hi = length - 1;
@@ -374,7 +358,10 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+
+ instance->arrayCreate();
+
+ uint len = instance->getLength();
if (!len) {
if (!instance->isArrayObject())
@@ -382,28 +369,14 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
return Encode::undefined();
}
- Property *front = 0;
- uint pidx = instance->propertyIndexFromArrayIndex(0);
- if (pidx < UINT_MAX && !instance->arrayData[pidx].value.isEmpty())
- front = instance->arrayData + pidx;
-
- ScopedValue result(scope, front ? instance->getValue(front, instance->arrayAttributes ? instance->arrayAttributes[pidx] : Attr_Data) : Encode::undefined());
+ ScopedValue result(scope);
- if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
- if (!instance->sparseArray) {
- if (instance->arrayDataLen) {
- ++instance->arrayOffset;
- ++instance->arrayData;
- --instance->arrayDataLen;
- --instance->arrayAlloc;
- if (instance->arrayAttributes)
- ++instance->arrayAttributes;
- }
- } else {
- uint idx = instance->sparseArray->pop_front();
- instance->freeArrayValue(idx);
- }
+ if (!instance->protoHasArray() && !instance->arrayData->hasAttributes() && instance->arrayData->length() <= len) {
+ result = instance->arrayData->vtable()->pop_front(instance.getPointer());
} else {
+ result = instance->getIndexed(0);
+ if (scope.hasException())
+ return Encode::undefined();
ScopedValue v(scope);
// do it the slow way
for (uint k = 1; k < len; ++k) {
@@ -415,6 +388,8 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
instance->putIndexed(k - 1, v);
else
instance->deleteIndexedProperty(k - 1);
+ if (scope.hasException())
+ return Encode::undefined();
}
instance->deleteIndexedProperty(len - 1);
if (scope.hasException())
@@ -436,7 +411,7 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
return Encode::undefined();
Scoped<ArrayObject> result(scope, ctx->engine->newArrayObject());
- uint len = getLength(ctx, o);
+ uint len = o->getLength();
double s = ScopedValue(scope, ctx->argument(0))->toInteger();
uint start;
if (s < 0)
@@ -477,10 +452,10 @@ ReturnedValue ArrayPrototype::method_sort(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
ScopedValue comparefn(scope, ctx->argument(0));
- instance->arraySort(ctx, instance, comparefn, len);
+ ArrayData::sort(ctx, instance, comparefn, len);
return ctx->callData->thisObject.asReturnedValue();
}
@@ -490,7 +465,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<ArrayObject> newArray(scope, ctx->engine->newArrayObject());
@@ -504,17 +479,19 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, ctx->argument(1))->toInteger(), 0.), (double)(len - start));
newArray->arrayReserve(deleteCount);
+ ScopedValue v(scope);
for (uint i = 0; i < deleteCount; ++i) {
- newArray->arrayData[i].value = instance->getIndexed(start + i);
+ bool exists;
+ v = instance->getIndexed(start + i, &exists);
if (scope.hasException())
return Encode::undefined();
- newArray->arrayDataLen = i + 1;
+ if (exists)
+ newArray->arrayPut(i, v);
}
newArray->setArrayLengthUnchecked(deleteCount);
uint itemCount = ctx->callData->argc < 2 ? 0 : ctx->callData->argc - 2;
- ScopedValue v(scope);
if (itemCount < deleteCount) {
for (uint k = start; k < len - deleteCount; ++k) {
bool exists;
@@ -568,32 +545,15 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
- ScopedValue v(scope);
- if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
- for (int i = ctx->callData->argc - 1; i >= 0; --i) {
- v = ctx->argument(i);
-
- if (!instance->sparseArray) {
- if (!instance->arrayOffset)
- instance->getArrayHeadRoom();
-
- --instance->arrayOffset;
- --instance->arrayData;
- ++instance->arrayDataLen;
- ++instance->arrayAlloc;
- if (instance->arrayAttributes) {
- --instance->arrayAttributes;
- *instance->arrayAttributes = Attr_Data;
- }
- instance->arrayData->value = v.asReturnedValue();
- } else {
- uint idx = instance->allocArrayValue(v);
- instance->sparseArray->push_front(idx);
- }
- }
+ instance->arrayCreate();
+
+ uint len = instance->getLength();
+
+ if (!instance->protoHasArray() && !instance->arrayData->hasAttributes() && instance->arrayData->length() <= len) {
+ instance->arrayData->vtable()->push_front(instance.getPointer(), ctx->callData->args, ctx->callData->argc);
} else {
+ ScopedValue v(scope);
for (uint k = len; k > 0; --k) {
bool exists;
v = instance->getIndexed(k - 1, &exists);
@@ -622,7 +582,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
if (!len)
return Encode(-1);
@@ -651,7 +611,39 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
return Encode(-1);
}
- return instance->arrayIndexOf(searchValue, fromIndex, len, ctx, instance.getPointer());
+ ScopedValue value(scope);
+
+ if (instance->hasAccessorProperty || (instance->arrayType() >= ArrayData::Sparse) || instance->protoHasArray()) {
+ // lets be safe and slow
+ for (uint i = fromIndex; i < len; ++i) {
+ bool exists;
+ value = instance->getIndexed(i, &exists);
+ if (scope.hasException())
+ return Encode::undefined();
+ if (exists && __qmljs_strict_equal(value, searchValue))
+ return Encode(i);
+ }
+ } else if (!instance->arrayData) {
+ return Encode(-1);
+ } else {
+ Q_ASSERT(instance->arrayType() == ArrayData::Simple || instance->arrayType() == ArrayData::Complex);
+ if (len > instance->arrayData->length())
+ len = instance->arrayData->length();
+ Value *val = instance->arrayData->data;
+ Value *end = val + len;
+ val += fromIndex;
+ while (val < end) {
+ if (!val->isEmpty()) {
+ value = *val;
+ if (scope.hasException())
+ return Encode::undefined();
+ if (__qmljs_strict_equal(value, searchValue))
+ return Encode((uint)(val - instance->arrayData->data));
+ }
+ ++val;
+ }
+ }
+ return Encode(-1);
}
ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
@@ -661,7 +653,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
if (!len)
return Encode(-1);
@@ -707,7 +699,7 @@ ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
@@ -741,7 +733,7 @@ ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
@@ -775,7 +767,7 @@ ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
@@ -806,7 +798,7 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
@@ -843,7 +835,7 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
@@ -884,7 +876,7 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
@@ -934,7 +926,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
if (!instance)
return Encode::undefined();
- uint len = getLength(ctx, instance);
+ uint len = instance->getLength();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 7e809f9064..e7f8ba711f 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -51,7 +51,7 @@ namespace QV4 {
struct ArrayCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
ArrayCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -64,8 +64,6 @@ struct ArrayPrototype: ArrayObject
void init(ExecutionEngine *engine, ObjectRef ctor);
- static uint getLength(ExecutionContext *ctx, ObjectRef o);
-
static ReturnedValue method_isArray(CallContext *ctx);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_toLocaleString(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index f8edfb7850..662ec64efb 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -43,13 +43,13 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(BooleanCtor);
-DEFINE_MANAGED_VTABLE(BooleanObject);
+DEFINE_OBJECT_VTABLE(BooleanCtor);
+DEFINE_OBJECT_VTABLE(BooleanObject);
BooleanCtor::BooleanCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Boolean"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 8d6adc0fb2..617f7f6b01 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -51,7 +51,7 @@ namespace QV4 {
struct BooleanCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
BooleanCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *, CallData *callData);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 8c6d75d1de..cec42e87aa 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -51,27 +51,7 @@
using namespace QV4;
-const ManagedVTable ExecutionContext::static_vtbl =
-{
- call,
- construct,
- markObjects,
- destroy,
- 0 /*collectDeletables*/,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- isEqualTo,
- 0,
- "ExecutionContext",
-};
+DEFINE_MANAGED_VTABLE(ExecutionContext);
CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
{
@@ -91,13 +71,13 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData
c->lookups = c->compilationUnit->runtimeLookups;
}
- c->locals = (SafeValue *)((quintptr(c + 1) + 7) & ~7);
+ c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
if (function->varCount)
std::fill(c->locals, c->locals + function->varCount, Primitive::undefinedValue());
c->callData = reinterpret_cast<CallData *>(c->locals + function->varCount);
- ::memcpy(c->callData, callData, sizeof(CallData) + (callData->argc - 1) * sizeof(SafeValue));
+ ::memcpy(c->callData, callData, sizeof(CallData) + (callData->argc - 1) * sizeof(Value));
if (callData->argc < static_cast<int>(function->formalParameterCount))
std::fill(c->callData->args + c->callData->argc, c->callData->args + function->formalParameterCount, Primitive::undefinedValue());
c->callData->argc = qMax((uint)callData->argc, function->formalParameterCount);
@@ -144,7 +124,7 @@ void ExecutionContext::createMutableBinding(const StringRef name, bool deletable
ctx = ctx->outer;
}
- if (activation->__hasProperty__(name))
+ if (activation->hasProperty(name))
return;
Property desc = Property::fromValue(Primitive::undefinedValue());
PropertyAttributes attrs(Attr_Data);
@@ -234,7 +214,7 @@ CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject
lookups = compilationUnit->runtimeLookups;
}
- locals = (SafeValue *)(this + 1);
+ locals = (Value *)(this + 1);
if (function->varCount)
std::fill(locals, locals + function->varCount, Primitive::undefinedValue());
}
@@ -248,7 +228,7 @@ bool ExecutionContext::deleteProperty(const StringRef name)
if (ctx->type == Type_WithContext) {
hasWith = true;
WithContext *w = static_cast<WithContext *>(ctx);
- if (w->withObject->__hasProperty__(name))
+ if (w->withObject->hasProperty(name))
return w->withObject->deleteProperty(name);
} else if (ctx->type == Type_CatchContext) {
CatchContext *c = static_cast<CatchContext *>(ctx);
@@ -263,11 +243,11 @@ bool ExecutionContext::deleteProperty(const StringRef name)
// ### throw in strict mode?
return false;
}
- if (c->activation && c->activation->__hasProperty__(name))
+ if (c->activation && c->activation->hasProperty(name))
return c->activation->deleteProperty(name);
} else if (ctx->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
- if (g->global->__hasProperty__(name))
+ if (g->global->hasProperty(name))
return g->global->deleteProperty(name);
}
}
@@ -320,7 +300,7 @@ void ExecutionContext::setProperty(const StringRef name, const ValueRef value)
for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) {
if (ctx->type == Type_WithContext) {
ScopedObject w(scope, static_cast<WithContext *>(ctx)->withObject);
- if (w->__hasProperty__(name)) {
+ if (w->hasProperty(name)) {
w->put(name, value);
return;
}
@@ -349,16 +329,9 @@ void ExecutionContext::setProperty(const StringRef name, const ValueRef value)
}
if (activation) {
- if (ctx->type == Type_QmlContext) {
+ if (ctx->type == Type_QmlContext || activation->hasOwnProperty(name)) {
activation->put(name, value);
return;
- } else {
- PropertyAttributes attrs;
- Property *p = activation->__getOwnProperty__(name, &attrs);
- if (p) {
- activation->putValue(p, attrs, value);
- return;
- }
}
}
}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 9f905df15c..f9511d98e3 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -42,7 +42,7 @@
#define QMLJS_ENVIRONMENT_H
#include "qv4global_p.h"
-#include "qv4value_def_p.h"
+#include "qv4scopedvalue_p.h"
#include "qv4managed_p.h"
#include "qv4engine_p.h"
@@ -69,7 +69,11 @@ struct WithContext;
struct Q_QML_EXPORT ExecutionContext : public Managed
{
- Q_MANAGED
+ V4_MANAGED
+ Q_MANAGED_TYPE(ExecutionContext)
+ enum {
+ IsExecutionContext = true
+ };
enum ContextType {
Type_GlobalContext = 0x1,
@@ -170,13 +174,17 @@ struct CallContext : public ExecutionContext
FunctionObject *function;
int realArgumentCount;
- SafeValue *locals;
+ Value *locals;
Object *activation;
inline ReturnedValue argument(int i);
bool needsOwnArguments() const;
};
+inline ReturnedValue CallContext::argument(int i) {
+ return i < callData->argc ? callData->args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
+}
+
struct GlobalContext : public ExecutionContext
{
GlobalContext(ExecutionEngine *engine);
@@ -188,8 +196,8 @@ struct CatchContext : public ExecutionContext
{
CatchContext(ExecutionEngine *engine, const StringRef exceptionVarName, const ValueRef exceptionValue);
- SafeString exceptionVarName;
- SafeValue exceptionValue;
+ StringValue exceptionVarName;
+ Value exceptionValue;
};
struct WithContext : public ExecutionContext
@@ -239,6 +247,15 @@ struct ExecutionContextSaver
}
};
+inline Scope::Scope(ExecutionContext *ctx)
+ : engine(ctx->engine)
+#ifndef QT_NO_DEBUG
+ , size(0)
+#endif
+{
+ mark = engine->jsStackTop;
+}
+
/* Function *f, int argc */
#define requiredMemoryForExecutionContect(f, argc) \
((sizeof(CallContext) + 7) & ~7) + sizeof(Value) * (f->varCount + qMax((uint)argc, f->formalParameterCount)) + sizeof(CallData)
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 5d0c8ccf8e..a9ef29618c 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -641,13 +641,12 @@ static double getLocalTZA()
#endif
}
-DEFINE_MANAGED_VTABLE(DateObject);
+DEFINE_OBJECT_VTABLE(DateObject);
DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date)
: Object(engine->dateClass)
{
- setVTable(&static_vtbl);
- type = Type_DateObject;
+ setVTable(staticVTable());
value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
}
@@ -656,12 +655,12 @@ QDateTime DateObject::toQDateTime() const
return ToDateTime(value.asDouble(), Qt::LocalTime);
}
-DEFINE_MANAGED_VTABLE(DateCtor);
+DEFINE_OBJECT_VTABLE(DateCtor);
DateCtor::DateCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Date"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 9c451dd251..c52e8c3ee1 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -52,10 +52,10 @@ class QDateTime;
namespace QV4 {
struct DateObject: Object {
- Q_MANAGED
- SafeValue value;
+ V4_OBJECT
+ Q_MANAGED_TYPE(DateObject)
+ Value value;
DateObject(ExecutionEngine *engine, const ValueRef date): Object(engine->dateClass) {
- type = Type_DateObject;
value = date;
}
DateObject(ExecutionEngine *engine, const QDateTime &value);
@@ -64,15 +64,14 @@ struct DateObject: Object {
protected:
DateObject(InternalClass *ic): Object(ic) {
- setVTable(&static_vtbl);
- type = Type_DateObject;
+ Q_ASSERT(internalClass->vtable == staticVTable());
value = Primitive::fromDouble(qSNaN());
}
};
struct DateCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
DateCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *, CallData *callData);
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 4170b6817f..dade627206 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -179,7 +179,7 @@ void Debugger::resume(Speed speed)
return;
if (!m_returnedValue.isUndefined())
- m_returnedValue = Primitive::undefinedValue();
+ m_returnedValue = Encode::undefined();
clearTemporaryBreakPoints();
if (speed == StepOver)
@@ -648,15 +648,15 @@ void Debugger::applyPendingBreakPoints()
void Debugger::setBreakOnInstruction(Function *function, qptrdiff codeOffset, bool onoff)
{
uchar *codePtr = const_cast<uchar *>(function->codeData) + codeOffset;
- QQmlJS::Moth::Instr *instruction = reinterpret_cast<QQmlJS::Moth::Instr*>(codePtr);
- instruction->common.breakPoint = onoff;
+ Moth::Instr::instr_debug *debug = reinterpret_cast<Moth::Instr::instr_debug *>(codePtr);
+ debug->breakPoint = onoff;
}
bool Debugger::hasBreakOnInstruction(Function *function, qptrdiff codeOffset)
{
uchar *codePtr = const_cast<uchar *>(function->codeData) + codeOffset;
- QQmlJS::Moth::Instr *instruction = reinterpret_cast<QQmlJS::Moth::Instr*>(codePtr);
- return instruction->common.breakPoint;
+ Moth::Instr::instr_debug *debug = reinterpret_cast<Moth::Instr::instr_debug *>(codePtr);
+ return debug->breakPoint;
}
bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index dc5a60b341..885186e86b 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4context_p.h>
-#include <qv4value_p.h>
+#include <qv4value_inl_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
@@ -63,11 +63,14 @@
#include <qv4stringobject_p.h>
#include <qv4identifiertable_p.h>
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4executableallocator_p.h"
#include "qv4sequenceobject_p.h"
#include "qv4qobjectwrapper_p.h"
#include "qv4qmlextensions_p.h"
+#include <QtCore/QTextStream>
+
#ifdef V4_ENABLE_JIT
#include "qv4isel_masm_p.h"
#endif // V4_ENABLE_JIT
@@ -156,14 +159,15 @@ quintptr getStackLimit()
}
-ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
- : memoryManager(new QV4::MemoryManager)
+ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
+ : current(0)
+ , memoryManager(new QV4::MemoryManager)
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
- , current(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, debugger(0)
+ , profiler(0)
, globalObject(0)
, globalCode(0)
, v8Engine(0)
@@ -182,11 +186,11 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
#ifdef V4_ENABLE_JIT
static const bool forceMoth = !qgetenv("QV4_FORCE_INTERPRETER").isEmpty();
if (forceMoth)
- factory = new QQmlJS::Moth::ISelFactory;
+ factory = new Moth::ISelFactory;
else
- factory = new QQmlJS::MASM::ISelFactory;
+ factory = new JIT::ISelFactory;
#else // !V4_ENABLE_JIT
- factory = new QQmlJS::Moth::ISelFactory;
+ factory = new Moth::ISelFactory;
#endif // V4_ENABLE_JIT
}
iselFactory.reset(factory);
@@ -197,11 +201,11 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
// we allow it to grow to 2 times JSStackLimit, as we can overshoot due to garbage collection
// and ScopedValues allocated outside of JIT'ed methods.
*jsStack = WTF::PageAllocation::allocate(2*JSStackLimit, WTF::OSAllocator::JSVMStackPages, true);
- jsStackBase = (SafeValue *)jsStack->base();
+ jsStackBase = (Value *)jsStack->base();
jsStackTop = jsStackBase;
// set up stack limits
- jsStackLimit = jsStackBase + JSStackLimit/sizeof(SafeValue);
+ jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);
cStackLimit = getStackLimit();
Scope scope(this);
@@ -209,9 +213,9 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
identifierTable = new IdentifierTable(this);
emptyClass = new (classPool.allocate(sizeof(InternalClass))) InternalClass(this);
- executionContextClass = emptyClass->changeVTable(&ExecutionContext::static_vtbl);
- stringClass = emptyClass->changeVTable(&String::static_vtbl);
- regExpValueClass = emptyClass->changeVTable(&RegExp::static_vtbl);
+ executionContextClass = InternalClass::create(this, ExecutionContext::staticVTable(), 0);
+ stringClass = InternalClass::create(this, String::staticVTable(), 0);
+ regExpValueClass = InternalClass::create(this, RegExp::staticVTable(), 0);
id_undefined = newIdentifier(QStringLiteral("undefined"));
id_null = newIdentifier(QStringLiteral("null"));
@@ -244,69 +248,69 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
id_toString = newIdentifier(QStringLiteral("toString"));
id_valueOf = newIdentifier(QStringLiteral("valueOf"));
- ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(emptyClass->changeVTable(&ObjectPrototype::static_vtbl));
- objectClass = InternalClass::create(this, &Object::static_vtbl, objectPrototype);
- Q_ASSERT(objectClass->vtable == &Object::static_vtbl);
+ ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(InternalClass::create(this, ObjectPrototype::staticVTable(), 0));
+ objectClass = InternalClass::create(this, Object::staticVTable(), objectPrototype);
+ Q_ASSERT(objectClass->vtable == Object::staticVTable());
- arrayClass = InternalClass::create(this, &ArrayObject::static_vtbl, objectPrototype);
+ arrayClass = InternalClass::create(this, ArrayObject::staticVTable(), objectPrototype);
arrayClass = arrayClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
ArrayPrototype *arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass);
arrayClass = arrayClass->changePrototype(arrayPrototype);
- InternalClass *argsClass = InternalClass::create(this, &ArgumentsObject::static_vtbl, objectPrototype);
+ InternalClass *argsClass = InternalClass::create(this, ArgumentsObject::staticVTable(), objectPrototype);
argsClass = argsClass->addMember(id_length, Attr_NotEnumerable);
argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- Q_ASSERT(argumentsObjectClass->vtable == &ArgumentsObject::static_vtbl);
- Q_ASSERT(strictArgumentsObjectClass->vtable == &ArgumentsObject::static_vtbl);
+ Q_ASSERT(argumentsObjectClass->vtable == ArgumentsObject::staticVTable());
+ Q_ASSERT(strictArgumentsObjectClass->vtable == ArgumentsObject::staticVTable());
initRootContext();
- StringPrototype *stringPrototype = new (memoryManager) StringPrototype(objectClass);
- stringObjectClass = InternalClass::create(this, &String::static_vtbl, stringPrototype);
+ StringPrototype *stringPrototype = new (memoryManager) StringPrototype(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype));
+ stringObjectClass = InternalClass::create(this, String::staticVTable(), stringPrototype);
- NumberPrototype *numberPrototype = new (memoryManager) NumberPrototype(objectClass);
- numberClass = InternalClass::create(this, &NumberObject::static_vtbl, numberPrototype);
+ NumberPrototype *numberPrototype = new (memoryManager) NumberPrototype(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype));
+ numberClass = InternalClass::create(this, NumberObject::staticVTable(), numberPrototype);
- BooleanPrototype *booleanPrototype = new (memoryManager) BooleanPrototype(objectClass);
- booleanClass = InternalClass::create(this, &BooleanObject::static_vtbl, booleanPrototype);
+ BooleanPrototype *booleanPrototype = new (memoryManager) BooleanPrototype(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype));
+ booleanClass = InternalClass::create(this, BooleanObject::staticVTable(), booleanPrototype);
- DatePrototype *datePrototype = new (memoryManager) DatePrototype(objectClass);
- dateClass = InternalClass::create(this, &DateObject::static_vtbl, datePrototype);
+ DatePrototype *datePrototype = new (memoryManager) DatePrototype(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype));
+ dateClass = InternalClass::create(this, DateObject::staticVTable(), datePrototype);
- FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(InternalClass::create(this, &FunctionPrototype::static_vtbl, objectPrototype));
- functionClass = InternalClass::create(this, &FunctionObject::static_vtbl, functionPrototype);
+ FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(InternalClass::create(this, FunctionPrototype::staticVTable(), objectPrototype));
+ functionClass = InternalClass::create(this, FunctionObject::staticVTable(), functionPrototype);
uint index;
functionWithProtoClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == FunctionObject::Index_Prototype);
protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index);
Q_ASSERT(index == FunctionObject::Index_ProtoConstructor);
- RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(objectClass);
- regExpClass = InternalClass::create(this, &RegExpObject::static_vtbl, regExpPrototype);
+ RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype));
+ regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype);
regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- ErrorPrototype *errorPrototype = new (memoryManager) ErrorPrototype(objectClass);
- errorClass = InternalClass::create(this, &ErrorObject::static_vtbl, errorPrototype);
+ ErrorPrototype *errorPrototype = new (memoryManager) ErrorPrototype(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype));
+ errorClass = InternalClass::create(this, ErrorObject::staticVTable(), errorPrototype);
EvalErrorPrototype *evalErrorPrototype = new (memoryManager) EvalErrorPrototype(errorClass);
- evalErrorClass = InternalClass::create(this, &EvalErrorObject::static_vtbl, evalErrorPrototype);
+ evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable(), evalErrorPrototype);
RangeErrorPrototype *rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(errorClass);
- rangeErrorClass = InternalClass::create(this, &RangeErrorObject::static_vtbl, rangeErrorPrototype);
+ rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable(), rangeErrorPrototype);
ReferenceErrorPrototype *referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(errorClass);
- referenceErrorClass = InternalClass::create(this, &ReferenceErrorObject::static_vtbl, referenceErrorPrototype);
+ referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable(), referenceErrorPrototype);
SyntaxErrorPrototype *syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(errorClass);
- syntaxErrorClass = InternalClass::create(this, &SyntaxErrorObject::static_vtbl, syntaxErrorPrototype);
+ syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable(), syntaxErrorPrototype);
TypeErrorPrototype *typeErrorPrototype = new (memoryManager) TypeErrorPrototype(errorClass);
- typeErrorClass = InternalClass::create(this, &TypeErrorObject::static_vtbl, typeErrorPrototype);
+ typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable(), typeErrorPrototype);
URIErrorPrototype *uRIErrorPrototype = new (memoryManager) URIErrorPrototype(errorClass);
- uriErrorClass = InternalClass::create(this, &URIErrorObject::static_vtbl, uRIErrorPrototype);
+ uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable(), uRIErrorPrototype);
- VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(InternalClass::create(this, &VariantPrototype::static_vtbl, objectPrototype));
- variantClass = InternalClass::create(this, &VariantObject::static_vtbl, variantPrototype);
+ VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype));
+ variantClass = InternalClass::create(this, VariantObject::staticVTable(), variantPrototype);
Q_ASSERT(variantClass->prototype == variantPrototype);
Q_ASSERT(variantPrototype->internalClass->prototype == objectPrototype);
@@ -371,8 +375,8 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
globalObject->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
globalObject->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
ScopedObject o(scope);
- globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = new (memoryManager) MathObject(this)));
- globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = new (memoryManager) JsonObject(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = new (memoryManager) MathObject(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype))));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = new (memoryManager) JsonObject(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype))));
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
@@ -399,6 +403,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
ExecutionEngine::~ExecutionEngine()
{
delete debugger;
+ delete profiler;
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = 0;
delete identifierTable;
@@ -423,7 +428,13 @@ void ExecutionEngine::enableDebugger()
{
Q_ASSERT(!debugger);
debugger = new Debugging::Debugger(this);
- iselFactory.reset(new QQmlJS::Moth::ISelFactory);
+ iselFactory.reset(new Moth::ISelFactory);
+}
+
+void ExecutionEngine::enableProfiler()
+{
+ Q_ASSERT(!profiler);
+ profiler = new QV4::Profiling::Profiler();
}
void ExecutionEngine::initRootContext()
@@ -457,7 +468,7 @@ Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *
return f->asReturned<FunctionObject>();
}
-Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<SafeValue> &boundArgs)
+Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs)
{
Q_ASSERT(target);
@@ -511,6 +522,8 @@ Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
ArrayObject *object = new (memoryManager) ArrayObject(this);
if (count) {
+ Scope scope(this);
+ ScopedValue protectArray(scope, object);
if (count < 0x1000)
object->arrayReserve(count);
object->setArrayLengthUnchecked(count);
@@ -545,12 +558,12 @@ Returned<DateObject> *ExecutionEngine::newDateObject(const QDateTime &dt)
Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
{
- bool global = (flags & QQmlJS::V4IR::RegExp::RegExp_Global);
+ bool global = (flags & IR::RegExp::RegExp_Global);
bool ignoreCase = false;
bool multiline = false;
- if (flags & QQmlJS::V4IR::RegExp::RegExp_IgnoreCase)
+ if (flags & IR::RegExp::RegExp_IgnoreCase)
ignoreCase = true;
- if (flags & QQmlJS::V4IR::RegExp::RegExp_Multiline)
+ if (flags & IR::RegExp::RegExp_Multiline)
multiline = true;
Scope scope(this);
@@ -558,7 +571,7 @@ Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern,
return newRegExpObject(re, global);
}
-Returned<RegExpObject> *ExecutionEngine::newRegExpObject(Referenced<RegExp> re, bool global)
+Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExpRef re, bool global)
{
RegExpObject *object = new (memoryManager) RegExpObject(this, re, global);
return object->asReturned<RegExpObject>();
@@ -729,6 +742,39 @@ StackFrame ExecutionEngine::currentStackFrame() const
return frame;
}
+/* Helper and "C" linkage exported function to format a GDBMI stacktrace for
+ * invocation by a debugger.
+ * Sample GDB invocation: print qt_v4StackTrace((void*)0x7fffffffb290)
+ * Sample CDB invocation: .call Qt5Qmld!qt_v4StackTrace(0x7fffffffb290) ; gh
+ * Note: The helper is there to suppress MSVC warning 4190 about anything
+ * with UDT return types in a "C" linkage function. */
+
+static inline char *v4StackTrace(const ExecutionContext *context)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "stack=[";
+ if (context && context->engine) {
+ const QVector<StackFrame> stackTrace = context->engine->stackTrace(20);
+ for (int i = 0; i < stackTrace.size(); ++i) {
+ if (i)
+ str << ',';
+ const QUrl url(stackTrace.at(i).source);
+ const QString fileName = url.isLocalFile() ? url.toLocalFile() : url.toString();
+ str << "frame={level=\"" << i << "\",func=\"" << stackTrace.at(i).function
+ << "\",file=\"" << fileName << "\",fullname=\"" << fileName
+ << "\",line=\"" << stackTrace.at(i).line << "\",language=\"js\"}";
+ }
+ }
+ str << ']';
+ return qstrdup(result.toLocal8Bit().constData());
+}
+
+extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
+{
+ return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
+}
+
QUrl ExecutionEngine::resolvedUrl(const QString &file)
{
QUrl src(file);
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index ecb5f2b4d5..d8ac750e75 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -61,6 +61,9 @@ namespace QV4 {
namespace Debugging {
class Debugger;
} // namespace Debugging
+namespace Profiling {
+class Profiler;
+} // namespace Profiling
namespace CompiledData {
struct CompilationUnit;
}
@@ -121,11 +124,6 @@ struct ExecutionContextSaver;
struct Q_QML_EXPORT ExecutionEngine
{
- MemoryManager *memoryManager;
- ExecutableAllocator *executableAllocator;
- ExecutableAllocator *regExpAllocator;
- QScopedPointer<QQmlJS::EvalISelFactory> iselFactory;
-
private:
friend struct ExecutionContextSaver;
friend struct ExecutionContext;
@@ -133,20 +131,27 @@ private:
public:
ExecutionContext *currentContext() const { return current; }
+ Value *jsStackTop;
+ quint32 hasException;
GlobalContext *rootContext;
- SafeValue *jsStackTop;
- SafeValue *jsStackLimit;
+ MemoryManager *memoryManager;
+ ExecutableAllocator *executableAllocator;
+ ExecutableAllocator *regExpAllocator;
+ QScopedPointer<EvalISelFactory> iselFactory;
+
+
+ Value *jsStackLimit;
quintptr cStackLimit;
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
enum { JSStackLimit = 4*1024*1024 };
WTF::PageAllocation *jsStack;
- SafeValue *jsStackBase;
+ Value *jsStackBase;
- SafeValue *stackPush(uint nValues) {
- SafeValue *ptr = jsStackTop;
+ Value *stackPush(uint nValues) {
+ Value *ptr = jsStackTop;
jsStackTop = ptr + nValues;
return ptr;
}
@@ -167,6 +172,7 @@ public:
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
+ QV4::Profiling::Profiler *profiler;
Object *globalObject;
@@ -174,22 +180,22 @@ public:
QV8Engine *v8Engine;
- SafeValue objectCtor;
- SafeValue stringCtor;
- SafeValue numberCtor;
- SafeValue booleanCtor;
- SafeValue arrayCtor;
- SafeValue functionCtor;
- SafeValue dateCtor;
- SafeValue regExpCtor;
- SafeValue errorCtor;
- SafeValue evalErrorCtor;
- SafeValue rangeErrorCtor;
- SafeValue referenceErrorCtor;
- SafeValue syntaxErrorCtor;
- SafeValue typeErrorCtor;
- SafeValue uRIErrorCtor;
- SafeValue sequencePrototype;
+ Value objectCtor;
+ Value stringCtor;
+ Value numberCtor;
+ Value booleanCtor;
+ Value arrayCtor;
+ Value functionCtor;
+ Value dateCtor;
+ Value regExpCtor;
+ Value errorCtor;
+ Value evalErrorCtor;
+ Value rangeErrorCtor;
+ Value referenceErrorCtor;
+ Value syntaxErrorCtor;
+ Value typeErrorCtor;
+ Value uRIErrorCtor;
+ Value sequencePrototype;
QQmlJS::MemoryPool classPool;
InternalClass *emptyClass;
@@ -228,36 +234,36 @@ public:
QVector<Property> argumentsAccessors;
- SafeString id_undefined;
- SafeString id_null;
- SafeString id_true;
- SafeString id_false;
- SafeString id_boolean;
- SafeString id_number;
- SafeString id_string;
- SafeString id_object;
- SafeString id_function;
- SafeString id_length;
- SafeString id_prototype;
- SafeString id_constructor;
- SafeString id_arguments;
- SafeString id_caller;
- SafeString id_callee;
- SafeString id_this;
- SafeString id___proto__;
- SafeString id_enumerable;
- SafeString id_configurable;
- SafeString id_writable;
- SafeString id_value;
- SafeString id_get;
- SafeString id_set;
- SafeString id_eval;
- SafeString id_uintMax;
- SafeString id_name;
- SafeString id_index;
- SafeString id_input;
- SafeString id_toString;
- SafeString id_valueOf;
+ StringValue id_undefined;
+ StringValue id_null;
+ StringValue id_true;
+ StringValue id_false;
+ StringValue id_boolean;
+ StringValue id_number;
+ StringValue id_string;
+ StringValue id_object;
+ StringValue id_function;
+ StringValue id_length;
+ StringValue id_prototype;
+ StringValue id_constructor;
+ StringValue id_arguments;
+ StringValue id_caller;
+ StringValue id_callee;
+ StringValue id_this;
+ StringValue id___proto__;
+ StringValue id_enumerable;
+ StringValue id_configurable;
+ StringValue id_writable;
+ StringValue id_value;
+ StringValue id_get;
+ StringValue id_set;
+ StringValue id_eval;
+ StringValue id_uintMax;
+ StringValue id_name;
+ StringValue id_index;
+ StringValue id_input;
+ StringValue id_toString;
+ StringValue id_valueOf;
QSet<CompiledData::CompilationUnit*> compilationUnits;
QMap<quintptr, QV4::Function*> allFunctions;
@@ -285,17 +291,18 @@ public:
// bookkeeping.
MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
- ExecutionEngine(QQmlJS::EvalISelFactory *iselFactory = 0);
+ ExecutionEngine(EvalISelFactory *iselFactory = 0);
~ExecutionEngine();
void enableDebugger();
+ void enableProfiler();
ExecutionContext *pushGlobalContext();
void pushContext(CallContext *context);
ExecutionContext *popContext();
Returned<FunctionObject> *newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *));
- Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<SafeValue> &boundArgs);
+ Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs);
Returned<Object> *newObject();
Returned<Object> *newObject(InternalClass *internalClass);
@@ -315,7 +322,7 @@ public:
Returned<DateObject> *newDateObject(const QDateTime &dt);
Returned<RegExpObject> *newRegExpObject(const QString &pattern, int flags);
- Returned<RegExpObject> *newRegExpObject(Referenced<RegExp> re, bool global);
+ Returned<RegExpObject> *newRegExpObject(RegExpRef re, bool global);
Returned<RegExpObject> *newRegExpObject(const QRegExp &re);
Returned<Object> *newErrorObject(const ValueRef value);
@@ -352,8 +359,7 @@ public:
bool recheckCStackLimits();
// Exception handling
- SafeValue exceptionValue;
- quint32 hasException;
+ Value exceptionValue;
StackTrace exceptionStackTrace;
ReturnedValue throwException(const ValueRef value);
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index cf5c06dd41..29615e8ec2 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -76,8 +76,6 @@ ErrorObject::ErrorObject(InternalClass *ic)
: Object(ic)
, stack(0)
{
- type = Type_ErrorObject;
-
Scope scope(engine());
ScopedValue protectThis(scope, this);
@@ -89,7 +87,6 @@ ErrorObject::ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t)
: Object(ic)
, stack(0)
{
- type = Type_ErrorObject;
subtype = t;
Scope scope(engine());
@@ -113,7 +110,6 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, ErrorObject:
: Object(ic)
, stack(0)
{
- type = Type_ErrorObject;
subtype = t;
Scope scope(engine());
@@ -137,7 +133,6 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QStrin
: Object(ic)
, stack(0)
{
- type = Type_ErrorObject;
subtype = t;
Scope scope(engine());
@@ -196,9 +191,9 @@ void ErrorObject::markObjects(Managed *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-DEFINE_MANAGED_VTABLE(ErrorObject);
+DEFINE_OBJECT_VTABLE(ErrorObject);
-DEFINE_MANAGED_VTABLE(SyntaxErrorObject);
+DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg)
: ErrorObject(engine->syntaxErrorClass, msg, SyntaxError)
@@ -255,24 +250,24 @@ URIErrorObject::URIErrorObject(ExecutionEngine *engine, const ValueRef message)
{
}
-DEFINE_MANAGED_VTABLE(ErrorCtor);
-DEFINE_MANAGED_VTABLE(EvalErrorCtor);
-DEFINE_MANAGED_VTABLE(RangeErrorCtor);
-DEFINE_MANAGED_VTABLE(ReferenceErrorCtor);
-DEFINE_MANAGED_VTABLE(SyntaxErrorCtor);
-DEFINE_MANAGED_VTABLE(TypeErrorCtor);
-DEFINE_MANAGED_VTABLE(URIErrorCtor);
+DEFINE_OBJECT_VTABLE(ErrorCtor);
+DEFINE_OBJECT_VTABLE(EvalErrorCtor);
+DEFINE_OBJECT_VTABLE(RangeErrorCtor);
+DEFINE_OBJECT_VTABLE(ReferenceErrorCtor);
+DEFINE_OBJECT_VTABLE(SyntaxErrorCtor);
+DEFINE_OBJECT_VTABLE(TypeErrorCtor);
+DEFINE_OBJECT_VTABLE(URIErrorCtor);
ErrorCtor::ErrorCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Error"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ErrorCtor::ErrorCtor(ExecutionContext *scope, const QString &name)
: FunctionObject(scope, name)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
@@ -284,13 +279,13 @@ ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
{
- return that->construct(callData);
+ return static_cast<Object *>(that)->construct(callData);
}
EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
: ErrorCtor(scope, QStringLiteral("EvalError"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
@@ -303,7 +298,7 @@ ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
: ErrorCtor(scope, QStringLiteral("RangeError"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
@@ -316,7 +311,7 @@ ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
: ErrorCtor(scope, QStringLiteral("ReferenceError"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
@@ -329,7 +324,7 @@ ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
: ErrorCtor(scope, QStringLiteral("SyntaxError"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
@@ -342,7 +337,7 @@ ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
: ErrorCtor(scope, QStringLiteral("TypeError"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
@@ -355,7 +350,7 @@ ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
: ErrorCtor(scope, QStringLiteral("URIError"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index def776d3b6..c44cc5cdb2 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -51,7 +51,11 @@ namespace QV4 {
struct SyntaxErrorObject;
struct ErrorObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(ErrorObject)
+ enum {
+ IsErrorObject = true
+ };
enum ErrorType {
Error,
@@ -99,7 +103,7 @@ struct ReferenceErrorObject: ErrorObject {
};
struct SyntaxErrorObject: ErrorObject {
- Q_MANAGED
+ V4_OBJECT
SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg);
SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
};
@@ -115,7 +119,7 @@ struct URIErrorObject: ErrorObject {
struct ErrorCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
ErrorCtor(ExecutionContext *scope);
ErrorCtor(ExecutionContext *scope, const QString &name);
@@ -125,7 +129,7 @@ struct ErrorCtor: FunctionObject
struct EvalErrorCtor: ErrorCtor
{
- Q_MANAGED
+ V4_OBJECT
EvalErrorCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -133,7 +137,7 @@ struct EvalErrorCtor: ErrorCtor
struct RangeErrorCtor: ErrorCtor
{
- Q_MANAGED
+ V4_OBJECT
RangeErrorCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -141,7 +145,7 @@ struct RangeErrorCtor: ErrorCtor
struct ReferenceErrorCtor: ErrorCtor
{
- Q_MANAGED
+ V4_OBJECT
ReferenceErrorCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -149,7 +153,7 @@ struct ReferenceErrorCtor: ErrorCtor
struct SyntaxErrorCtor: ErrorCtor
{
- Q_MANAGED
+ V4_OBJECT
SyntaxErrorCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -157,7 +161,7 @@ struct SyntaxErrorCtor: ErrorCtor
struct TypeErrorCtor: ErrorCtor
{
- Q_MANAGED
+ V4_OBJECT
TypeErrorCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -165,7 +169,7 @@ struct TypeErrorCtor: ErrorCtor
struct URIErrorCtor: ErrorCtor
{
- Q_MANAGED
+ V4_OBJECT
URIErrorCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
@@ -184,37 +188,37 @@ struct ErrorPrototype: ErrorObject
struct EvalErrorPrototype: ErrorObject
{
- EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
+ EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
};
struct RangeErrorPrototype: ErrorObject
{
- RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
+ RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
};
struct ReferenceErrorPrototype: ErrorObject
{
- ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
+ ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
};
struct SyntaxErrorPrototype: ErrorObject
{
- SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
+ SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
};
struct TypeErrorPrototype: ErrorObject
{
- TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
+ TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
};
struct URIErrorPrototype: ErrorObject
{
- URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
+ URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
};
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 0e90e213c4..811b445f9e 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -42,7 +42,7 @@
#include "qv4function_p.h"
#include "qv4managed_p.h"
#include "qv4string_p.h"
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4engine_p.h"
#include "qv4lookup_p.h"
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 8d07853b45..377b45bfa3 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -47,7 +47,7 @@
#include <QtCore/QByteArray>
#include <QtCore/qurl.h>
-#include "qv4value_def_p.h"
+#include "qv4value_p.h"
#include <private/qv4compileddata_p.h>
#include <private/qv4engine_p.h>
@@ -81,7 +81,7 @@ struct InternalClass;
struct Lookup;
struct Function {
- SafeString name;
+ StringValue name;
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 6c596ff5cf..07ec94a58d 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -67,11 +67,12 @@
#include <iostream>
#include <algorithm>
#include "qv4alloca_p.h"
+#include "qv4profiling_p.h"
using namespace QV4;
-DEFINE_MANAGED_VTABLE(FunctionObject);
+DEFINE_OBJECT_VTABLE(FunctionObject);
FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto)
: Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass)
@@ -112,7 +113,6 @@ FunctionObject::FunctionObject(InternalClass *ic)
{
name = ic->engine->id_undefined;
- type = Type_FunctionObject;
needsActivation = false;
strictMode = false;
}
@@ -130,7 +130,6 @@ void FunctionObject::init(const StringRef n, bool createProto)
Scope s(internalClass->engine);
ScopedValue protectThis(s, this);
- type = Type_FunctionObject;
needsActivation = true;
strictMode = false;
@@ -224,19 +223,19 @@ InternalClass *FunctionObject::internalClassForConstructor()
Scope scope(internalClass->engine);
ScopedObject p(scope, proto);
if (p)
- classForConstructor = InternalClass::create(scope.engine, &Object::static_vtbl, p.getPointer());
+ classForConstructor = InternalClass::create(scope.engine, Object::staticVTable(), p.getPointer());
else
classForConstructor = scope.engine->objectClass;
return classForConstructor;
}
-DEFINE_MANAGED_VTABLE(FunctionCtor);
+DEFINE_OBJECT_VTABLE(FunctionCtor);
FunctionCtor::FunctionCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Function"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
// 15.3.2
@@ -275,13 +274,13 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
if (!fe)
return v4->currentContext()->throwSyntaxError(QLatin1String("Parse error"));
- QQmlJS::V4IR::Module module(v4->debugger != 0);
+ IR::Module module(v4->debugger != 0);
QQmlJS::RuntimeCodegen cg(v4->currentContext(), f->strictMode);
cg.generateFromFunctionExpression(QString(), function, fe, &module);
QV4::Compiler::JSUnitGenerator jsGenerator(&module);
- QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator));
+ QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator));
QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile();
QV4::Function *vmf = compilationUnit->linkToEngine(v4);
@@ -342,19 +341,19 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
if (!arg->isNullOrUndefined())
return ctx->throwTypeError();
} else {
- len = ArrayPrototype::getLength(ctx, arr);
+ len = arr->getLength();
}
ScopedCallData callData(scope, len);
if (len) {
- if (!(arr->flags & SimpleArray) || arr->protoHasArray() || arr->hasAccessorProperty) {
+ if (arr->arrayType() != ArrayData::Simple || arr->protoHasArray() || arr->hasAccessorProperty) {
for (quint32 i = 0; i < len; ++i)
callData->args[i] = arr->getIndexed(i);
} else {
- int alen = qMin(len, arr->arrayDataLen);
- for (int i = 0; i < alen; ++i)
- callData->args[i] = arr->arrayData[i].value;
+ int alen = qMin(len, arr->arrayData->length());
+ if (alen)
+ memcpy(callData->args, arr->arrayData->data, alen*sizeof(Value));
for (quint32 i = alen; i < len; ++i)
callData->args[i] = Primitive::undefinedValue();
}
@@ -389,19 +388,19 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
return ctx->throwTypeError();
ScopedValue boundThis(scope, ctx->argument(0));
- QVector<SafeValue> boundArgs;
+ QVector<Value> boundArgs;
for (int i = 1; i < ctx->callData->argc; ++i)
boundArgs += ctx->callData->args[i];
return ctx->engine->newBoundFunction(ctx->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
}
-DEFINE_MANAGED_VTABLE(ScriptFunction);
+DEFINE_OBJECT_VTABLE(ScriptFunction);
ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
: FunctionObject(scope, function->name, true)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
Scope s(scope);
ScopedValue protectThis(s, this);
@@ -426,8 +425,8 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
if (scope->strictMode) {
Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
- *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
- *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
+ insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
@@ -449,7 +448,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData);
ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, f->function->code(ctx, f->function->codeData));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
@@ -473,7 +472,7 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
CallContext *ctx = context->newCallContext(f, callData);
ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, f->function->code(ctx, f->function->codeData));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(ctx->engine, f->function->compiledFunction);
@@ -481,12 +480,12 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
return result.asReturnedValue();
}
-DEFINE_MANAGED_VTABLE(SimpleScriptFunction);
+DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *function)
: FunctionObject(scope, function->name, true)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
Scope s(scope);
ScopedValue protectThis(s, this);
@@ -511,8 +510,8 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
if (scope->strictMode) {
Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
- *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
- *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
+ insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
@@ -546,7 +545,7 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
}
Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<Object> result(scope, f->function->code(&ctx, f->function->codeData));
+ Scoped<Object> result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
@@ -583,7 +582,7 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
}
Q_ASSERT(v4->currentContext() == &ctx);
- ScopedValue result(scope, f->function->code(&ctx, f->function->codeData));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
@@ -594,13 +593,13 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
-DEFINE_MANAGED_VTABLE(BuiltinFunction);
+DEFINE_OBJECT_VTABLE(BuiltinFunction);
BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *))
: FunctionObject(scope, name)
, code(code)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
@@ -646,16 +645,16 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
return f->code(&ctx, f->index);
}
-DEFINE_MANAGED_VTABLE(IndexedBuiltinFunction);
+DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
-DEFINE_MANAGED_VTABLE(BoundFunction);
+DEFINE_OBJECT_VTABLE(BoundFunction);
-BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<SafeValue> &boundArgs)
+BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs)
: FunctionObject(scope, QStringLiteral("__bound function__"))
, target(target)
, boundArgs(boundArgs)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
subtype = FunctionObject::BoundFunction;
this->boundThis = boundThis;
@@ -672,8 +671,8 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target,
ExecutionEngine *v4 = scope->engine;
Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
- *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
- *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd;
+ insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
void BoundFunction::destroy(Managed *that)
@@ -690,8 +689,8 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
callData->thisObject = f->boundThis;
- memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(SafeValue));
- memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(SafeValue));
+ memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
return f->target->call(callData);
}
@@ -703,8 +702,8 @@ ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
return Encode::undefined();
ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
- memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(SafeValue));
- memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(SafeValue));
+ memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
return f->target->construct(callData);
}
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 96534cb68c..af4ec024d5 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -93,7 +93,11 @@ struct InternalClass;
struct Lookup;
struct Q_QML_EXPORT FunctionObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(FunctionObject)
+ enum {
+ IsFunctionObject = true
+ };
// Used with Managed::subType
enum FunctionType {
RegularFunction = 0,
@@ -107,7 +111,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
ExecutionContext *scope;
- SafeString name;
+ StringValue name;
unsigned int formalParameterCount;
unsigned int varCount;
Function *function;
@@ -124,14 +128,10 @@ struct Q_QML_EXPORT FunctionObject: Object {
ReturnedValue newInstance();
+ using Object::construct;
+ using Object::call;
static ReturnedValue construct(Managed *that, CallData *);
static ReturnedValue call(Managed *that, CallData *d);
- inline ReturnedValue construct(CallData *callData) {
- return internalClass->vtable->construct(this, callData);
- }
- inline ReturnedValue call(CallData *callData) {
- return internalClass->vtable->call(this, callData);
- }
static FunctionObject *cast(const Value &v) {
return v.asFunctionObject();
@@ -155,9 +155,11 @@ inline FunctionObject *value_cast(const Value &v) {
return v.asFunctionObject();
}
+DEFINE_REF(FunctionObject, Object);
+
struct FunctionCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
FunctionCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *that, CallData *callData);
@@ -176,7 +178,7 @@ struct FunctionPrototype: FunctionObject
};
struct BuiltinFunction: FunctionObject {
- Q_MANAGED
+ V4_OBJECT
ReturnedValue (*code)(CallContext *);
BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *));
@@ -187,7 +189,7 @@ struct BuiltinFunction: FunctionObject {
struct IndexedBuiltinFunction: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
ReturnedValue (*code)(CallContext *ctx, uint index);
uint index;
@@ -197,7 +199,7 @@ struct IndexedBuiltinFunction: FunctionObject
, code(code)
, index(index)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static ReturnedValue construct(Managed *m, CallData *)
@@ -210,7 +212,7 @@ struct IndexedBuiltinFunction: FunctionObject
struct ScriptFunction: FunctionObject {
- Q_MANAGED
+ V4_OBJECT
ScriptFunction(ExecutionContext *scope, Function *function);
static ReturnedValue construct(Managed *, CallData *callData);
@@ -218,7 +220,7 @@ struct ScriptFunction: FunctionObject {
};
struct SimpleScriptFunction: FunctionObject {
- Q_MANAGED
+ V4_OBJECT
SimpleScriptFunction(ExecutionContext *scope, Function *function);
static ReturnedValue construct(Managed *, CallData *callData);
@@ -226,12 +228,12 @@ struct SimpleScriptFunction: FunctionObject {
};
struct BoundFunction: FunctionObject {
- Q_MANAGED
+ V4_OBJECT
FunctionObject *target;
- SafeValue boundThis;
- QVector<SafeValue> boundArgs;
+ Value boundThis;
+ QVector<Value> boundArgs;
- BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<SafeValue> &boundArgs);
+ BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs);
~BoundFunction() {}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 1d465df0c0..746513cc2f 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -156,12 +156,16 @@ template<typename T> struct Returned;
typedef Returned<String> ReturnedString;
typedef Returned<Object> ReturnedObject;
typedef Returned<FunctionObject> ReturnedFunctionObject;
-template<typename T> struct Referenced;
-typedef Referenced<Managed> ManagedRef;
-typedef Referenced<String> StringRef;
-typedef Referenced<Object> ObjectRef;
-typedef Referenced<ArrayObject> ArrayObjectRef;
-typedef Referenced<FunctionObject> FunctionObjectRef;
+struct ManagedRef;
+struct StringRef;
+struct ObjectRef;
+struct ArrayObjectRef;
+struct FunctionObjectRef;
+struct RegExpRef;
+
+struct PersistentValuePrivate;
+class PersistentValue;
+class WeakValue;
namespace Global {
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index fa8af8ed5d..76a8b0c25c 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -41,7 +41,7 @@
#include "qv4globalobject_p.h"
#include "qv4mm_p.h"
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4context_p.h"
#include "qv4function_p.h"
#include "qv4debugging_p.h"
@@ -344,12 +344,12 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
return QString();
}
-DEFINE_MANAGED_VTABLE(EvalFunction);
+DEFINE_OBJECT_VTABLE(EvalFunction);
EvalFunction::EvalFunction(ExecutionContext *scope)
: FunctionObject(scope, scope->engine->id_eval)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1));
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index bf529a465d..63823acc19 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -50,12 +50,12 @@ namespace QV4 {
struct Q_QML_EXPORT EvalFunction : FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
EvalFunction(ExecutionContext *scope);
ReturnedValue evalCall(CallData *callData, bool directCall);
- using Managed::construct;
+ using Object::construct;
static ReturnedValue call(Managed *that, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index d0e0e9413b..7642db1e9b 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -131,8 +131,8 @@ void QV4Include::finished()
QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (redirect.isValid()) {
m_url = m_url.resolved(redirect.toUrl());
- delete m_reply;
-
+ delete m_reply;
+
QNetworkRequest request;
request.setUrl(m_url);
@@ -209,7 +209,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
callbackFunction);
result = i->result();
- } else {
+ } else {
QFile f(localFile);
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index c4c72f3a83..d1cadb3aa5 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -58,7 +58,7 @@
#include <private/qqmlcontext_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4context_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index 29ede3d104..761a180722 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -183,6 +183,8 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto)
{
InternalClass *c = engine->emptyClass->changeVTable(vtable);
+ if (!proto)
+ return c;
return c->changePrototype(proto);
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 6633435668..20927ab8e7 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -66,6 +66,8 @@ static int indent = 0;
#endif
+DEFINE_OBJECT_VTABLE(JsonObject);
+
class JsonParser
{
public:
@@ -288,8 +290,7 @@ bool JsonParser::parseMember(ObjectRef o)
if (idx < UINT_MAX) {
o->putIndexed(idx, val);
} else {
- Property *p = o->insertMember(s, Attr_Data);
- p->value = val.asReturnedValue();
+ o->insertMember(s, val);
}
END;
@@ -337,7 +338,7 @@ ReturnedValue JsonParser::parseArray()
}
}
- DEBUG << "size =" << array->arrayLength();
+ DEBUG << "size =" << array->getLength();
END;
--nestingLevel;
@@ -853,7 +854,7 @@ QString Stringify::JA(ArrayObjectRef a)
indent += gap;
QStringList partial;
- uint len = a->arrayLength();
+ uint len = a->getLength();
ScopedValue v(scope);
for (uint i = 0; i < len; ++i) {
bool exists;
@@ -884,12 +885,10 @@ QString Stringify::JA(ArrayObjectRef a)
}
-JsonObject::JsonObject(ExecutionEngine *engine)
- : Object(engine)
+JsonObject::JsonObject(InternalClass *ic)
+ : Object(ic)
{
- type = Type_JSONObject;
-
- Scope scope(engine);
+ Scope scope(ic->engine);
ScopedObject protectThis(scope, this);
defineDefaultProperty(QStringLiteral("parse"), method_parse, 2);
@@ -925,7 +924,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
if (o) {
stringify.replacerFunction = o->asFunctionObject();
if (o->isArrayObject()) {
- uint arrayLen = o->arrayLength();
+ uint arrayLen = o->getLength();
ScopedValue v(scope);
for (uint i = 0; i < arrayLen; ++i) {
v = o->getIndexed(i);
@@ -1057,10 +1056,9 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
int size = array.size();
Scoped<ArrayObject> a(scope, engine->newArrayObject());
a->arrayReserve(size);
- for (int i = 0; i < size; i++) {
- a->arrayData[i].value = fromJsonValue(engine, array.at(i));
- a->arrayDataLen = i + 1;
- }
+ ScopedValue v(scope);
+ for (int i = 0; i < size; i++)
+ a->arrayPut(i, (v = fromJsonValue(engine, array.at(i))));
a->setArrayLengthUnchecked(size);
return a.asReturnedValue();
}
@@ -1083,7 +1081,7 @@ QJsonArray JsonObject::toJsonArray(ArrayObjectRef a, V4ObjectSet &visitedObjects
visitedObjects.insert(a);
ScopedValue v(scope);
- quint32 length = a->arrayLength();
+ quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
if (v->asFunctionObject())
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 3bcbdeadbf..34a4f4dd4b 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -51,10 +51,12 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct JsonObject : Object {
+ Q_MANAGED_TYPE(JsonObject)
+ V4_OBJECT
private:
typedef QSet<QV4::Object *> V4ObjectSet;
public:
- JsonObject(ExecutionEngine *engine);
+ JsonObject(InternalClass *ic);
static ReturnedValue method_parse(CallContext *ctx);
static ReturnedValue method_stringify(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index a870cdac61..4a75272843 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -46,8 +46,40 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
+
+ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttributes *attrs)
+{
+ int i = 0;
+ while (i < Size && obj) {
+ classList[i] = obj->internalClass;
+
+ index = obj->internalClass->find(name);
+ if (index != UINT_MAX) {
+ level = i;
+ *attrs = obj->internalClass->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData[index].value.asReturnedValue() : obj->getValue(thisObject, obj->memberData + index, *attrs);
+ }
+
+ obj = obj->prototype();
+ ++i;
+ }
+ level = Size;
+
+ while (obj) {
+ index = obj->internalClass->find(name);
+ if (index != UINT_MAX) {
+ *attrs = obj->internalClass->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData[index].value.asReturnedValue() : obj->getValue(thisObject, obj->memberData + index, *attrs);
+ }
+
+ obj = obj->prototype();
+ }
+ return Primitive::emptyValue().asReturnedValue();
+}
+
+ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
{
+ Object *thisObject = obj;
int i = 0;
while (i < Size && obj) {
classList[i] = obj->internalClass;
@@ -56,7 +88,7 @@ Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return obj->memberData + index;
+ return !attrs->isAccessor() ? obj->memberData[index].value.asReturnedValue() : thisObject->getValue(obj->memberData + index, *attrs);
}
obj = obj->prototype();
@@ -68,14 +100,142 @@ Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return obj->memberData + index;
+ return !attrs->isAccessor() ? obj->memberData[index].value.asReturnedValue() : thisObject->getValue(obj->memberData + index, *attrs);
}
obj = obj->prototype();
}
- return 0;
+ return Primitive::emptyValue().asReturnedValue();
+}
+
+ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, const ValueRef object, const ValueRef index)
+{
+ if (object->isObject() && index->asArrayIndex() < UINT_MAX) {
+ l->indexedGetter = indexedGetterObjectInt;
+ return indexedGetterObjectInt(l, object, index);
+ }
+ return indexedGetterFallback(l, object, index);
+}
+
+ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index)
+{
+ Q_UNUSED(l);
+ ExecutionContext *ctx = l->engine->currentContext();
+ Scope scope(ctx);
+ uint idx = index->asArrayIndex();
+
+ Scoped<Object> o(scope, object);
+ if (!o) {
+ if (idx < UINT_MAX) {
+ if (String *str = object->asString()) {
+ if (idx >= (uint)str->toQString().length()) {
+ return Encode::undefined();
+ }
+ const QString s = str->toQString().mid(idx, 1);
+ return scope.engine->newString(s)->asReturnedValue();
+ }
+ }
+
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow());
+ return ctx->throwTypeError(message);
+ }
+
+ o = __qmljs_convert_to_object(ctx, object);
+ if (!o) // type error
+ return Encode::undefined();
+ }
+
+ if (idx < UINT_MAX) {
+ if (!o->arrayData->hasAttributes()) {
+ ScopedValue v(scope, o->arrayData->get(idx));
+ if (!v->isEmpty())
+ return v->asReturnedValue();
+ }
+
+ return o->getIndexed(idx);
+ }
+
+ ScopedString name(scope, index->toString(ctx));
+ if (scope.hasException())
+ return Encode::undefined();
+ return o->get(name);
+
+}
+
+
+ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index)
+{
+ uint idx = index->asArrayIndex();
+ if (idx == UINT_MAX || !object->isObject())
+ return indexedGetterGeneric(l, object, index);
+
+ Object *o = object->objectValue();
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
+ if (idx < static_cast<SimpleArrayData *>(o->arrayData)->len)
+ if (!o->arrayData->data[idx].isEmpty())
+ return o->arrayData->data[idx].asReturnedValue();
+ }
+
+ return indexedGetterFallback(l, object, index);
+}
+
+void Lookup::indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v)
+{
+ if (object->isObject()) {
+ Object *o = object->objectValue();
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) {
+ l->indexedSetter = indexedSetterObjectInt;
+ indexedSetterObjectInt(l, object, index, v);
+ return;
+ }
+ }
+ indexedSetterFallback(l, object, index, v);
+}
+
+void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef value)
+{
+ ExecutionContext *ctx = l->engine->currentContext();
+ Scope scope(ctx);
+ ScopedObject o(scope, object->toObject(ctx));
+ if (scope.engine->hasException)
+ return;
+
+ uint idx = index->asArrayIndex();
+ if (idx < UINT_MAX) {
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
+ if (s && idx < s->len && !s->data[idx].isEmpty()) {
+ s->data[idx] = value;
+ return;
+ }
+ }
+ o->putIndexed(idx, value);
+ return;
+ }
+
+ ScopedString name(scope, index->toString(ctx));
+ o->put(name, value);
}
+void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v)
+{
+ uint idx = index->asArrayIndex();
+ if (idx == UINT_MAX || !object->isObject()) {
+ indexedSetterGeneric(l, object, index, v);
+ return;
+ }
+
+ Object *o = object->objectValue();
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
+ if (idx < s->len && !s->data[idx].isEmpty()) {
+ s->data[idx] = v;
+ return;
+ }
+ }
+ indexedSetterFallback(l, object, index, v);
+}
ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
{
@@ -106,8 +266,8 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
}
PropertyAttributes attrs;
- Property *p = l->lookup(proto, &attrs);
- if (p) {
+ ReturnedValue v = l->lookup(object, proto, &attrs);
+ if (v != Primitive::emptyValue().asReturnedValue()) {
l->type = object->type();
l->proto = proto;
if (attrs.isData()) {
@@ -115,13 +275,13 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
l->getter = Lookup::primitiveGetter0;
else if (l->level == 1)
l->getter = Lookup::primitiveGetter1;
- return p->value.asReturnedValue();
+ return v;
} else {
if (l->level == 0)
l->getter = Lookup::primitiveGetterAccessor0;
else if (l->level == 1)
l->getter = Lookup::primitiveGetterAccessor1;
- return proto->getValue(object, p, attrs);
+ return v;
}
}
@@ -316,13 +476,22 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, const ValueRef object)
return getterGeneric(l, object);
}
+ReturnedValue Lookup::arrayLengthGetter(Lookup *l, const ValueRef object)
+{
+ if (ArrayObject *a = object->asArrayObject())
+ return a->memberData[ArrayObject::LengthPropertyIndex].value.asReturnedValue();
+
+ l->getter = getterGeneric;
+ return getterGeneric(l, object);
+}
+
ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
PropertyAttributes attrs;
- Property *p = l->lookup(o, &attrs);
- if (p) {
+ ReturnedValue v = l->lookup(o, &attrs);
+ if (v != Primitive::emptyValue().asReturnedValue()) {
if (attrs.isData()) {
if (l->level == 0)
l->globalGetter = globalGetter0;
@@ -330,7 +499,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
l->globalGetter = globalGetter1;
else if (l->level == 2)
l->globalGetter = globalGetter2;
- return p->value.asReturnedValue();
+ return v;
} else {
if (l->level == 0)
l->globalGetter = globalGetterAccessor0;
@@ -338,7 +507,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
l->globalGetter = globalGetterAccessor1;
else if (l->level == 2)
l->globalGetter = globalGetterAccessor2;
- return o->getValue(p, attrs);
+ return v;
}
}
Scope scope(ctx);
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 9966d36604..7f107bf8eb 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -55,11 +55,14 @@ namespace QV4 {
struct Lookup {
enum { Size = 4 };
union {
+ ReturnedValue (*indexedGetter)(Lookup *l, const ValueRef object, const ValueRef index);
+ void (*indexedSetter)(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
ReturnedValue (*getter)(Lookup *l, const ValueRef object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionContext *ctx);
void (*setter)(Lookup *l, const ValueRef object, const ValueRef v);
};
union {
+ ExecutionEngine *engine;
InternalClass *classList[Size];
struct {
void *dummy0;
@@ -72,6 +75,14 @@ struct Lookup {
uint index;
String *name;
+ static ReturnedValue indexedGetterGeneric(Lookup *l, const ValueRef object, const ValueRef index);
+ static ReturnedValue indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index);
+ static ReturnedValue indexedGetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index);
+
+ static void indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
+ static void indexedSetterFallback(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef value);
+ static void indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
+
static ReturnedValue getterGeneric(Lookup *l, const ValueRef object);
static ReturnedValue getter0(Lookup *l, const ValueRef object);
static ReturnedValue getter1(Lookup *l, const ValueRef object);
@@ -85,6 +96,7 @@ struct Lookup {
static ReturnedValue primitiveGetterAccessor0(Lookup *l, const ValueRef object);
static ReturnedValue primitiveGetterAccessor1(Lookup *l, const ValueRef object);
static ReturnedValue stringLengthGetter(Lookup *l, const ValueRef object);
+ static ReturnedValue arrayLengthGetter(Lookup *l, const ValueRef object);
static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionContext *ctx);
static ReturnedValue globalGetter0(Lookup *l, ExecutionContext *ctx);
@@ -100,7 +112,8 @@ struct Lookup {
static void setterInsert1(Lookup *l, const ValueRef object, const ValueRef value);
static void setterInsert2(Lookup *l, const ValueRef object, const ValueRef value);
- Property *lookup(Object *obj, PropertyAttributes *attrs);
+ ReturnedValue lookup(ValueRef thisObject, Object *obj, PropertyAttributes *attrs);
+ ReturnedValue lookup(Object *obj, PropertyAttributes *attrs);
};
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index fef7489110..1f4030a4ed 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -47,24 +47,18 @@ using namespace QV4;
const ManagedVTable Managed::static_vtbl =
{
- call,
- construct,
- 0 /*markObjects*/,
- destroy,
- 0 /*collectDeletables*/,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- isEqualTo,
+ Managed::IsExecutionContext,
+ Managed::IsString,
+ Managed::IsObject,
+ Managed::IsFunctionObject,
+ Managed::IsErrorObject,
+ Managed::IsArrayData,
0,
+ Managed::MyType,
"Managed",
+ destroy,
+ 0 /*markObjects*/,
+ isEqualTo
};
@@ -101,7 +95,7 @@ ExecutionEngine *Managed::engine() const
QString Managed::className() const
{
const char *s = 0;
- switch (Type(type)) {
+ switch (Type(internalClass->vtable->type)) {
case Type_Invalid:
case Type_String:
return QString();
@@ -157,18 +151,23 @@ QString Managed::className() const
case Type_ArgumentsObject:
s = "Arguments";
break;
- case Type_JSONObject:
+ case Type_JsonObject:
s = "JSON";
break;
case Type_MathObject:
s = "Math";
break;
+
+ case Type_ExecutionContext:
+ s = "__ExecutionContext";
+ break;
case Type_ForeachIteratorObject:
s = "__ForeachIterator";
break;
case Type_RegExp:
- s = "RegExp";
+ s = "__RegExp";
break;
+
case Type_QmlSequence:
s = "QmlSequence";
break;
@@ -182,67 +181,7 @@ void Managed::setVTable(const ManagedVTable *vt)
internalClass = internalClass->changeVTable(vt);
}
-ReturnedValue Managed::construct(Managed *m, CallData *)
-{
- return m->engine()->currentContext()->throwTypeError();
-}
-
-ReturnedValue Managed::call(Managed *m, CallData *)
-{
- return m->engine()->currentContext()->throwTypeError();
-}
-
-ReturnedValue Managed::getLookup(Managed *m, Lookup *)
-{
- return m->engine()->currentContext()->throwTypeError();
-}
-
-void Managed::setLookup(Managed *m, Lookup *, const ValueRef)
-{
- m->engine()->currentContext()->throwTypeError();
-}
-
bool Managed::isEqualTo(Managed *, Managed *)
{
return false;
}
-
-ReturnedValue Managed::get(const StringRef name, bool *hasProperty)
-{
- return internalClass->vtable->get(this, name, hasProperty);
-}
-
-ReturnedValue Managed::getIndexed(uint index, bool *hasProperty)
-{
- return internalClass->vtable->getIndexed(this, index, hasProperty);
-}
-
-void Managed::put(const StringRef name, const ValueRef value)
-{
- internalClass->vtable->put(this, name, value);
-}
-
-void Managed::setLookup(Lookup *l, const ValueRef v)
-{
- internalClass->vtable->setLookup(this, l, v);
-}
-
-void Managed::putIndexed(uint index, const ValueRef value)
-{
- internalClass->vtable->putIndexed(this, index, value);
-}
-
-PropertyAttributes Managed::query(StringRef name) const
-{
- return internalClass->vtable->query(this, name);
-}
-
-bool Managed::deleteProperty(const StringRef name)
-{
- return internalClass->vtable->deleteProperty(this, name);
-}
-
-Property *Managed::advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
-{
- return internalClass->vtable->advanceIterator(this, it, name, index, attributes);
-}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index e10409f397..8c6f2daf9b 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -45,7 +45,7 @@
#include <QtCore/QVector>
#include <QtCore/QDebug>
#include "qv4global_p.h"
-#include "qv4value_def_p.h"
+#include "qv4value_p.h"
#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -53,8 +53,8 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
#define Q_MANAGED_CHECK \
- template <typename T> inline void qt_check_for_QMANAGED_macro(const T &_q_argument) const \
- { int i = qYouForgotTheQ_MANAGED_Macro(this, &_q_argument); i = i + 1; }
+ template <typename T> inline void qt_check_for_QMANAGED_macro(const T *_q_argument) const \
+ { int i = qYouForgotTheQ_MANAGED_Macro(this, _q_argument); i = i + 1; }
template <typename T>
inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
@@ -62,13 +62,25 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
template <typename T1, typename T2>
inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
-#define Q_MANAGED \
+#define V4_MANAGED \
public: \
Q_MANAGED_CHECK \
static const QV4::ManagedVTable static_vtbl; \
+ static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
template <typename T> \
QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+#define V4_OBJECT \
+ public: \
+ Q_MANAGED_CHECK \
+ static const QV4::ObjectVTable static_vtbl; \
+ static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ template <typename T> \
+ QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+
+#define Q_MANAGED_TYPE(type) \
+ public: \
+ enum { MyType = Type_##type };
struct GCDeletable
{
@@ -80,10 +92,25 @@ struct GCDeletable
struct ManagedVTable
{
+ uint isExecutionContext : 1;
+ uint isString : 1;
+ uint isObject : 1;
+ uint isFunctionObject : 1;
+ uint isErrorObject : 1;
+ uint isArrayData : 1;
+ uint unused : 18;
+ uint type : 8;
+ const char *className;
+ void (*destroy)(Managed *);
+ void (*markObjects)(Managed *, ExecutionEngine *e);
+ bool (*isEqualTo)(Managed *m, Managed *other);
+};
+
+struct ObjectVTable
+{
+ ManagedVTable managedVTable;
ReturnedValue (*call)(Managed *, CallData *data);
ReturnedValue (*construct)(Managed *, CallData *data);
- void (*markObjects)(Managed *, ExecutionEngine *e);
- void (*destroy)(Managed *);
void (*collectDeletables)(Managed *, GCDeletable **deletable);
ReturnedValue (*get)(Managed *, const StringRef name, bool *hasProperty);
ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
@@ -95,18 +122,58 @@ struct ManagedVTable
bool (*deleteIndexedProperty)(Managed *m, uint index);
ReturnedValue (*getLookup)(Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const ValueRef v);
- bool (*isEqualTo)(Managed *m, Managed *other);
- Property *(*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
- const char *className;
+ uint (*getLength)(const Managed *m);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
};
+#define DEFINE_MANAGED_VTABLE_INT(classname) \
+{ \
+ classname::IsExecutionContext, \
+ classname::IsString, \
+ classname::IsObject, \
+ classname::IsFunctionObject, \
+ classname::IsErrorObject, \
+ classname::IsArrayData, \
+ 0, \
+ classname::MyType, \
+ #classname, \
+ destroy, \
+ markObjects, \
+ isEqualTo \
+}
+
+
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = \
+const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname)
+
+
+#define DEFINE_OBJECT_VTABLE(classname) \
+const QV4::ObjectVTable classname::static_vtbl = \
+{ \
+ DEFINE_MANAGED_VTABLE_INT(classname), \
+ call, \
+ construct, \
+ 0, \
+ get, \
+ getIndexed, \
+ put, \
+ putIndexed, \
+ query, \
+ queryIndexed, \
+ deleteProperty, \
+ deleteIndexedProperty, \
+ getLookup, \
+ setLookup, \
+ getLength, \
+ advanceIterator \
+}
+
+#define DEFINE_MANAGED_VTABLE_WITH_NAME(classname, name) \
+const QV4::ObjectVTable classname::static_vtbl = \
{ \
+ DEFINE_MANAGED_VTABLE_INT(name), \
call, \
construct, \
- markObjects, \
- destroy, \
0, \
get, \
getIndexed, \
@@ -118,18 +185,16 @@ const QV4::ManagedVTable classname::static_vtbl = \
deleteIndexedProperty, \
getLookup, \
setLookup, \
- isEqualTo, \
- advanceIterator, \
- #classname \
+ getLength, \
+ advanceIterator \
}
#define DEFINE_MANAGED_VTABLE_WITH_DELETABLES(classname) \
-const QV4::ManagedVTable classname::static_vtbl = \
+const QV4::ObjectVTable classname::static_vtbl = \
{ \
+ DEFINE_MANAGED_VTABLE_INT(classname), \
call, \
construct, \
- markObjects, \
- destroy, \
collectDeletables, \
get, \
getIndexed, \
@@ -141,14 +206,21 @@ const QV4::ManagedVTable classname::static_vtbl = \
deleteIndexedProperty, \
getLookup, \
setLookup, \
- isEqualTo, \
- advanceIterator, \
- #classname \
+ getLength, \
+ advanceIterator \
}
struct Q_QML_EXPORT Managed
{
- Q_MANAGED
+ V4_MANAGED
+ enum {
+ IsExecutionContext = false,
+ IsString = false,
+ IsObject = false,
+ IsFunctionObject = false,
+ IsErrorObject = false,
+ IsArrayData = false
+ };
private:
void *operator new(size_t);
Managed(const Managed &other);
@@ -158,7 +230,7 @@ protected:
Managed(InternalClass *internal)
: internalClass(internal), _data(0)
{
- Q_ASSERT(!internalClass || internalClass->vtable);
+ Q_ASSERT(internalClass && internalClass->vtable);
inUse = 1; extensible = 1;
}
@@ -183,13 +255,16 @@ public:
Type_RegExpObject,
Type_ErrorObject,
Type_ArgumentsObject,
- Type_JSONObject,
+ Type_JsonObject,
Type_MathObject,
+
+ Type_ExecutionContext,
Type_ForeachIteratorObject,
Type_RegExp,
Type_QmlSequence
};
+ Q_MANAGED_TYPE(Invalid)
ExecutionEngine *engine() const;
@@ -199,9 +274,9 @@ public:
if (!this || !internalClass)
return 0;
#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(*static_cast<T *>(this));
+ static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
#endif
- return internalClass->vtable == &T::static_vtbl ? static_cast<T *>(this) : 0;
+ return internalClass->vtable == T::staticVTable() ? static_cast<T *>(this) : 0;
}
template <typename T>
const T *as() const {
@@ -209,26 +284,26 @@ public:
if (!this)
return 0;
#if !defined(QT_NO_QOBJECT_CHECK)
- reinterpret_cast<T *>(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast<T *>(const_cast<Managed *>(this)));
+ static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
#endif
- return internalClass->vtable == &T::static_vtbl ? static_cast<const T *>(this) : 0;
+ return internalClass->vtable == T::staticVTable() ? static_cast<const T *>(this) : 0;
}
- String *asString() { return type == Type_String ? reinterpret_cast<String *>(this) : 0; }
- Object *asObject() { return type != Type_String ? reinterpret_cast<Object *>(this) : 0; }
- ArrayObject *asArrayObject() { return type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
- FunctionObject *asFunctionObject() { return type == Type_FunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
- BooleanObject *asBooleanObject() { return type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
- NumberObject *asNumberObject() { return type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
- StringObject *asStringObject() { return type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
- DateObject *asDateObject() { return type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
- ErrorObject *asErrorObject() { return type == Type_ErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
- ArgumentsObject *asArgumentsObject() { return type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
+ String *asString() { return internalClass->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
+ Object *asObject() { return internalClass->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
+ ArrayObject *asArrayObject() { return internalClass->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
+ FunctionObject *asFunctionObject() { return internalClass->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
+ BooleanObject *asBooleanObject() { return internalClass->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
+ NumberObject *asNumberObject() { return internalClass->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
+ StringObject *asStringObject() { return internalClass->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
+ DateObject *asDateObject() { return internalClass->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
+ ErrorObject *asErrorObject() { return internalClass->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
+ ArgumentsObject *asArgumentsObject() { return internalClass->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
- bool isListType() const { return type == Type_QmlSequence; }
+ bool isListType() const { return internalClass->vtable->type == Type_QmlSequence; }
- bool isArrayObject() const { return type == Type_ArrayObject; }
- bool isStringObject() const { return type == Type_StringObject; }
+ bool isArrayObject() const { return internalClass->vtable->type == Type_ArrayObject; }
+ bool isStringObject() const { return internalClass->vtable->type == Type_StringObject; }
QString className() const;
@@ -244,61 +319,31 @@ public:
void setVTable(const ManagedVTable *vt);
- ReturnedValue construct(CallData *d);
- ReturnedValue call(CallData *d);
- ReturnedValue get(const StringRef name, bool *hasProperty = 0);
- ReturnedValue getIndexed(uint index, bool *hasProperty = 0);
- void put(const StringRef name, const ValueRef value);
- void putIndexed(uint index, const ValueRef value);
- PropertyAttributes query(StringRef name) const;
- PropertyAttributes queryIndexed(uint index) const
- { return internalClass->vtable->queryIndexed(this, index); }
-
- bool deleteProperty(const StringRef name);
- bool deleteIndexedProperty(uint index)
- { return internalClass->vtable->deleteIndexedProperty(this, index); }
- ReturnedValue getLookup(Lookup *l)
- { return internalClass->vtable->getLookup(this, l); }
- void setLookup(Lookup *l, const ValueRef v);
-
bool isEqualTo(Managed *other)
{ return internalClass->vtable->isEqualTo(this, other); }
- Property *advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
static void destroy(Managed *that) { that->_data = 0; }
- static ReturnedValue construct(Managed *m, CallData *d);
- static ReturnedValue call(Managed *m, CallData *);
- static ReturnedValue getLookup(Managed *m, Lookup *);
- static void setLookup(Managed *m, Lookup *l, const ValueRef v);
static bool isEqualTo(Managed *m, Managed *other);
- uint internalType() const {
- return type;
- }
-
ReturnedValue asReturnedValue() { return Value::fromManaged(this).asReturnedValue(); }
InternalClass *internalClass;
- enum {
- SimpleArray = 1
- };
-
union {
uint _data;
struct {
uchar markBit : 1;
uchar inUse : 1;
uchar extensible : 1; // used by Object
- uchar isNonStrictArgumentsObject : 1;
+ uchar _unused : 1;
uchar needsActivation : 1; // used by FunctionObject
uchar strictMode : 1; // used by FunctionObject
uchar bindingKeyFlag : 1;
uchar hasAccessorProperty : 1;
- uchar type;
+ uchar _type;
mutable uchar subtype;
- uchar flags;
+ uchar _flags;
};
};
@@ -308,6 +353,7 @@ private:
friend struct ObjectIterator;
};
+
template<>
inline Managed *value_cast(const Value &v) {
return v.asManaged();
@@ -336,12 +382,67 @@ inline FunctionObject *managed_cast(Managed *m)
}
-inline ReturnedValue Managed::construct(CallData *d) {
- return internalClass->vtable->construct(this, d);
-}
-inline ReturnedValue Managed::call(CallData *d) {
- return internalClass->vtable->call(this, d);
-}
+Value *extractValuePointer(const ScopedValue &);
+template<typename T>
+Value *extractValuePointer(const Scoped<T> &);
+
+#define DEFINE_REF_METHODS(Class, Base) \
+ Class##Ref(const QV4::ScopedValue &v) \
+ { QV4::Value *val = extractValuePointer(v); ptr = QV4::value_cast<Class>(*val) ? val : 0; } \
+ Class##Ref(const QV4::Scoped<Class> &v) { ptr = extractValuePointer(v); } \
+ Class##Ref(QV4::TypedValue<Class> &v) { ptr = &v; } \
+ Class##Ref(QV4::Value &v) { ptr = QV4::value_cast<Class>(v) ? &v : 0; } \
+ Class##Ref &operator=(Class *t) { \
+ if (sizeof(void *) == 4) \
+ ptr->tag = QV4::Value::Managed_Type; \
+ ptr->m = t; \
+ return *this; \
+ } \
+ Class##Ref &operator=(QV4::Returned<Class> *t) { \
+ if (sizeof(void *) == 4) \
+ ptr->tag = QV4::Value::Managed_Type; \
+ ptr->m = t->getPointer(); \
+ return *this; \
+ } \
+ operator const Class *() const { return ptr ? static_cast<Class*>(ptr->managed()) : 0; } \
+ const Class *operator->() const { return static_cast<Class*>(ptr->managed()); } \
+ operator Class *() { return ptr ? static_cast<Class*>(ptr->managed()) : 0; } \
+ Class *operator->() { return static_cast<Class*>(ptr->managed()); } \
+ Class *getPointer() const { return static_cast<Class *>(ptr->managed()); } \
+ operator QV4::Returned<Class> *() const { return ptr ? QV4::Returned<Class>::create(getPointer()) : 0; } \
+ static Class##Ref null() { Class##Ref c; c.ptr = 0; return c; } \
+protected: \
+ Class##Ref() {} \
+public: \
+
+#define DEFINE_REF(Class, Base) \
+struct Class##Ref : public Base##Ref \
+{ DEFINE_REF_METHODS(Class, Base) } \
+
+
+struct ManagedRef {
+ // Important: Do NOT add a copy constructor to this class or any derived class
+ // adding a copy constructor actually changes the calling convention, ie.
+ // is not even binary compatible. Adding it would break assumptions made
+ // in the jit'ed code.
+ DEFINE_REF_METHODS(Managed, Managed);
+
+ bool operator==(const ManagedRef &other) {
+ if (ptr == other.ptr)
+ return true;
+ return ptr && other.ptr && ptr->m == other.ptr->m;
+ }
+ bool operator!=(const ManagedRef &other) {
+ return !operator==(other);
+ }
+ bool operator!() const { return !ptr || !ptr->managed(); }
+
+ bool isNull() const { return !ptr; }
+ ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); }
+
+public:
+ Value *ptr;
+};
}
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 5a7af1f041..16d76e6914 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -51,14 +51,14 @@
using namespace QV4;
+DEFINE_OBJECT_VTABLE(MathObject);
+
static const double qt_PI = 2.0 * ::asin(1.0);
-MathObject::MathObject(ExecutionEngine *engine)
- : Object(engine)
+MathObject::MathObject(InternalClass *ic)
+ : Object(ic)
{
- type = Type_MathObject;
-
- Scope scope(engine);
+ Scope scope(ic->engine);
ScopedObject protectThis(scope, this);
defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0)));
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 6fe3db3950..18a80c2ba0 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -49,7 +49,9 @@ namespace QV4 {
struct MathObject: Object
{
- MathObject(ExecutionEngine *engine);
+ V4_OBJECT
+ Q_MANAGED_TYPE(MathObject)
+ MathObject(InternalClass *ic);
static ReturnedValue method_abs(CallContext *context);
static ReturnedValue method_acos(CallContext *context);
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 1d6347b335..7bb41f1eec 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -288,6 +288,7 @@ Managed *MemoryManager::alloc(std::size_t size)
if (size >= MemoryManager::Data::MaxItemSize) {
// we use malloc for this
MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(malloc(size + sizeof(MemoryManager::Data::LargeItem)));
+ memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
item->next = m_d->largeItems;
m_d->largeItems = item;
return item->managed();
@@ -354,7 +355,7 @@ Managed *MemoryManager::alloc(std::size_t size)
void MemoryManager::mark()
{
- SafeValue *markBase = m_d->engine->jsStackTop;
+ Value *markBase = m_d->engine->jsStackTop;
m_d->engine->markObjects();
@@ -529,10 +530,12 @@ void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size,
#ifdef V4_USE_VALGRIND
VALGRIND_ENABLE_ERROR_REPORTING;
#endif
- if (m->internalClass->vtable->collectDeletables)
- m->internalClass->vtable->collectDeletables(m, deletable);
+ Object *o = m->asObject();
+ if (o && o->vtable()->collectDeletables)
+ o->vtable()->collectDeletables(m, deletable);
m->internalClass->vtable->destroy(m);
+ memset(m, 0, size);
m->setNextFree(*f);
#ifdef V4_USE_VALGRIND
VALGRIND_DISABLE_ERROR_REPORTING;
@@ -695,8 +698,8 @@ void MemoryManager::collectFromStack() const
void MemoryManager::collectFromJSStack() const
{
- SafeValue *v = engine()->jsStackBase;
- SafeValue *top = engine()->jsStackTop;
+ Value *v = engine()->jsStackBase;
+ Value *top = engine()->jsStackTop;
while (v < top) {
Managed *m = v->asManaged();
if (m && m->inUse)
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h
index 7d28319536..a8fd585332 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/jsruntime/qv4mm_p.h
@@ -44,7 +44,7 @@
#include "qv4global_p.h"
#include "qv4context_p.h"
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include <QScopedPointer>
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index a363a06242..decbcab7a0 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -48,13 +48,13 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(NumberCtor);
-DEFINE_MANAGED_VTABLE(NumberObject);
+DEFINE_OBJECT_VTABLE(NumberCtor);
+DEFINE_OBJECT_VTABLE(NumberObject);
NumberCtor::NumberCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Number"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 1ca3a71249..ccabcf6727 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -51,7 +51,7 @@ namespace QV4 {
struct NumberCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
NumberCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *that, CallData *callData);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 106525d412..de84747221 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -67,42 +67,30 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(Object);
+DEFINE_OBJECT_VTABLE(Object);
Object::Object(ExecutionEngine *engine)
: Managed(engine->objectClass)
, memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
- , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
{
- type = Type_Object;
- flags = SimpleArray;
- memset(memberData, 0, sizeof(Property)*memberDataAlloc);
}
Object::Object(InternalClass *ic)
: Managed(ic)
, memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
- , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
{
Q_ASSERT(internalClass->vtable && internalClass->vtable != &Managed::static_vtbl);
- type = Type_Object;
- flags = SimpleArray;
if (internalClass->size >= memberDataAlloc) {
memberDataAlloc = internalClass->size;
memberData = new Property[memberDataAlloc];
}
- memset(memberData, 0, sizeof(Property)*memberDataAlloc);
}
Object::~Object()
{
if (memberData != inlineProperties)
delete [] memberData;
- delete [] (arrayData - (sparseArray ? 0 : arrayOffset));
- if (arrayAttributes)
- delete [] (arrayAttributes - (sparseArray ? 0 : arrayOffset));
- delete sparseArray;
_data = 0;
}
@@ -150,12 +138,12 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val
return;
if (attrs.isAccessor()) {
- if (pd->set) {
- Scope scope(pd->set->engine());
+ if (FunctionObject *set = pd->setter()) {
+ Scope scope(set->engine());
ScopedCallData callData(scope, 1);
callData->args[0] = *value;
callData->thisObject = this;
- pd->set->call(callData);
+ set->call(callData);
return;
}
goto reject;
@@ -172,12 +160,6 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val
engine()->currentContext()->throwTypeError();
}
-void Object::defineDefaultProperty(const StringRef name, ValueRef value)
-{
- Property *pd = insertMember(name, Attr_Data|Attr_NotEnumerable);
- pd->value = *value;
-}
-
void Object::defineDefaultProperty(const QString &name, ValueRef value)
{
ExecutionEngine *e = engine();
@@ -216,12 +198,11 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)
void Object::defineAccessorProperty(const StringRef name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *))
{
ExecutionEngine *v4 = engine();
- Property *p = insertMember(name, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- if (getter)
- p->setGetter(v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer());
- if (setter)
- p->setSetter(v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer());
+ QV4::Scope scope(v4);
+ ScopedProperty p(scope);
+ p->setGetter(getter ? v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer() : 0);
+ p->setSetter(setter ? v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer() : 0);
+ insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
void Object::defineReadonlyProperty(const QString &name, ValueRef value)
@@ -234,8 +215,7 @@ void Object::defineReadonlyProperty(const QString &name, ValueRef value)
void Object::defineReadonlyProperty(const StringRef name, ValueRef value)
{
- Property *pd = insertMember(name, Attr_ReadOnly);
- pd->value = *value;
+ insertMember(name, value, Attr_ReadOnly);
}
void Object::markObjects(Managed *that, ExecutionEngine *e)
@@ -248,33 +228,13 @@ void Object::markObjects(Managed *that, ExecutionEngine *e)
} else {
for (uint i = 0; i < o->internalClass->size; ++i) {
const Property &pd = o->memberData[i];
- if (o->internalClass->propertyData[i].isAccessor()) {
- if (pd.getter())
- pd.getter()->mark(e);
- if (pd.setter())
- pd.setter()->mark(e);
- } else {
- pd.value.mark(e);
- }
- }
- }
- if (o->flags & SimpleArray) {
- for (uint i = 0; i < o->arrayDataLen; ++i)
- o->arrayData[i].value.mark(e);
- return;
- } else {
- for (uint i = 0; i < o->arrayDataLen; ++i) {
- const Property &pd = o->arrayData[i];
- if (o->arrayAttributes && o->arrayAttributes[i].isAccessor()) {
- if (pd.getter())
- pd.getter()->mark(e);
- if (pd.setter())
- pd.setter()->mark(e);
- } else {
- pd.value.mark(e);
- }
+ pd.value.mark(e);
+ if (o->internalClass->propertyData[i].isAccessor())
+ pd.set.mark(e);
}
}
+ if (o->arrayData)
+ o->arrayData->mark(e);
}
void Object::ensureMemberIndex(uint idx)
@@ -290,7 +250,7 @@ void Object::ensureMemberIndex(uint idx)
}
}
-Property *Object::insertMember(const StringRef s, PropertyAttributes attributes)
+void Object::insertMember(const StringRef s, const Property &p, PropertyAttributes attributes)
{
uint idx;
internalClass = internalClass->addMember(s.getPointer(), attributes, &idx);
@@ -300,7 +260,7 @@ Property *Object::insertMember(const StringRef s, PropertyAttributes attributes)
ensureMemberIndex(idx);
- return memberData + idx;
+ memberData[idx] = p;
}
// Section 8.12.1
@@ -324,14 +284,11 @@ Property *Object::__getOwnProperty__(const StringRef name, PropertyAttributes *a
Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
{
- uint pidx = propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX) {
- Property *p = arrayData + pidx;
- if (!p->value.isEmpty() && !(arrayAttributes && arrayAttributes[pidx].isGeneric())) {
- if (attrs)
- *attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- return p;
- }
+ Property *p = arrayData->getProperty(index);
+ if (p) {
+ if (attrs)
+ *attrs = arrayData->attributes(index);
+ return p;
}
if (isStringObject()) {
if (attrs)
@@ -349,7 +306,7 @@ Property *Object::__getPropertyDescriptor__(const StringRef name, PropertyAttrib
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
- return __getPropertyDescriptor__(idx);
+ return __getPropertyDescriptor__(idx, attrs);
const Object *o = this;
@@ -372,14 +329,11 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
{
const Object *o = this;
while (o) {
- uint pidx = o->propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX) {
- Property *p = o->arrayData + pidx;
- if (!p->value.isEmpty()) {
- if (attrs)
- *attrs = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- return p;
- }
+ Property *p = o->arrayData->getProperty(index);
+ if (p) {
+ if (attrs)
+ *attrs = o->arrayData->attributes(index);
+ return p;
}
if (o->isStringObject()) {
Property *p = static_cast<const StringObject *>(o)->getIndex(index);
@@ -396,36 +350,73 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
return 0;
}
-bool Object::__hasProperty__(const StringRef name) const
+bool Object::hasProperty(const StringRef name) const
{
- if (__getPropertyDescriptor__(name))
- return true;
+ uint idx = name->asArrayIndex();
+ if (idx != UINT_MAX)
+ return hasProperty(idx);
const Object *o = this;
while (o) {
- if (!o->query(name).isEmpty())
+ if (o->hasOwnProperty(name))
return true;
+
o = o->prototype();
}
return false;
}
-bool Object::__hasProperty__(uint index) const
+bool Object::hasProperty(uint index) const
{
- if (__getPropertyDescriptor__(index))
- return true;
-
const Object *o = this;
while (o) {
- if (!o->queryIndexed(index).isEmpty())
- return true;
+ if (o->hasOwnProperty(index))
+ return true;
+
o = o->prototype();
}
return false;
}
+bool Object::hasOwnProperty(const StringRef name) const
+{
+ uint idx = name->asArrayIndex();
+ if (idx != UINT_MAX)
+ return hasOwnProperty(idx);
+
+ if (internalClass->find(name) < UINT_MAX)
+ return true;
+ if (!query(name).isEmpty())
+ return true;
+ return false;
+}
+
+bool Object::hasOwnProperty(uint index) const
+{
+ if (!arrayData->isEmpty(index))
+ return true;
+ if (isStringObject()) {
+ String *s = static_cast<const StringObject *>(this)->value.asString();
+ if (index < (uint)s->length())
+ return true;
+ }
+ if (!queryIndexed(index).isEmpty())
+ return true;
+ return false;
+}
+
+ReturnedValue Object::construct(Managed *m, CallData *)
+{
+ return m->engine()->currentContext()->throwTypeError();
+}
+
+ReturnedValue Object::call(Managed *m, CallData *)
+{
+ return m->engine()->currentContext()->throwTypeError();
+}
+
ReturnedValue Object::get(Managed *m, const StringRef name, bool *hasProperty)
{
return static_cast<Object *>(m)->internalGet(name, hasProperty);
@@ -463,17 +454,13 @@ PropertyAttributes Object::query(const Managed *m, StringRef name)
PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
{
const Object *o = static_cast<const Object *>(m);
- uint pidx = o->propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX) {
- if (o->arrayAttributes)
- return o->arrayAttributes[pidx];
- if (!o->arrayData[pidx].value.isEmpty())
- return Attr_Data;
- }
+ if (o->arrayData->get(index) != Primitive::emptyValue().asReturnedValue())
+ return o->arrayData->attributes(index);
+
if (o->isStringObject()) {
- Property *p = static_cast<const StringObject *>(o)->getIndex(index);
- if (p)
- return Attr_Data;
+ String *s = static_cast<const StringObject *>(o)->value.asString();
+ if (index < (uint)s->length())
+ return (Attr_NotWritable|Attr_NotConfigurable);
}
return Attr_Invalid;
}
@@ -492,8 +479,8 @@ ReturnedValue Object::getLookup(Managed *m, Lookup *l)
{
Object *o = static_cast<Object *>(m);
PropertyAttributes attrs;
- Property *p = l->lookup(o, &attrs);
- if (p) {
+ ReturnedValue v = l->lookup(o, &attrs);
+ if (v != Primitive::emptyValue().asReturnedValue()) {
if (attrs.isData()) {
if (l->level == 0)
l->getter = Lookup::getter0;
@@ -501,7 +488,7 @@ ReturnedValue Object::getLookup(Managed *m, Lookup *l)
l->getter = Lookup::getter1;
else if (l->level == 2)
l->getter = Lookup::getter2;
- return p->value.asReturnedValue();
+ return v;
} else {
if (l->level == 0)
l->getter = Lookup::getterAccessor0;
@@ -509,7 +496,7 @@ ReturnedValue Object::getLookup(Managed *m, Lookup *l)
l->getter = Lookup::getterAccessor1;
else if (l->level == 2)
l->getter = Lookup::getterAccessor2;
- return o->getValue(p, attrs);
+ return v;
}
}
return Encode::undefined();
@@ -564,46 +551,47 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
l->setter = Lookup::setterInsert2;
}
-Property *Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
name = (String *)0;
*index = UINT_MAX;
- if (!it->arrayIndex)
- it->arrayNode = o->sparseArrayBegin();
-
- // sparse arrays
- if (it->arrayNode) {
- while (it->arrayNode != o->sparseArrayEnd()) {
- int k = it->arrayNode->key();
- uint pidx = it->arrayNode->value;
- Property *p = o->arrayData + pidx;
- it->arrayNode = it->arrayNode->nextNode();
- PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- it->arrayIndex = k + 1;
- *index = k;
- if (attrs)
+ if (o->arrayData) {
+ if (!it->arrayIndex)
+ it->arrayNode = o->sparseBegin();
+
+ // sparse arrays
+ if (it->arrayNode) {
+ while (it->arrayNode != o->sparseEnd()) {
+ int k = it->arrayNode->key();
+ uint pidx = it->arrayNode->value;
+ Property *p = reinterpret_cast<Property *>(o->arrayData->data + pidx);
+ it->arrayNode = it->arrayNode->nextNode();
+ PropertyAttributes a = o->arrayData->attributes(k);
+ if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
+ it->arrayIndex = k + 1;
+ *index = k;
*attrs = a;
- return p;
+ *pd = *p;
+ return;
+ }
}
+ it->arrayNode = 0;
+ it->arrayIndex = UINT_MAX;
}
- it->arrayNode = 0;
- it->arrayIndex = UINT_MAX;
- }
- // dense arrays
- while (it->arrayIndex < o->arrayDataLen) {
- uint pidx = o->propertyIndexFromArrayIndex(it->arrayIndex);
- Property *p = o->arrayData + pidx;
- PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- ++it->arrayIndex;
- if (!p->value.isEmpty()
- && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) {
- *index = it->arrayIndex - 1;
- if (attrs)
+ // dense arrays
+ while (it->arrayIndex < o->arrayData->length()) {
+ Value *val = o->arrayData->data + it->arrayIndex;
+ PropertyAttributes a = o->arrayData->attributes(it->arrayIndex);
+ ++it->arrayIndex;
+ if (!val->isEmpty()
+ && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) {
+ *index = it->arrayIndex - 1;
*attrs = a;
- return p;
+ pd->value = *val;
+ return;
+ }
}
}
@@ -616,13 +604,13 @@ Property *Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
name = n;
- if (attrs)
- *attrs = a;
- return p;
+ *attrs = a;
+ *pd = *p;
+ return;
}
}
- return 0;
+ *attrs = PropertyAttributes();
}
// Section 8.12.3
@@ -654,17 +642,14 @@ ReturnedValue Object::internalGet(const StringRef name, bool *hasProperty)
ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
{
Property *pd = 0;
- PropertyAttributes attrs = Attr_Data;
+ PropertyAttributes attrs;
Object *o = this;
while (o) {
- uint pidx = o->propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX) {
- if (!o->arrayData[pidx].value.isEmpty()) {
- pd = o->arrayData + pidx;
- if (o->arrayAttributes)
- attrs = o->arrayAttributes[pidx];
- break;
- }
+ Property *p = o->arrayData->getProperty(index);
+ if (p) {
+ pd = p;
+ attrs = o->arrayData->attributes(index);
+ break;
}
if (o->isStringObject()) {
pd = static_cast<StringObject *>(o)->getIndex(index);
@@ -761,11 +746,8 @@ void Object::internalPut(const StringRef name, const ValueRef value)
return;
}
- {
- Property *p = insertMember(name, Attr_Data);
- p->value = *value;
- return;
- }
+ insertMember(name, value);
+ return;
reject:
if (engine()->currentContext()->strictMode) {
@@ -781,14 +763,11 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
if (internalClass->engine->hasException)
return;
- Property *pd = 0;
PropertyAttributes attrs;
- uint pidx = propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX && !arrayData[pidx].value.isEmpty()) {
- pd = arrayData + pidx;
- attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
- }
+ Property *pd = arrayData->getProperty(index);
+ if (pd)
+ attrs = arrayData->attributes(index);
if (!pd && isStringObject()) {
pd = static_cast<StringObject *>(this)->getIndex(index);
@@ -879,22 +858,8 @@ bool Object::internalDeleteIndexedProperty(uint index)
if (internalClass->engine->hasException)
return false;
- uint pidx = propertyIndexFromArrayIndex(index);
- if (pidx == UINT_MAX)
- return true;
- if (arrayData[pidx].value.isEmpty())
- return true;
-
- if (!arrayAttributes || arrayAttributes[pidx].isConfigurable()) {
- arrayData[pidx].value = Primitive::emptyValue();
- if (arrayAttributes)
- arrayAttributes[pidx].clear();
- if (sparseArray) {
- arrayData[pidx].value.int_32 = arrayFreeList;
- arrayFreeList = pidx;
- }
+ if (!arrayData || arrayData->vtable()->del(this, index))
return true;
- }
if (engine()->currentContext()->strictMode)
engine()->currentContext()->throwTypeError();
@@ -913,6 +878,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
Scope scope(ctx);
Property *current;
PropertyAttributes *cattrs;
+ uint memberIndex;
if (isArrayObject() && name->equals(ctx->engine->id_length)) {
assert(ArrayObject::LengthPropertyIndex == internalClass->find(ctx->engine->id_length));
@@ -943,24 +909,22 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
}
// Clause 1
- {
- uint member = internalClass->find(name.getPointer());
- current = (member < UINT_MAX) ? memberData + member : 0;
- cattrs = internalClass->propertyData.constData() + member;
- }
+ memberIndex = internalClass->find(name.getPointer());
+ current = (memberIndex < UINT_MAX) ? memberData + memberIndex : 0;
+ cattrs = internalClass->propertyData.constData() + memberIndex;
if (!current) {
// clause 3
if (!extensible)
goto reject;
// clause 4
- Property *pd = insertMember(name, attrs);
- *pd = p;
- pd->fullyPopulated(&attrs);
+ Property pd = p;
+ pd.fullyPopulated(&attrs);
+ insertMember(name, pd, attrs);
return true;
}
- return __defineOwnProperty__(ctx, current, name, p, attrs);
+ return __defineOwnProperty__(ctx, memberIndex, name, p, attrs);
reject:
if (ctx->strictMode)
ctx->throwTypeError();
@@ -969,20 +933,27 @@ reject:
bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs)
{
- Property *current = 0;
-
// 15.4.5.1, 4b
- if (isArrayObject() && index >= arrayLength() && !internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
+ if (isArrayObject() && index >= getLength() && !internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
goto reject;
- if (isNonStrictArgumentsObject)
+ if (ArgumentsObject::isNonStrictArgumentsObject(this))
return static_cast<ArgumentsObject *>(this)->defineOwnProperty(ctx, index, p, attrs);
+ return defineOwnProperty2(ctx, index, p, attrs);
+reject:
+ if (ctx->strictMode)
+ ctx->throwTypeError();
+ return false;
+}
+
+bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs)
+{
+ Property *current = 0;
+
// Clause 1
{
- uint pidx = propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX && !arrayData[pidx].value.isEmpty())
- current = arrayData + pidx;
+ current = arrayData->getProperty(index);
if (!current && isStringObject())
current = static_cast<StringObject *>(this)->getIndex(index);
}
@@ -992,30 +963,40 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop
if (!extensible)
goto reject;
// clause 4
- Property *pd = arrayInsert(index, attrs);
- *pd = p;
- pd->fullyPopulated(&attrs);
+ Property pp(p);
+ pp.fullyPopulated(&attrs);
+ if (attrs == Attr_Data) {
+ Scope scope(ctx);
+ ScopedValue v(scope, pp.value);
+ arraySet(index, v);
+ } else {
+ arraySet(index, pp, attrs);
+ }
return true;
}
- return __defineOwnProperty__(ctx, current, StringRef::null(), p, attrs);
+ return __defineOwnProperty__(ctx, index, StringRef::null(), p, attrs);
reject:
if (ctx->strictMode)
ctx->throwTypeError();
return false;
}
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, const StringRef member, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs)
{
// clause 5
if (attrs.isEmpty())
return true;
- PropertyAttributes cattrs = Attr_Data;
- if (!member.isNull())
- cattrs = internalClass->propertyData[current - memberData];
- else if (arrayAttributes)
- cattrs = arrayAttributes[current - arrayData];
+ Property *current;
+ PropertyAttributes cattrs;
+ if (!member.isNull()) {
+ current = memberData + index;
+ cattrs = internalClass->propertyData[index];
+ } else {
+ current = arrayData->getProperty(index);
+ cattrs = arrayData->attributes(index);
+ }
// clause 6
if (p.isSubset(attrs, *current, cattrs))
@@ -1042,12 +1023,23 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, con
// 9b
cattrs.setType(PropertyAttributes::Accessor);
cattrs.clearWritable();
+ if (member.isNull()) {
+ // need to convert the array and the slot
+ initSparseArray();
+ setArrayAttributes(index, cattrs);
+ current = arrayData->getProperty(index);
+ }
current->setGetter(0);
current->setSetter(0);
} else {
// 9c
cattrs.setType(PropertyAttributes::Data);
cattrs.setWritable(false);
+ if (member.isNull()) {
+ // need to convert the array and the slot
+ setArrayAttributes(index, cattrs);
+ current = arrayData->getProperty(index);
+ }
current->value = Primitive::undefinedValue();
}
} else if (cattrs.isData() && attrs.isData()) { // clause 10
@@ -1056,11 +1048,11 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, con
goto reject;
}
} else { // clause 10
- assert(cattrs.isAccessor() && attrs.isAccessor());
+ Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
- if (p.getter() && !(current->getter() == p.getter() || (!current->getter() && (quintptr)p.getter() == 0x1)))
+ if (!p.value.isEmpty() && current->value.val != p.value.val)
goto reject;
- if (p.setter() && !(current->setter() == p.setter() || (!current->setter() && (quintptr)p.setter() == 0x1)))
+ if (!p.set.isEmpty() && current->set.val != p.set.val)
goto reject;
}
}
@@ -1071,12 +1063,9 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, con
if (!member.isNull()) {
internalClass = internalClass->changeMember(member.getPointer(), cattrs);
} else {
- if (cattrs != Attr_Data)
- ensureArrayAttributes();
- if (arrayAttributes)
- arrayAttributes[current - arrayData] = cattrs;
+ setArrayAttributes(index, cattrs);
}
- if (attrs.isAccessor())
+ if (cattrs.isAccessor())
hasAccessorProperty = 1;
return true;
reject:
@@ -1100,323 +1089,83 @@ void Object::copyArrayData(Object *other)
Scope scope(engine());
if (other->protoHasArray() || other->hasAccessorProperty) {
- uint len = other->arrayLength();
+ uint len = other->getLength();
Q_ASSERT(len);
ScopedValue v(scope);
for (uint i = 0; i < len; ++i) {
arraySet(i, (v = other->getIndexed(i)));
}
- } else {
- arrayReserve(other->arrayDataLen);
- arrayDataLen = other->arrayDataLen;
- memcpy(arrayData, other->arrayData, arrayDataLen*sizeof(Property));
- }
-
- arrayOffset = 0;
-
- if (other->sparseArray) {
- flags &= ~SimpleArray;
- sparseArray = new SparseArray(*other->sparseArray);
- arrayFreeList = other->arrayFreeList;
- }
-
- setArrayLengthUnchecked(other->arrayLength());
-}
-
-
-ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
-{
- Q_UNUSED(ctx);
-
- Scope scope(engine());
- ScopedValue value(scope);
-
- if (!(o->flags & SimpleArray) || o->protoHasArray()) {
- // lets be safe and slow
- for (uint i = fromIndex; i < endIndex; ++i) {
- bool exists;
- value = o->getIndexed(i, &exists);
- if (scope.hasException())
- return Encode::undefined();
- if (exists && __qmljs_strict_equal(value, v))
- return Encode(i);
- }
- } else if (sparseArray) {
- for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
- value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
- if (scope.hasException())
- return Encode::undefined();
- if (__qmljs_strict_equal(value, v))
- return Encode(n->key());
- }
- } else {
- if (endIndex > arrayDataLen)
- endIndex = arrayDataLen;
- Property *pd = arrayData;
- Property *end = pd + endIndex;
- pd += fromIndex;
- while (pd < end) {
- if (!pd->value.isEmpty()) {
- value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
- if (scope.hasException())
- return Encode::undefined();
- if (__qmljs_strict_equal(value, v))
- return Encode((uint)(pd - arrayData));
- }
- ++pd;
- }
- }
- return Encode(-1);
-}
-
-void Object::arrayConcat(const ArrayObject *other)
-{
- int newLen = arrayDataLen + other->arrayLength();
- if (other->sparseArray)
- initSparse();
- // ### copy attributes as well!
- if (sparseArray) {
- if (other->sparseArray) {
- for (const SparseArrayNode *it = other->sparseArray->begin(); it != other->sparseArray->end(); it = it->nextNode())
- arraySet(arrayDataLen + it->key(), other->arrayData + it->value);
- } else {
- int oldSize = arrayDataLen;
- arrayReserve(oldSize + other->arrayLength());
- memcpy(arrayData + oldSize, other->arrayData, other->arrayLength()*sizeof(Property));
- if (arrayAttributes)
- std::fill(arrayAttributes + oldSize, arrayAttributes + oldSize + other->arrayLength(), PropertyAttributes(Attr_Data));
- for (uint i = 0; i < other->arrayLength(); ++i) {
- SparseArrayNode *n = sparseArray->insert(arrayDataLen + i);
- n->value = oldSize + i;
- }
+ } else if (!other->arrayData) {
+ ;
+ } else if (other->hasAccessorProperty && other->arrayData->attrs && other->arrayData->isSparse()){
+ // do it the slow way
+ ScopedValue v(scope);
+ for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other->arrayData)->sparse->begin();
+ it != static_cast<const SparseArrayData *>(other->arrayData)->sparse->end(); it = it->nextNode()) {
+ v = other->getValue(reinterpret_cast<Property *>(other->arrayData->data + it->value), other->arrayData->attrs[it->value]);
+ arraySet(it->key(), v);
}
} else {
- uint oldSize = arrayLength();
- arrayReserve(oldSize + other->arrayDataLen);
- if (oldSize > arrayDataLen) {
- for (uint i = arrayDataLen; i < oldSize; ++i)
- arrayData[i].value = Primitive::emptyValue();
- }
- if (other->arrayAttributes) {
- for (uint i = 0; i < other->arrayDataLen; ++i) {
- bool exists;
- arrayData[oldSize + i].value = const_cast<ArrayObject *>(other)->getIndexed(i, &exists);
- arrayDataLen = oldSize + i + 1;
- if (arrayAttributes)
- arrayAttributes[oldSize + i] = Attr_Data;
- if (!exists)
- arrayData[oldSize + i].value = Primitive::emptyValue();
- }
+ Q_ASSERT(!arrayData && other->arrayData);
+ ArrayData::realloc(this, other->arrayData->type, 0, other->arrayData->alloc, other->arrayData->attrs);
+ if (other->arrayType() == ArrayData::Sparse) {
+ SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData);
+ SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData);
+ dd->sparse = new SparseArray(*od->sparse);
+ dd->freeList = od->freeList;
} else {
- arrayDataLen = oldSize + other->arrayDataLen;
- memcpy(arrayData + oldSize, other->arrayData, other->arrayDataLen*sizeof(Property));
- if (arrayAttributes)
- std::fill(arrayAttributes + oldSize, arrayAttributes + oldSize + other->arrayDataLen, PropertyAttributes(Attr_Data));
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData);
+ d->len = static_cast<SimpleArrayData *>(other->arrayData)->len;
+ d->offset = 0;
}
+ memcpy(arrayData->data, other->arrayData->data, arrayData->alloc*sizeof(Value));
}
- setArrayLengthUnchecked(newLen);
+ setArrayLengthUnchecked(other->getLength());
}
-void Object::arraySort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint len)
+uint Object::getLength(const Managed *m)
{
- if (!arrayDataLen)
- return;
-
- if (sparseArray) {
- context->throwUnimplemented(QStringLiteral("Object::sort unimplemented for sparse arrays"));
- return;
- }
-
- if (len > arrayDataLen)
- len = arrayDataLen;
-
- // The spec says the sorting goes through a series of get,put and delete operations.
- // this implies that the attributes don't get sorted around.
- // behavior of accessor properties is implementation defined. We simply turn them all
- // into data properties and then sort. This is in line with the sentence above.
- if (arrayAttributes) {
- for (uint i = 0; i < len; i++) {
- if ((arrayAttributes && arrayAttributes[i].isGeneric()) || arrayData[i].value.isEmpty()) {
- while (--len > i)
- if (!((arrayAttributes && arrayAttributes[len].isGeneric())|| arrayData[len].value.isEmpty()))
- break;
- arrayData[i].value = getValue(arrayData + len, arrayAttributes[len]);
- arrayData[len].value = Primitive::emptyValue();
- if (arrayAttributes) {
- arrayAttributes[i] = Attr_Data;
- arrayAttributes[len].clear();
- }
- } else if (arrayAttributes[i].isAccessor()) {
- arrayData[i].value = getValue(arrayData + i, arrayAttributes[i]);
- arrayAttributes[i] = Attr_Data;
- }
- }
- }
-
- if (!(comparefn->isUndefined() || comparefn->asObject())) {
- context->throwTypeError();
- return;
- }
-
- ArrayElementLessThan lessThan(context, thisObject, comparefn);
-
- if (!len)
- return;
- Property *begin = arrayData;
- std::sort(begin, begin + len, lessThan);
-}
-
-
-void Object::initSparse()
-{
- if (!sparseArray) {
- flags &= ~SimpleArray;
- sparseArray = new SparseArray;
- for (uint i = 0; i < arrayDataLen; ++i) {
- if (!((arrayAttributes && arrayAttributes[i].isGeneric()) || arrayData[i].value.isEmpty())) {
- SparseArrayNode *n = sparseArray->insert(i);
- n->value = i + arrayOffset;
- }
- }
-
- uint off = arrayOffset;
- if (!arrayOffset) {
- arrayFreeList = arrayDataLen;
- } else {
- arrayFreeList = 0;
- arrayData -= off;
- arrayAlloc += off;
- int o = off;
- for (int i = 0; i < o - 1; ++i) {
- arrayData[i].value = Primitive::fromInt32(i + 1);
- }
- arrayData[o - 1].value = Primitive::fromInt32(arrayDataLen + off);
- }
- for (uint i = arrayDataLen + off; i < arrayAlloc; ++i) {
- arrayData[i].value = Primitive::fromInt32(i + 1);
- }
- }
-}
-
-void Object::arrayReserve(uint n)
-{
- if (n < 8)
- n = 8;
- if (n >= arrayAlloc) {
- uint off;
- if (sparseArray) {
- assert(arrayFreeList == arrayAlloc);
- // ### FIXME
- arrayDataLen = arrayAlloc;
- off = 0;
- } else {
- off = arrayOffset;
- }
- arrayAlloc = qMax(n, 2*arrayAlloc);
- Property *newArrayData = new Property[arrayAlloc + off];
- if (arrayData) {
- memcpy(newArrayData + off, arrayData, sizeof(Property)*arrayDataLen);
- delete [] (arrayData - off);
- }
- arrayData = newArrayData + off;
- if (sparseArray) {
- for (uint i = arrayFreeList; i < arrayAlloc; ++i) {
- arrayData[i].value = Primitive::emptyValue();
- arrayData[i].value = Primitive::fromInt32(i + 1);
- }
- }
-
- if (arrayAttributes) {
- PropertyAttributes *newAttrs = new PropertyAttributes[arrayAlloc];
- memcpy(newAttrs, arrayAttributes, sizeof(PropertyAttributes)*arrayDataLen);
- delete [] (arrayAttributes - off);
-
- arrayAttributes = newAttrs;
- if (sparseArray) {
- for (uint i = arrayFreeList; i < arrayAlloc; ++i)
- arrayAttributes[i] = Attr_Invalid;
- }
- }
- }
+ Scope scope(m->engine());
+ ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length));
+ return v->toUInt32();
}
-void Object::ensureArrayAttributes()
+bool Object::setArrayLength(uint newLen)
{
- if (arrayAttributes)
- return;
-
- flags &= ~SimpleArray;
- uint off = sparseArray ? 0 : arrayOffset;
- arrayAttributes = new PropertyAttributes[arrayAlloc + off];
- arrayAttributes += off;
- for (uint i = 0; i < arrayDataLen; ++i)
- arrayAttributes[i] = Attr_Data;
- for (uint i = arrayDataLen; i < arrayAlloc; ++i)
- arrayAttributes[i] = Attr_Invalid;
-}
-
-
-bool Object::setArrayLength(uint newLen) {
- assert(isArrayObject());
+ Q_ASSERT(isArrayObject());
const Property *lengthProperty = memberData + ArrayObject::LengthPropertyIndex;
if (lengthProperty && !internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
return false;
- uint oldLen = arrayLength();
+ uint oldLen = getLength();
bool ok = true;
if (newLen < oldLen) {
- if (sparseArray) {
- SparseArrayNode *begin = sparseArray->lowerBound(newLen);
- if (begin != sparseArray->end()) {
- SparseArrayNode *it = sparseArray->end()->previousNode();
- while (1) {
- Property &pd = arrayData[it->value];
- if (arrayAttributes) {
- if (!arrayAttributes[it->value].isConfigurable()) {
- ok = false;
- newLen = it->key() + 1;
- break;
- } else {
- arrayAttributes[it->value].clear();
- }
- }
- pd.value.tag = Value::Empty_Type;
- pd.value.int_32 = arrayFreeList;
- arrayFreeList = it->value;
- bool brk = (it == begin);
- SparseArrayNode *prev = it->previousNode();
- sparseArray->erase(it);
- if (brk)
- break;
- it = prev;
- }
- }
+ if (!arrayData) {
+ Q_ASSERT(!newLen);
} else {
- Property *it = arrayData + arrayDataLen;
- const Property *begin = arrayData + newLen;
- while (--it >= begin) {
- if (arrayAttributes) {
- if (!arrayAttributes[it - arrayData].isEmpty() && !arrayAttributes[it - arrayData].isConfigurable()) {
- ok = false;
- newLen = it - arrayData + 1;
- break;
- } else {
- arrayAttributes[it - arrayData].clear();
- }
- it->value = Primitive::emptyValue();
- }
- }
- arrayDataLen = newLen;
+ uint l = arrayData->vtable()->truncate(this, newLen);
+ if (l != newLen)
+ ok = false;
+ newLen = l;
}
} else {
if (newLen >= 0x100000)
- initSparse();
+ initSparseArray();
}
setArrayLengthUnchecked(newLen);
return ok;
}
-DEFINE_MANAGED_VTABLE(ArrayObject);
+void Object::initSparseArray()
+{
+ if (arrayType() == ArrayData::Sparse)
+ return;
+
+ ArrayData::realloc(this, ArrayData::Sparse, 0, 0, false);
+}
+
+
+DEFINE_OBJECT_VTABLE(ArrayObject);
ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
: Object(engine->arrayClass)
@@ -1431,10 +1180,9 @@ ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
// elements converted to JS Strings.
int len = list.count();
arrayReserve(len);
- for (int ii = 0; ii < len; ++ii) {
- arrayData[ii].value = Encode(engine->newString(list.at(ii)));
- arrayDataLen = ii + 1;
- }
+ ScopedValue v(scope);
+ for (int ii = 0; ii < len; ++ii)
+ arrayPut(ii, (v = engine->newString(list.at(ii))));
setArrayLengthUnchecked(len);
}
@@ -1442,10 +1190,28 @@ void ArrayObject::init(ExecutionEngine *engine)
{
Q_UNUSED(engine);
- type = Type_ArrayObject;
memberData[LengthPropertyIndex].value = Primitive::fromInt32(0);
}
+ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
+{
+ if (l->name->equals(m->engine()->id_length)) {
+ // special case, as the property is on the object itself
+ l->getter = Lookup::arrayLengthGetter;
+ ArrayObject *a = static_cast<ArrayObject *>(m);
+ return a->memberData[ArrayObject::LengthPropertyIndex].value.asReturnedValue();
+ }
+ return Object::getLookup(m, l);
+}
+
+uint ArrayObject::getLength(const Managed *m)
+{
+ const ArrayObject *a = static_cast<const ArrayObject *>(m);
+ if (a->memberData[ArrayObject::LengthPropertyIndex].value.isInteger())
+ return a->memberData[ArrayObject::LengthPropertyIndex].value.integerValue();
+ return Primitive::toUInt32(a->memberData[ArrayObject::LengthPropertyIndex].value.doubleValue());
+}
+
QStringList ArrayObject::toQStringList() const
{
QStringList result;
@@ -1454,7 +1220,7 @@ QStringList ArrayObject::toQStringList() const
Scope scope(engine);
ScopedValue v(scope);
- uint32_t length = arrayLength();
+ uint32_t length = getLength();
for (uint32_t i = 0; i < length; ++i) {
v = const_cast<ArrayObject *>(this)->getIndexed(i);
result.append(v->toQStringNoThrow());
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 23f2f682fd..e3361ae160 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -49,7 +49,7 @@
#include "qv4managed_p.h"
#include "qv4property_p.h"
#include "qv4internalclass_p.h"
-#include "qv4sparsearray_p.h"
+#include "qv4arraydata_p.h"
#include <QtCore/QString>
#include <QtCore/QHash>
@@ -100,20 +100,17 @@ struct SyntaxErrorPrototype;
struct TypeErrorPrototype;
struct URIErrorPrototype;
+
struct Q_QML_EXPORT Object: Managed {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(Object)
+ enum {
+ IsObject = true
+ };
uint memberDataAlloc;
Property *memberData;
- union {
- uint arrayFreeList;
- uint arrayOffset;
- };
- uint arrayDataLen;
- uint arrayAlloc;
- PropertyAttributes *arrayAttributes;
- Property *arrayData;
- SparseArray *sparseArray;
+ ArrayData *arrayData;
enum {
InlinePropertySize = 4
@@ -124,6 +121,7 @@ struct Q_QML_EXPORT Object: Managed {
Object(InternalClass *internalClass);
~Object();
+ const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass->vtable); }
Object *prototype() const { return internalClass->prototype; }
bool setPrototype(Object *proto);
@@ -133,13 +131,17 @@ struct Q_QML_EXPORT Object: Managed {
Property *__getPropertyDescriptor__(const StringRef name, PropertyAttributes *attrs = 0) const;
Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
- bool __hasProperty__(const StringRef name) const;
- bool __hasProperty__(uint index) const;
+ bool hasProperty(const StringRef name) const;
+ bool hasProperty(uint index) const;
- bool __defineOwnProperty__(ExecutionContext *ctx, Property *current, const StringRef member, const Property &p, PropertyAttributes attrs);
+ bool hasOwnProperty(const StringRef name) const;
+ bool hasOwnProperty(uint index) const;
+
+ bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionContext *ctx, const StringRef name, const Property &p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs);
+ bool defineOwnProperty2(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs);
//
// helpers
@@ -156,7 +158,9 @@ struct Q_QML_EXPORT Object: Managed {
void putValue(Property *pd, PropertyAttributes attrs, const ValueRef value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
- void defineDefaultProperty(const StringRef name, ValueRef value);
+ void defineDefaultProperty(const StringRef name, ValueRef value) {
+ insertMember(name, value, Attr_Data|Attr_NotEnumerable);
+ }
void defineDefaultProperty(const QString &name, ValueRef value);
void defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
void defineDefaultProperty(const StringRef name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
@@ -166,113 +170,73 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, ValueRef value);
void defineReadonlyProperty(const StringRef name, ValueRef value);
- Property *insertMember(const StringRef s, PropertyAttributes attributes);
+ void insertMember(const StringRef s, const ValueRef v, PropertyAttributes attributes = Attr_Data) {
+ insertMember(s, Property::fromValue(*v), attributes);
+ }
+ void insertMember(const StringRef s, const Property &p, PropertyAttributes attributes);
inline ExecutionEngine *engine() const { return internalClass->engine; }
// Array handling
- uint allocArrayValue() {
- uint idx = arrayFreeList;
- if (arrayAlloc <= arrayFreeList)
- arrayReserve(arrayAlloc + 1);
- arrayFreeList = arrayData[arrayFreeList].value.uint_32;
- if (arrayAttributes)
- arrayAttributes[idx].setType(PropertyAttributes::Data);
- return idx;
- }
-
- uint allocArrayValue(const ValueRef v) {
- uint idx = allocArrayValue();
- Property *pd = &arrayData[idx];
- pd->value = *v;
- return idx;
- }
- void freeArrayValue(int idx) {
- Property &pd = arrayData[idx];
- pd.value.tag = Value::Empty_Type;
- pd.value.int_32 = arrayFreeList;
- arrayFreeList = idx;
- if (arrayAttributes)
- arrayAttributes[idx].clear();
- }
-
- void getArrayHeadRoom() {
- assert(!sparseArray && !arrayOffset);
- arrayOffset = qMax(arrayDataLen >> 2, (uint)16);
- Property *newArray = new Property[arrayOffset + arrayAlloc];
- memcpy(newArray + arrayOffset, arrayData, arrayDataLen*sizeof(Property));
- delete [] arrayData;
- arrayData = newArray + arrayOffset;
- if (arrayAttributes) {
- PropertyAttributes *newAttrs = new PropertyAttributes[arrayOffset + arrayAlloc];
- memcpy(newAttrs + arrayOffset, arrayAttributes, arrayDataLen*sizeof(PropertyAttributes));
- delete [] arrayAttributes;
- arrayAttributes = newAttrs + arrayOffset;
- }
- }
-
public:
void copyArrayData(Object *other);
- void initSparse();
- uint arrayLength() const;
bool setArrayLength(uint newLen);
-
void setArrayLengthUnchecked(uint l);
- Property *arrayInsert(uint index, PropertyAttributes attributes = Attr_Data);
-
- void arraySet(uint index, const Property *pd);
+ void arraySet(uint index, const Property &p, PropertyAttributes attributes = Attr_Data);
void arraySet(uint index, ValueRef value);
- uint propertyIndexFromArrayIndex(uint index) const
- {
- if (!sparseArray) {
- if (index >= arrayDataLen)
- return UINT_MAX;
- return index;
- } else {
- SparseArrayNode *n = sparseArray->findNode(index);
- if (!n)
- return UINT_MAX;
- return n->value;
- }
+ bool arrayPut(uint index, ValueRef value) {
+ return arrayData->vtable()->put(this, index, value);
}
-
- Property *arrayAt(uint index) const {
- uint pidx = propertyIndexFromArrayIndex(index);
- if (pidx == UINT_MAX)
- return 0;
- return arrayData + pidx;
+ bool arrayPut(uint index, Value *values, uint n) {
+ return arrayData->vtable()->putArray(this, index, values, n);
}
-
- Property *nonSparseArrayAt(uint index) const {
- if (sparseArray)
- return 0;
- if (index >= arrayDataLen)
- return 0;
- return arrayData + index;
+ void setArrayAttributes(uint i, PropertyAttributes a) {
+ Q_ASSERT(arrayData);
+ if (arrayData->attrs || a != Attr_Data) {
+ ArrayData::ensureAttributes(this);
+ a.resolve();
+ arrayData->vtable()->setAttribute(this, i, a);
+ }
}
void push_back(const ValueRef v);
- SparseArrayNode *sparseArrayBegin() { return sparseArray ? sparseArray->begin() : 0; }
- SparseArrayNode *sparseArrayEnd() { return sparseArray ? sparseArray->end() : 0; }
+ ArrayData::Type arrayType() const {
+ return arrayData ? arrayData->type : ArrayData::Simple;
+ }
+ // ### remove me
+ void setArrayType(ArrayData::Type t) {
+ Q_ASSERT(t != ArrayData::Simple && t != ArrayData::Sparse);
+ arrayCreate();
+ arrayData->type = t;
+ }
+
+ inline void arrayReserve(uint n) {
+ ArrayData::realloc(this, ArrayData::Simple, 0, n, false);
+ }
- void arrayConcat(const ArrayObject *other);
- void arraySort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint arrayDataLen);
- ReturnedValue arrayIndexOf(const ValueRef v, uint fromIndex, uint arrayDataLen, ExecutionContext *ctx, Object *o);
+ void arrayCreate() {
+ if (!arrayData)
+ ArrayData::realloc(this, ArrayData::Simple, 0, 0, false);
+#ifdef CHECK_SPARSE_ARRAYS
+ initSparseArray();
+#endif
+ }
- void arrayReserve(uint n);
- void ensureArrayAttributes();
+ void initSparseArray();
+ SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData)->sparse->begin() : 0; }
+ SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData)->sparse->end() : 0; }
inline bool protoHasArray() {
Scope scope(engine());
Scoped<Object> p(scope, this);
while ((p = p->prototype()))
- if (p->arrayDataLen)
+ if (p->arrayData)
return true;
return false;
@@ -280,27 +244,38 @@ public:
void ensureMemberIndex(uint idx);
inline ReturnedValue get(const StringRef name, bool *hasProperty = 0)
- { return internalClass->vtable->get(this, name, hasProperty); }
+ { return vtable()->get(this, name, hasProperty); }
inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
- { return internalClass->vtable->getIndexed(this, idx, hasProperty); }
+ { return vtable()->getIndexed(this, idx, hasProperty); }
inline void put(const StringRef name, const ValueRef v)
- { internalClass->vtable->put(this, name, v); }
+ { vtable()->put(this, name, v); }
inline void putIndexed(uint idx, const ValueRef v)
- { internalClass->vtable->putIndexed(this, idx, v); }
- using Managed::get;
- using Managed::getIndexed;
- using Managed::put;
- using Managed::putIndexed;
- using Managed::query;
- using Managed::queryIndexed;
- using Managed::deleteProperty;
- using Managed::deleteIndexedProperty;
- using Managed::getLookup;
- using Managed::setLookup;
- using Managed::advanceIterator;
+ { vtable()->putIndexed(this, idx, v); }
+ PropertyAttributes query(StringRef name) const
+ { return vtable()->query(this, name); }
+ PropertyAttributes queryIndexed(uint index) const
+ { return vtable()->queryIndexed(this, index); }
+ bool deleteProperty(const StringRef name)
+ { return vtable()->deleteProperty(this, name); }
+ bool deleteIndexedProperty(uint index)
+ { return vtable()->deleteIndexedProperty(this, index); }
+ ReturnedValue getLookup(Lookup *l)
+ { return vtable()->getLookup(this, l); }
+ void setLookup(Lookup *l, const ValueRef v)
+ { vtable()->setLookup(this, l, v); }
+ void advanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes)
+ { vtable()->advanceIterator(this, it, name, index, p, attributes); }
+ uint getLength() const { return vtable()->getLength(this); }
+
+ inline ReturnedValue construct(CallData *d)
+ { return vtable()->construct(this, d); }
+ inline ReturnedValue call(CallData *d)
+ { return vtable()->call(this, d); }
protected:
static void destroy(Managed *that);
static void markObjects(Managed *that, ExecutionEngine *e);
+ static ReturnedValue construct(Managed *m, CallData *);
+ static ReturnedValue call(Managed *m, CallData *);
static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, const StringRef name, const ValueRef value);
@@ -311,8 +286,8 @@ protected:
static bool deleteIndexedProperty(Managed *m, uint index);
static ReturnedValue getLookup(Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const ValueRef v);
- static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
-
+ static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
+ static uint getLength(const Managed *m);
private:
ReturnedValue internalGet(const StringRef name, bool *hasProperty);
@@ -327,41 +302,40 @@ private:
};
struct BooleanObject: Object {
- Q_MANAGED
- SafeValue value;
+ V4_OBJECT
+ Q_MANAGED_TYPE(BooleanObject)
+ Value value;
BooleanObject(ExecutionEngine *engine, const ValueRef val)
: Object(engine->booleanClass) {
- type = Type_BooleanObject;
value = val;
}
protected:
BooleanObject(InternalClass *ic)
: Object(ic) {
- setVTable(&static_vtbl);
- type = Type_BooleanObject;
+ Q_ASSERT(internalClass->vtable == staticVTable());
value = Encode(false);
}
};
struct NumberObject: Object {
- Q_MANAGED
- SafeValue value;
+ V4_OBJECT
+ Q_MANAGED_TYPE(NumberObject)
+ Value value;
NumberObject(ExecutionEngine *engine, const ValueRef val)
: Object(engine->numberClass) {
- type = Type_NumberObject;
value = val;
}
protected:
NumberObject(InternalClass *ic)
: Object(ic) {
- setVTable(&static_vtbl);
- type = Type_NumberObject;
+ Q_ASSERT(internalClass->vtable == staticVTable());
value = Encode((int)0);
}
};
struct ArrayObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(ArrayObject)
enum {
LengthPropertyIndex = 0
};
@@ -372,19 +346,13 @@ struct ArrayObject: Object {
void init(ExecutionEngine *engine);
+ static ReturnedValue getLookup(Managed *m, Lookup *l);
+ using Object::getLength;
+ static uint getLength(const Managed *m);
+
QStringList toQStringList() const;
};
-inline uint Object::arrayLength() const
-{
- if (isArrayObject()) {
- if (memberData[ArrayObject::LengthPropertyIndex].value.isInteger())
- return memberData[ArrayObject::LengthPropertyIndex].value.integerValue();
- return Primitive::toUInt32(memberData[ArrayObject::LengthPropertyIndex].value.doubleValue());
- }
- return 0;
-}
-
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject()) {
@@ -396,64 +364,46 @@ inline void Object::setArrayLengthUnchecked(uint l)
inline void Object::push_back(const ValueRef v)
{
- uint idx = arrayLength();
- if (!sparseArray) {
- if (idx >= arrayAlloc)
- arrayReserve(idx + 1);
- arrayData[idx].value = *v;
- arrayDataLen = idx + 1;
- } else {
- uint idx = allocArrayValue(v);
- sparseArray->push_back(idx, arrayLength());
- }
+ arrayCreate();
+
+ uint idx = getLength();
+ arrayReserve(idx + 1);
+ arrayPut(idx, v);
setArrayLengthUnchecked(idx + 1);
}
-inline Property *Object::arrayInsert(uint index, PropertyAttributes attributes) {
- if (attributes.isAccessor())
+inline void Object::arraySet(uint index, const Property &p, PropertyAttributes attributes)
+{
+ // ### Clean up
+ arrayCreate();
+ if (attributes.isAccessor()) {
hasAccessorProperty = 1;
-
- Property *pd;
- if (!sparseArray && (index < 0x1000 || index < arrayDataLen + (arrayDataLen >> 2))) {
- if (index >= arrayAlloc)
- arrayReserve(index + 1);
- if (index >= arrayDataLen) {
- // mark possible hole in the array
- for (uint i = arrayDataLen; i < index; ++i) {
- arrayData[i].value = Primitive::emptyValue();
- if (arrayAttributes)
- arrayAttributes[i].clear();
- }
- arrayDataLen = index + 1;
- }
- pd = arrayData + index;
+ initSparseArray();
+ } else if (index > 0x1000 && index > 2*arrayData->alloc) {
+ initSparseArray();
} else {
- initSparse();
- SparseArrayNode *n = sparseArray->insert(index);
- if (n->value == UINT_MAX)
- n->value = allocArrayValue();
- pd = arrayData + n->value;
+ arrayData->vtable()->reallocate(this, index + 1, false);
}
- if (index >= arrayLength())
+ setArrayAttributes(index, attributes);
+ Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
+ pd->value = p.value;
+ if (attributes.isAccessor())
+ pd->set = p.set;
+ if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
- if (arrayAttributes || attributes != Attr_Data) {
- if (!arrayAttributes)
- ensureArrayAttributes();
- attributes.resolve();
- arrayAttributes[pd - arrayData] = attributes;
- }
- return pd;
}
-inline void Object::arraySet(uint index, ValueRef value)
-{
- Property *pd = arrayInsert(index);
- pd->value = *value;
-}
-inline void Object::arraySet(uint index, const Property *pd)
+inline void Object::arraySet(uint index, ValueRef value)
{
- *arrayInsert(index) = *pd;
+ arrayCreate();
+ if (index > 0x1000 && index > 2*arrayData->alloc) {
+ initSparseArray();
+ }
+ Property *pd = ArrayData::insert(this, index);
+ pd->value = value ? *value : Primitive::undefinedValue();
+ if (isArrayObject() && index >= getLength())
+ setArrayLengthUnchecked(index + 1);
}
template<>
@@ -467,11 +417,28 @@ inline ArrayObject *value_cast(const Value &v) {
}
template<>
-inline ReturnedValue value_convert<Object>(ExecutionContext *ctx, const Value &v)
+inline ReturnedValue value_convert<Object>(ExecutionEngine *e, const Value &v)
{
- return v.toObject(ctx)->asReturnedValue();
+ return v.toObject(e->currentContext())->asReturnedValue();
}
+struct ObjectRef : public ManagedRef
+{
+ DEFINE_REF_METHODS(Object, Managed)
+
+ static ObjectRef fromValuePointer(Value *s) {
+ ObjectRef r;
+ r.ptr = s;
+ if (sizeof(void *) == 8)
+ r.ptr->val = 0;
+ else
+ *r.ptr = Value::fromManaged(0);
+ return r;
+ }
+};
+
+DEFINE_REF(ArrayObject, Object);
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 04fa504991..e5f693c323 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -46,27 +46,26 @@
using namespace QV4;
-ObjectIterator::ObjectIterator(SafeObject *scratch1, SafeObject *scratch2, const ObjectRef o, uint flags)
- : object(*scratch1)
- , current(*scratch2)
+ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags)
+ : object(ObjectRef::fromValuePointer(scratch1))
+ , current(ObjectRef::fromValuePointer(scratch2))
, arrayNode(0)
, arrayIndex(0)
, memberIndex(0)
, flags(flags)
{
- object = o;
- current = o;
- tmpDynamicProperty.value = Primitive::undefinedValue();
+ object = o.getPointer();
+ current = o.getPointer();
- if (object && object->isNonStrictArgumentsObject) {
+ if (!!object && object->asArgumentsObject()) {
Scope scope(object->engine());
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
}
}
ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags)
- : object(*static_cast<SafeObject *>(scope.alloc(1)))
- , current(*static_cast<SafeObject *>(scope.alloc(1)))
+ : object(ObjectRef::fromValuePointer(scope.alloc(1)))
+ , current(ObjectRef::fromValuePointer(scope.alloc(1)))
, arrayNode(0)
, arrayIndex(0)
, memberIndex(0)
@@ -74,40 +73,47 @@ ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags)
{
object = o;
current = o;
- tmpDynamicProperty.value = Primitive::undefinedValue();
- if (object && object->isNonStrictArgumentsObject) {
+ if (!!object && object->asArgumentsObject()) {
Scope scope(object->engine());
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
}
}
-Property *ObjectIterator::next(StringRef name, uint *index, PropertyAttributes *attrs)
+void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAttributes *attrs)
{
name = (String *)0;
*index = UINT_MAX;
- if (!object)
- return 0;
- Property *p = 0;
+ if (!object) {
+ *attrs = PropertyAttributes();
+ return;
+ }
+
while (1) {
if (!current)
break;
- while ((p = current->advanceIterator(this, name, index, attrs))) {
+ while (1) {
+ current->advanceIterator(this, name, index, pd, attrs);
+ if (attrs->isEmpty())
+ break;
// check the property is not already defined earlier in the proto chain
if (current != object) {
- Property *pp;
- if (name) {
- pp = object->__getPropertyDescriptor__(name);
- } else {
- assert (*index != UINT_MAX);
- pp = object->__getPropertyDescriptor__(*index);
+ Object *o = object;
+ bool shadowed = false;
+ while (o != current) {
+ if ((!!name && o->hasOwnProperty(name)) ||
+ (*index != UINT_MAX && o->hasOwnProperty(*index))) {
+ shadowed = true;
+ break;
+ }
+ o = o->prototype();
}
- if (pp != p)
+ if (shadowed)
continue;
}
- return p;
+ return;
}
if (flags & WithProtoChain)
@@ -118,7 +124,7 @@ Property *ObjectIterator::next(StringRef name, uint *index, PropertyAttributes *
arrayIndex = 0;
memberIndex = 0;
}
- return 0;
+ *attrs = PropertyAttributes();
}
ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
@@ -127,14 +133,15 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
return Encode::null();
PropertyAttributes attrs;
+ Property p;
uint index;
Scope scope(object->engine());
ScopedString name(scope);
- Property *p = next(name, &index, &attrs);
- if (!p)
+ next(name, &index, &p, &attrs);
+ if (attrs.isEmpty())
return Encode::null();
- value = object->getValue(p, attrs);
+ value = object->getValue(&p, attrs);
if (!!name)
return name->asReturnedValue();
@@ -148,14 +155,15 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
return Encode::null();
PropertyAttributes attrs;
+ Property p;
uint index;
Scope scope(object->engine());
ScopedString name(scope);
- Property *p = next(name, &index, &attrs);
- if (!p)
+ next(name, &index, &p, &attrs);
+ if (attrs.isEmpty())
return Encode::null();
- value = object->getValue(p, attrs);
+ value = object->getValue(&p, attrs);
if (!!name)
return name->asReturnedValue();
@@ -169,11 +177,12 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
return Encode::null();
PropertyAttributes attrs;
+ Property p;
uint index;
Scope scope(object->engine());
ScopedString name(scope);
- Property *p = next(name, &index, &attrs);
- if (!p)
+ next(name, &index, &p, &attrs);
+ if (attrs.isEmpty())
return Encode::null();
if (!!name)
@@ -183,7 +192,7 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
}
-DEFINE_MANAGED_VTABLE(ForEachIteratorObject);
+DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
void ForEachIteratorObject::markObjects(Managed *that, ExecutionEngine *e)
{
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 6c333b328c..c87f284288 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -74,23 +74,22 @@ struct Q_QML_EXPORT ObjectIterator
uint memberIndex;
uint flags;
- Property tmpDynamicProperty;
-
- ObjectIterator(SafeObject *scratch1, SafeObject *scratch2, const ObjectRef o, uint flags);
+ ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags);
ObjectIterator(Scope &scope, const ObjectRef o, uint flags);
- Property *next(StringRef name, uint *index, PropertyAttributes *attributes = 0);
+ void next(StringRef name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(ValueRef value);
ReturnedValue nextPropertyNameAsString(ValueRef value);
ReturnedValue nextPropertyNameAsString();
};
struct ForEachIteratorObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(ForeachIteratorObject)
ObjectIterator it;
ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o)
- : Object(ctx->engine), it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
- setVTable(&static_vtbl);
- type = Type_ForeachIteratorObject;
+ : Object(ctx->engine), it(workArea, workArea + 1,
+ o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
+ setVTable(staticVTable());
}
ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); }
@@ -98,7 +97,7 @@ struct ForEachIteratorObject: Object {
protected:
static void markObjects(Managed *that, ExecutionEngine *e);
- SafeObject workArea[2];
+ Value workArea[2];
};
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 7ca790b970..51d6b8d414 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -72,12 +72,12 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(ObjectCtor);
+DEFINE_OBJECT_VTABLE(ObjectCtor);
ObjectCtor::ObjectCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("Object"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
@@ -105,9 +105,9 @@ ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
void ObjectPrototype::init(ExecutionEngine *v4, ObjectRef ctor)
{
Scope scope(v4);
- ScopedObject o(scope);
+ ScopedObject o(scope, this);
- ctor->defineReadonlyProperty(v4->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(v4->id_prototype, o);
ctor->defineReadonlyProperty(v4->id_length, Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
@@ -134,9 +134,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, ObjectRef ctor)
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
Scoped<String> id_proto(scope, v4->id___proto__);
- Property *p = insertMember(StringRef(v4->id___proto__), Attr_Accessor|Attr_NotEnumerable);
- p->setGetter(v4->newBuiltinFunction(v4->rootContext, id_proto, method_get_proto)->getPointer());
- p->setSetter(v4->newBuiltinFunction(v4->rootContext, id_proto, method_set_proto)->getPointer());
+ Property p = Property::fromAccessor(v4->newBuiltinFunction(v4->rootContext, id_proto, method_get_proto)->getPointer(),
+ v4->newBuiltinFunction(v4->rootContext, id_proto, method_set_proto)->getPointer());
+ insertMember(StringRef(v4->id___proto__), p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
@@ -157,7 +157,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (!O)
return ctx->throwTypeError();
- if (O->isNonStrictArgumentsObject)
+ if (ArgumentsObject::isNonStrictArgumentsObject(O.getPointer()))
Scoped<ArgumentsObject>(scope, O)->fullyCreate();
ScopedValue v(scope, ctx->argument(1));
@@ -239,12 +239,13 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
while (1) {
uint index;
PropertyAttributes attrs;
- Property *pd = it.next(name, &index, &attrs);
- if (!pd)
+ Property pd;
+ it.next(name, &index, &pd, &attrs);
+ if (attrs.isEmpty())
break;
Property n;
PropertyAttributes nattrs;
- val = o->getValue(pd, attrs);
+ val = o->getValue(&pd, attrs);
toPropertyDescriptor(ctx, val, &n, &nattrs);
if (scope.engine->hasException)
return Encode::undefined();
@@ -271,10 +272,12 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
o->internalClass = o->internalClass->sealed();
- o->ensureArrayAttributes();
- for (uint i = 0; i < o->arrayDataLen; ++i) {
- if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
- o->arrayAttributes[i].setConfigurable(false);
+ if (o->arrayData) {
+ ArrayData::ensureAttributes(o.getPointer());
+ for (uint i = 0; i < o->arrayData->alloc; ++i) {
+ if (!o->arrayData->isEmpty(i))
+ o->arrayData->attrs[i].setConfigurable(false);
+ }
}
return o.asReturnedValue();
@@ -287,19 +290,21 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- if (o->isNonStrictArgumentsObject)
+ if (ArgumentsObject::isNonStrictArgumentsObject(o.getPointer()))
Scoped<ArgumentsObject>(scope, o)->fullyCreate();
o->extensible = false;
o->internalClass = o->internalClass->frozen();
- o->ensureArrayAttributes();
- for (uint i = 0; i < o->arrayDataLen; ++i) {
- if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
- o->arrayAttributes[i].setConfigurable(false);
- if (o->arrayAttributes[i].isData())
- o->arrayAttributes[i].setWritable(false);
+ if (o->arrayData) {
+ ArrayData::ensureAttributes(o.getPointer());
+ for (uint i = 0; i < o->arrayData->alloc; ++i) {
+ if (!o->arrayData->isEmpty(i))
+ o->arrayData->attrs[i].setConfigurable(false);
+ if (o->arrayData->attrs[i].isData())
+ o->arrayData->attrs[i].setWritable(false);
+ }
}
return o.asReturnedValue();
}
@@ -328,15 +333,16 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
if (o->internalClass != o->internalClass->sealed())
return Encode(false);
- if (!o->arrayDataLen)
+ if (!o->arrayData || !o->arrayData->length())
return Encode(true);
- if (!o->arrayAttributes)
+ if (o->arrayData->length() && !o->arrayData->attrs)
return Encode(false);
- for (uint i = 0; i < o->arrayDataLen; ++i) {
- if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
- if (o->arrayAttributes[i].isConfigurable())
+ for (uint i = 0; i < o->arrayData->alloc; ++i) {
+ // ### Fix for sparse arrays
+ if (!o->arrayData->isEmpty(i))
+ if (o->arrayData->attributes(i).isConfigurable())
return Encode(false);
}
@@ -356,15 +362,16 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
if (o->internalClass != o->internalClass->frozen())
return Encode(false);
- if (!o->arrayDataLen)
+ if (!o->arrayData->length())
return Encode(true);
- if (!o->arrayAttributes)
+ if (o->arrayData->length() && !o->arrayData->attrs)
return Encode(false);
- for (uint i = 0; i < o->arrayDataLen; ++i) {
- if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
- if (o->arrayAttributes[i].isConfigurable() || o->arrayAttributes[i].isWritable())
+ for (uint i = 0; i < o->arrayData->alloc; ++i) {
+ // ### Fix for sparse arrays
+ if (!o->arrayData->isEmpty(i))
+ if (o->arrayData->attributes(i).isConfigurable() || o->arrayData->attributes(i).isWritable())
return Encode(false);
}
@@ -448,7 +455,7 @@ ReturnedValue ObjectPrototype::method_hasOwnProperty(CallContext *ctx)
Scoped<Object> O(scope, ctx->callData->thisObject, Scoped<Object>::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- bool r = O->__getOwnProperty__(P) != 0;
+ bool r = O->hasOwnProperty(P);
if (!r)
r = !O->query(P).isEmpty();
return Encode(r);
@@ -494,14 +501,14 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
return ctx->throwTypeError();
Scope scope(ctx);
- Scoped<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
-
Scoped<FunctionObject> f(scope, ctx->argument(1));
if (!f)
return ctx->throwTypeError();
+ Scoped<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
Scoped<Object> o(scope, ctx->callData->thisObject);
if (!o) {
if (!ctx->callData->thisObject.isUndefined())
@@ -509,7 +516,9 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
o = ctx->engine->globalObject;
}
- Property pd = Property::fromAccessor(f.getPointer(), 0);
+ Property pd;
+ pd.value = f;
+ pd.set = Primitive::emptyValue();
o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor);
return Encode::undefined();
}
@@ -520,14 +529,14 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
return ctx->throwTypeError();
Scope scope(ctx);
- Scoped<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
-
Scoped<FunctionObject> f(scope, ctx->argument(1));
if (!f)
return ctx->throwTypeError();
+ Scoped<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
Scoped<Object> o(scope, ctx->callData->thisObject);
if (!o) {
if (!ctx->callData->thisObject.isUndefined())
@@ -535,7 +544,9 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
o = ctx->engine->globalObject;
}
- Property pd = Property::fromAccessor(0, f.getPointer());
+ Property pd;
+ pd.value = Primitive::emptyValue();
+ pd.set = f;
o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor);
return Encode::undefined();
}
@@ -586,23 +597,21 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
}
attrs->clear();
- desc->setGetter(0);
- desc->setSetter(0);
+ desc->value = Primitive::emptyValue();
+ desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->__hasProperty__(ctx->engine->id_enumerable))
+ if (o->hasProperty(ctx->engine->id_enumerable))
attrs->setEnumerable((tmp = o->get(ctx->engine->id_enumerable))->toBoolean());
- if (o->__hasProperty__(ctx->engine->id_configurable))
+ if (o->hasProperty(ctx->engine->id_configurable))
attrs->setConfigurable((tmp = o->get(ctx->engine->id_configurable))->toBoolean());
- if (o->__hasProperty__(ctx->engine->id_get)) {
+ if (o->hasProperty(ctx->engine->id_get)) {
ScopedValue get(scope, o->get(ctx->engine->id_get));
FunctionObject *f = get->asFunctionObject();
- if (f) {
- desc->setGetter(f);
- } else if (get->isUndefined()) {
- desc->setGetter((FunctionObject *)0x1);
+ if (f || get->isUndefined()) {
+ desc->value = get;
} else {
ctx->throwTypeError();
return;
@@ -610,13 +619,11 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->__hasProperty__(ctx->engine->id_set)) {
+ if (o->hasProperty(ctx->engine->id_set)) {
ScopedValue set(scope, o->get(ctx->engine->id_set));
FunctionObject *f = set->asFunctionObject();
- if (f) {
- desc->setSetter(f);
- } else if (set->isUndefined()) {
- desc->setSetter((FunctionObject *)0x1);
+ if (f || set->isUndefined()) {
+ desc->set = set;
} else {
ctx->throwTypeError();
return;
@@ -624,7 +631,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->__hasProperty__(ctx->engine->id_writable)) {
+ if (o->hasProperty(ctx->engine->id_writable)) {
if (attrs->isAccessor()) {
ctx->throwTypeError();
return;
@@ -634,7 +641,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
desc->value = Primitive::undefinedValue();
}
- if (o->__hasProperty__(ctx->engine->id_value)) {
+ if (o->hasProperty(ctx->engine->id_value)) {
if (attrs->isAccessor()) {
ctx->throwTypeError();
return;
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 0bd8072db8..2b9974be06 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -51,7 +51,7 @@ namespace QV4 {
struct ObjectCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
ObjectCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *that, CallData *callData);
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
new file mode 100644
index 0000000000..72e3651757
--- /dev/null
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4persistent_p.h"
+#include "qv4mm_p.h"
+
+using namespace QV4;
+
+PersistentValue::PersistentValue(const ValueRef val)
+ : d(new PersistentValuePrivate(val.asReturnedValue()))
+{
+}
+
+PersistentValue::PersistentValue(ReturnedValue val)
+ : d(new PersistentValuePrivate(val))
+{
+}
+
+PersistentValue::PersistentValue(const PersistentValue &other)
+ : d(other.d)
+{
+ if (d)
+ d->ref();
+}
+
+PersistentValue &PersistentValue::operator=(const PersistentValue &other)
+{
+ if (d == other.d)
+ return *this;
+
+ // the memory manager cleans up those with a refcount of 0
+
+ if (d)
+ d->deref();
+ d = other.d;
+ if (d)
+ d->ref();
+
+ return *this;
+}
+
+PersistentValue &PersistentValue::operator =(const ValueRef other)
+{
+ if (!d) {
+ d = new PersistentValuePrivate(other.asReturnedValue());
+ return *this;
+ }
+ d = d->detach(other.asReturnedValue());
+ return *this;
+}
+
+PersistentValue &PersistentValue::operator =(ReturnedValue other)
+{
+ if (!d) {
+ d = new PersistentValuePrivate(other);
+ return *this;
+ }
+ d = d->detach(other);
+ return *this;
+}
+
+PersistentValue::~PersistentValue()
+{
+ if (d)
+ d->deref();
+}
+
+WeakValue::WeakValue(const ValueRef val)
+ : d(new PersistentValuePrivate(val.asReturnedValue(), /*engine*/0, /*weak*/true))
+{
+}
+
+WeakValue::WeakValue(const WeakValue &other)
+ : d(other.d)
+{
+ if (d)
+ d->ref();
+}
+
+WeakValue::WeakValue(ReturnedValue val)
+ : d(new PersistentValuePrivate(val, /*engine*/0, /*weak*/true))
+{
+}
+
+WeakValue &WeakValue::operator=(const WeakValue &other)
+{
+ if (d == other.d)
+ return *this;
+
+ // the memory manager cleans up those with a refcount of 0
+
+ if (d)
+ d->deref();
+ d = other.d;
+ if (d)
+ d->ref();
+
+ return *this;
+}
+
+WeakValue &WeakValue::operator =(const ValueRef other)
+{
+ if (!d) {
+ d = new PersistentValuePrivate(other.asReturnedValue(), /*engine*/0, /*weak*/true);
+ return *this;
+ }
+ d = d->detach(other.asReturnedValue(), /*weak*/true);
+ return *this;
+}
+
+WeakValue &WeakValue::operator =(const ReturnedValue &other)
+{
+ if (!d) {
+ d = new PersistentValuePrivate(other, /*engine*/0, /*weak*/true);
+ return *this;
+ }
+ d = d->detach(other, /*weak*/true);
+ return *this;
+}
+
+
+WeakValue::~WeakValue()
+{
+ if (d)
+ d->deref();
+}
+
+void WeakValue::markOnce(ExecutionEngine *e)
+{
+ if (!d)
+ return;
+ d->value.mark(e);
+}
+
+PersistentValuePrivate::PersistentValuePrivate(ReturnedValue v, ExecutionEngine *e, bool weak)
+ : refcount(1)
+ , weak(weak)
+ , engine(e)
+ , prev(0)
+ , next(0)
+{
+ value.val = v;
+ init();
+}
+
+void PersistentValuePrivate::init()
+{
+ if (!engine) {
+ Managed *m = value.asManaged();
+ if (!m)
+ return;
+
+ engine = m->engine();
+ }
+ if (engine && !prev) {
+ PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues;
+
+ prev = listRoot;
+ next = *listRoot;
+ *prev = this;
+ if (next)
+ next->prev = &this->next;
+ }
+}
+
+PersistentValuePrivate::~PersistentValuePrivate()
+{
+}
+
+void PersistentValuePrivate::removeFromList()
+{
+ if (prev) {
+ if (next)
+ next->prev = prev;
+ *prev = next;
+ next = 0;
+ prev = 0;
+ }
+}
+
+void PersistentValuePrivate::deref()
+{
+ // if engine is not 0, they are registered with the memory manager
+ // and will get cleaned up in the next gc run
+ if (!--refcount) {
+ removeFromList();
+ delete this;
+ }
+}
+
+PersistentValuePrivate *PersistentValuePrivate::detach(const QV4::ReturnedValue val, bool weak)
+{
+ if (refcount == 1) {
+ value.val = val;
+
+ Managed *m = value.asManaged();
+ if (!prev) {
+ if (m) {
+ ExecutionEngine *engine = m->engine();
+ if (engine) {
+ PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues;
+ prev = listRoot;
+ next = *listRoot;
+ *prev = this;
+ if (next)
+ next->prev = &this->next;
+ }
+ }
+ } else if (!m)
+ removeFromList();
+
+ return this;
+ }
+ --refcount;
+ return new PersistentValuePrivate(val, engine, weak);
+}
+
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
new file mode 100644
index 0000000000..21f37f3d96
--- /dev/null
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4PERSISTENT_H
+#define QV4PERSISTENT_H
+
+#include "qv4value_inl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate
+{
+ PersistentValuePrivate(ReturnedValue v, ExecutionEngine *engine = 0, bool weak = false);
+ virtual ~PersistentValuePrivate();
+ Value value;
+ uint refcount;
+ bool weak;
+ QV4::ExecutionEngine *engine;
+ PersistentValuePrivate **prev;
+ PersistentValuePrivate *next;
+
+ void init();
+ void removeFromList();
+ void ref() { ++refcount; }
+ void deref();
+ PersistentValuePrivate *detach(const ReturnedValue value, bool weak = false);
+
+ bool checkEngine(QV4::ExecutionEngine *otherEngine) {
+ if (!engine) {
+ Q_ASSERT(!value.isObject());
+ engine = otherEngine;
+ }
+ return (engine == otherEngine);
+ }
+};
+
+class Q_QML_EXPORT PersistentValue
+{
+public:
+ PersistentValue() : d(0) {}
+ PersistentValue(const PersistentValue &other);
+ PersistentValue &operator=(const PersistentValue &other);
+
+ PersistentValue(const ValueRef val);
+ PersistentValue(ReturnedValue val);
+ template<typename T>
+ PersistentValue(Returned<T> *obj);
+ PersistentValue(const ManagedRef obj);
+ PersistentValue &operator=(const ValueRef other);
+ PersistentValue &operator=(const ScopedValue &other);
+ PersistentValue &operator =(ReturnedValue other);
+ template<typename T>
+ PersistentValue &operator=(Returned<T> *obj);
+ PersistentValue &operator=(const ManagedRef obj);
+ ~PersistentValue();
+
+ ReturnedValue value() const {
+ return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue());
+ }
+
+ ExecutionEngine *engine() {
+ if (!d)
+ return 0;
+ if (d->engine)
+ return d->engine;
+ Managed *m = d->value.asManaged();
+ return m ? m->engine() : 0;
+ }
+
+ bool isUndefined() const { return !d || d->value.isUndefined(); }
+ bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); }
+ void clear() {
+ *this = PersistentValue();
+ }
+
+private:
+ friend struct ValueRef;
+ PersistentValuePrivate *d;
+};
+
+class Q_QML_EXPORT WeakValue
+{
+public:
+ WeakValue() : d(0) {}
+ WeakValue(const ValueRef val);
+ WeakValue(const WeakValue &other);
+ WeakValue(ReturnedValue val);
+ template<typename T>
+ WeakValue(Returned<T> *obj);
+ WeakValue &operator=(const WeakValue &other);
+ WeakValue &operator=(const ValueRef other);
+ WeakValue &operator =(const ReturnedValue &other);
+ template<typename T>
+ WeakValue &operator=(Returned<T> *obj);
+
+ ~WeakValue();
+
+ ReturnedValue value() const {
+ return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue());
+ }
+
+ ExecutionEngine *engine() {
+ if (!d)
+ return 0;
+ if (d->engine)
+ return d->engine;
+ Managed *m = d->value.asManaged();
+ return m ? m->engine() : 0;
+ }
+
+ bool isUndefined() const { return !d || d->value.isUndefined(); }
+ bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); }
+ void clear() {
+ *this = WeakValue();
+ }
+
+ void markOnce(ExecutionEngine *e);
+
+private:
+ friend struct ValueRef;
+ PersistentValuePrivate *d;
+};
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
new file mode 100644
index 0000000000..69efbfdee3
--- /dev/null
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4profiling_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QV4;
+using namespace QV4::Profiling;
+
+FunctionCallProperties FunctionCall::resolve() const
+{
+ FunctionCallProperties props = {
+ m_start,
+ m_end,
+ m_function->name.toQString(),
+ m_function->compilationUnit->fileName(),
+ m_function->compiledFunction->location.line,
+ m_function->compiledFunction->location.column
+ };
+ return props;
+}
+
+
+Profiler::Profiler() : enabled(false)
+{
+ static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
+ Q_UNUSED(metatype);
+ m_timer.start();
+}
+
+struct FunctionCallComparator {
+ bool operator()(const FunctionCallProperties &p1, const FunctionCallProperties &p2)
+ { return p1.start < p2.start; }
+};
+
+void Profiler::stopProfiling()
+{
+ enabled = false;
+ reportData();
+}
+
+void Profiler::reportData()
+{
+ QList<FunctionCallProperties> resolved;
+ resolved.reserve(m_data.size());
+ FunctionCallComparator comp;
+ foreach (const FunctionCall &call, m_data) {
+ FunctionCallProperties props = call.resolve();
+ resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props);
+ }
+ emit dataReady(resolved);
+}
+
+void Profiler::startProfiling()
+{
+ if (!enabled) {
+ m_data.clear();
+ enabled = true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
new file mode 100644
index 0000000000..6869b3134d
--- /dev/null
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4PROFILING_H
+#define QV4PROFILING_H
+
+#include "qv4global_p.h"
+#include "qv4engine_p.h"
+#include "qv4function_p.h"
+
+#include <QElapsedTimer>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Profiling {
+
+struct FunctionCallProperties {
+ qint64 start;
+ qint64 end;
+ QString name;
+ QString file;
+ int line;
+ int column;
+};
+
+class FunctionCall {
+public:
+
+ FunctionCall() : m_function(0), m_start(0), m_end(0)
+ { Q_ASSERT_X(false, Q_FUNC_INFO, "Cannot construct a function call without function"); }
+
+ FunctionCall(Function *function, qint64 start, qint64 end) :
+ m_function(function), m_start(start), m_end(end)
+ { m_function->compilationUnit->ref(); }
+
+ FunctionCall(const FunctionCall &other) :
+ m_function(other.m_function), m_start(other.m_start), m_end(other.m_end)
+ { m_function->compilationUnit->ref(); }
+
+ ~FunctionCall()
+ { m_function->compilationUnit->deref(); }
+
+ FunctionCall &operator=(const FunctionCall &other) {
+ if (&other != this) {
+ if (m_function)
+ m_function->compilationUnit->deref();
+ m_function = other.m_function;
+ m_start = other.m_start;
+ m_end = other.m_end;
+ m_function->compilationUnit->ref();
+ }
+ return *this;
+ }
+
+ FunctionCallProperties resolve() const;
+
+private:
+
+ Function *m_function;
+ qint64 m_start;
+ qint64 m_end;
+};
+
+#define Q_V4_PROFILE(engine, ctx, function)\
+ ((engine->profiler && engine->profiler->enabled) ?\
+ Profiling::FunctionCallProfiler::profileCall(engine->profiler, ctx, function) :\
+ function->code(ctx, function->codeData))
+
+class Q_QML_EXPORT Profiler : public QObject {
+ Q_OBJECT
+ Q_DISABLE_COPY(Profiler)
+public:
+ Profiler();
+
+ bool enabled;
+
+public slots:
+ void stopProfiling();
+ void startProfiling();
+ void reportData();
+ void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
+
+signals:
+ void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &);
+
+private:
+ QElapsedTimer m_timer;
+ QVector<FunctionCall> m_data;
+
+ friend class FunctionCallProfiler;
+};
+
+class FunctionCallProfiler {
+ Q_DISABLE_COPY(FunctionCallProfiler)
+public:
+
+ // It's enough to ref() the function in the destructor as it will probably not disappear while
+ // it's executing ...
+ FunctionCallProfiler(Profiler *profiler, Function *function) :
+ profiler(profiler), function(function), startTime(profiler->m_timer.nsecsElapsed())
+ {}
+
+ ~FunctionCallProfiler()
+ {
+ profiler->m_data.append(FunctionCall(function, startTime, profiler->m_timer.nsecsElapsed()));
+ }
+
+ static ReturnedValue profileCall(Profiler *profiler, ExecutionContext *ctx, Function *function)
+ {
+ FunctionCallProfiler callProfiler(profiler, function);
+ return function->code(ctx, function->codeData);
+ }
+
+ Profiler *profiler;
+ Function *function;
+ qint64 startTime;
+};
+
+
+} // namespace Profiling
+} // namespace QV4
+
+Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>)
+
+#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 9763de5adf..aceb6022f8 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -42,7 +42,7 @@
#define QV4PROPERTYDESCRIPTOR_H
#include "qv4global_p.h"
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -52,13 +52,8 @@ namespace QV4 {
struct FunctionObject;
struct Property {
- union {
- Value value;
- struct {
- FunctionObject *get;
- FunctionObject *set;
- };
- };
+ Value value;
+ Value set;
// Section 8.10
inline void fullyPopulated(PropertyAttributes *attrs) {
@@ -67,10 +62,10 @@ struct Property {
}
if (attrs->type() == PropertyAttributes::Accessor) {
attrs->clearWritable();
- if (get == (FunctionObject *)0x1)
- get = 0;
- if (set == (FunctionObject *)0x1)
- set = 0;
+ if (value.isEmpty())
+ value = Primitive::undefinedValue();
+ if (set.isEmpty())
+ set = Primitive::undefinedValue();
}
attrs->resolve();
}
@@ -82,8 +77,8 @@ struct Property {
}
static inline Property fromAccessor(FunctionObject *getter, FunctionObject *setter) {
Property pd;
- pd.get = getter;
- pd.set = setter;
+ pd.value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter));
+ pd.set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter));
return pd;
}
@@ -96,10 +91,10 @@ struct Property {
inline bool isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const;
inline void merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs);
- inline FunctionObject *getter() const { return get; }
- inline FunctionObject *setter() const { return set; }
- inline void setGetter(FunctionObject *g) { get = g; }
- inline void setSetter(FunctionObject *s) { set = s; }
+ inline FunctionObject *getter() const { return reinterpret_cast<FunctionObject *>(value.asManaged()); }
+ inline FunctionObject *setter() const { return reinterpret_cast<FunctionObject *>(set.asManaged()); }
+ inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
+ inline void setSetter(FunctionObject *s) { set = Primitive::fromManaged(reinterpret_cast<Managed *>(s)); }
};
inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const
@@ -115,9 +110,9 @@ inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &
if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other.value))
return false;
if (attrs.type() == PropertyAttributes::Accessor) {
- if (get != other.get)
+ if (value.asManaged() != other.value.asManaged())
return false;
- if (set != other.set)
+ if (set.asManaged() != other.set.asManaged())
return false;
}
return true;
@@ -133,10 +128,10 @@ inline void Property::merge(PropertyAttributes &attrs, const Property &other, Pr
attrs.setWritable(otherAttrs.isWritable());
if (otherAttrs.type() == PropertyAttributes::Accessor) {
attrs.setType(PropertyAttributes::Accessor);
- if (other.get)
- get = (other.get == (FunctionObject *)0x1) ? 0 : other.get;
- if (other.set)
- set = (other.set == (FunctionObject *)0x1) ? 0 : other.set;
+ if (!other.value.isEmpty())
+ value = other.value;
+ if (!other.set.isEmpty())
+ set = other.set;
} else if (otherAttrs.type() == PropertyAttributes::Data){
attrs.setType(PropertyAttributes::Data);
value = other.value;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e40875dff3..7f4ac22377 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -241,7 +241,7 @@ QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
: Object(engine)
, m_object(object)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
Scope scope(engine);
ScopedObject protectThis(scope, this);
@@ -695,42 +695,39 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, StringRef name)
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(engine);
QQmlPropertyData local;
if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local)
- || name->equals(const_cast<SafeString &>(that->m_destroy)) || name->equals(engine->id_toString))
+ || name->equals(const_cast<StringValue &>(that->m_destroy)) || name->equals(engine->id_toString))
return QV4::Attr_Data;
else
return QV4::Object::query(m, name);
}
-Property *QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes)
{
name = (String *)0;
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- if (!that->m_object)
- return QV4::Object::advanceIterator(m, it, name, index, attributes);
-
- const QMetaObject *mo = that->m_object->metaObject();
- const int propertyCount = mo->propertyCount();
- if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()));
- ++it->arrayIndex;
- if (attributes)
+ if (that->m_object) {
+ const QMetaObject *mo = that->m_object->metaObject();
+ const int propertyCount = mo->propertyCount();
+ if (it->arrayIndex < static_cast<uint>(propertyCount)) {
+ name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()));
+ ++it->arrayIndex;
*attributes = QV4::Attr_Data;
- it->tmpDynamicProperty.value = that->get(name);
- return &it->tmpDynamicProperty;
- }
- const int methodCount = mo->methodCount();
- if (it->arrayIndex < static_cast<uint>(propertyCount + methodCount)) {
- name = that->engine()->newString(QString::fromUtf8(mo->method(it->arrayIndex - propertyCount).name()));
- ++it->arrayIndex;
- if (attributes)
+ p->value = that->get(name);
+ return;
+ }
+ const int methodCount = mo->methodCount();
+ if (it->arrayIndex < static_cast<uint>(propertyCount + methodCount)) {
+ name = that->engine()->newString(QString::fromUtf8(mo->method(it->arrayIndex - propertyCount).name()));
+ ++it->arrayIndex;
*attributes = QV4::Attr_Data;
- it->tmpDynamicProperty.value = that->get(name);
- return &it->tmpDynamicProperty;
+ p->value = that->get(name);
+ return;
+ }
}
- return QV4::Object::advanceIterator(m, it, name, index, attributes);
+ QV4::Object::advanceIterator(m, it, name, index, p, attributes);
}
namespace QV4 {
@@ -1120,7 +1117,7 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType,
return args[0].toValue(engine);
} else if (returnType != QMetaType::Void) {
-
+
CallArgument arg;
arg.initAsType(returnType);
@@ -1140,7 +1137,7 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType,
}
/*!
- Returns the match score for converting \a actual to be of type \a conversionType. A
+ Returns the match score for converting \a actual to be of type \a conversionType. A
zero score means "perfect match" whereas a higher score is worse.
The conversion table is copied out of the \l QScript::callQtMethod() function.
@@ -1314,7 +1311,7 @@ static const QQmlPropertyData * RelatedMethod(QObject *object,
QMetaMethod method = mo->method(current->overrideIndex);
dummy.load(method);
-
+
// Look for overloaded methods
QByteArray methodName = method.name();
for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
@@ -1348,7 +1345,7 @@ static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &d
int *args = 0;
QVarLengthArray<int, 9> dummy;
- args = QQmlPropertyCache::methodParameterTypes(object, data.coreIndex, dummy,
+ args = QQmlPropertyCache::methodParameterTypes(object, data.coreIndex, dummy,
&unknownTypeError);
if (!args) {
@@ -1374,13 +1371,13 @@ static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &d
/*!
Resolve the overloaded method to call. The algorithm works conceptually like this:
1. Resolve the set of overloads it is *possible* to call.
- Impossible overloads include those that have too many parameters or have parameters
- of unknown type.
- 2. Filter the set of overloads to only contain those with the closest number of
+ Impossible overloads include those that have too many parameters or have parameters
+ of unknown type.
+ 2. Filter the set of overloads to only contain those with the closest number of
parameters.
For example, if we are called with 3 parameters and there are 2 overloads that
take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
- 3. Find the best remaining overload based on its match score.
+ 3. Find the best remaining overload based on its match score.
If two or more overloads have the same match score, call the last one. The match
score is constructed by adding the matchScore() result for each of the parameters.
*/
@@ -1431,7 +1428,7 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
continue; // We already have a better option
int methodMatchScore = 0;
- for (int ii = 0; ii < methodArgumentCount; ++ii)
+ for (int ii = 0; ii < methodArgumentCount; ++ii)
methodMatchScore += MatchScore((v = callArgs->args[ii]), methodArgTypes[ii]);
if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
@@ -1453,7 +1450,7 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
const QQmlPropertyData *candidate = &data;
while (candidate) {
- error += QLatin1String("\n ") +
+ error += QLatin1String("\n ") +
QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).methodSignature().constData());
candidate = RelatedMethod(object, candidate, dummy);
}
@@ -1488,7 +1485,7 @@ void CallArgument::cleanup()
jsonObjectPtr->~QJsonObject();
} else if (type == QMetaType::QJsonValue) {
jsonValuePtr->~QJsonValue();
- }
+ }
}
void *CallArgument::dataPtr()
@@ -1595,7 +1592,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
if (array) {
Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
- uint32_t length = array->arrayLength();
+ uint32_t length = array->getLength();
for (uint32_t ii = 0; ii < length; ++ii) {
QObject *o = 0;
qobjectWrapper = array->getIndexed(ii);
@@ -1692,10 +1689,9 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
QList<QObject *> &list = *qlistPtr;
QV4::Scoped<ArrayObject> array(scope, v4->newArrayObject());
array->arrayReserve(list.count());
- for (int ii = 0; ii < list.count(); ++ii) {
- array->arrayData[ii].value = QV4::QObjectWrapper::wrap(v4, list.at(ii));
- array->arrayDataLen = ii + 1;
- }
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < list.count(); ++ii)
+ array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(v4, list.at(ii))));
array->setArrayLengthUnchecked(list.count());
return array.asReturnedValue();
} else if (type == qMetaTypeId<QQmlV4Handle>()) {
@@ -1709,7 +1705,8 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
} else if (type == -1 || type == qMetaTypeId<QVariant>()) {
QVariant value = *qvariantPtr;
QV4::ScopedValue rv(scope, engine->fromVariant(value));
- if (QV4::Referenced<QObjectWrapper> qobjectWrapper = rv->asRef<QV4::QObjectWrapper>()) {
+ QV4::QObjectWrapperRef qobjectWrapper = rv;
+ if (!!qobjectWrapper) {
if (QObject *object = qobjectWrapper->object())
QQmlData::get(object, true)->setImplicitDestructible();
}
@@ -1729,7 +1726,7 @@ QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index
, m_object(object)
, m_index(index)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
subtype = WrappedQtMethod;
m_qmlGlobal = qmlGlobal;
}
@@ -1843,17 +1840,17 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
}
}
-DEFINE_MANAGED_VTABLE(QObjectMethod);
+DEFINE_OBJECT_VTABLE(QObjectMethod);
QmlSignalHandler::QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex)
: Object(engine)
, m_object(object)
, m_signalIndex(signalIndex)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
-DEFINE_MANAGED_VTABLE(QmlSignalHandler);
+DEFINE_OBJECT_VTABLE(QmlSignalHandler);
void MultiplyWrappedQObjectMap::insert(QObject *key, Object *value)
{
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 07de1933c5..ca38c5b0dc 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -62,7 +62,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -77,7 +77,7 @@ struct QObjectSlotDispatcher;
struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
enum RevisionMode { IgnoreRevision, CheckRevision };
@@ -111,12 +111,12 @@ private:
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
QPointer<QObject> m_object;
- SafeString m_destroy;
+ StringValue m_destroy;
static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
static void put(Managed *m, const StringRef name, const ValueRef value);
static PropertyAttributes query(const Managed *, StringRef name);
- static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Managed *that, QV4::ExecutionEngine *e);
static void collectDeletables(Managed *m, GCDeletable **deletable);
static void destroy(Managed *that)
@@ -130,7 +130,7 @@ private:
struct QObjectMethod : public QV4::FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
enum { DestroyMethod = -1, ToStringMethod = -2 };
@@ -161,7 +161,7 @@ private:
struct QmlSignalHandler : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex);
@@ -200,6 +200,8 @@ private Q_SLOTS:
void removeDestroyedObject(QObject*);
};
+DEFINE_REF(QObjectWrapper, Object);
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 41ff9f9741..e5490cffd1 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -99,8 +99,6 @@ RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase,
, m_ignoreCase(ignoreCase)
, m_multiLine(multiline)
{
- type = Type_RegExpObject;
-
if (!engine)
return;
const char* error = 0;
@@ -136,71 +134,3 @@ void RegExp::markObjects(Managed *that, ExecutionEngine *e)
Q_UNUSED(that);
Q_UNUSED(e);
}
-
-ReturnedValue RegExp::get(Managed *, const StringRef, bool *)
-{
- return Encode::undefined();
-}
-
-ReturnedValue RegExp::getIndexed(Managed *m, uint index, bool *hasProperty)
-{
- Q_UNUSED(m);
- Q_UNUSED(index);
- Q_UNUSED(hasProperty);
-
- return Encode::undefined();
-}
-
-void RegExp::put(Managed *m, const StringRef name, const ValueRef value)
-{
- Q_UNUSED(m);
- Q_UNUSED(name);
- Q_UNUSED(value);
-}
-
-void RegExp::putIndexed(Managed *m, uint index, const ValueRef value)
-{
- Q_UNUSED(m);
- Q_UNUSED(index);
- Q_UNUSED(value);
-}
-
-PropertyAttributes RegExp::query(const Managed *m, StringRef name)
-{
- Q_UNUSED(m);
- Q_UNUSED(name);
-
- return Attr_Invalid;
-}
-
-PropertyAttributes RegExp::queryIndexed(const Managed *m, uint index)
-{
- Q_UNUSED(m);
- Q_UNUSED(index);
-
- return Attr_Invalid;
-}
-
-bool RegExp::deleteProperty(Managed *, const StringRef)
-{
- return false;
-}
-
-bool RegExp::deleteIndexedProperty(Managed *m, uint index)
-{
- Q_UNUSED(m);
- Q_UNUSED(index);
-
- return false;
-}
-
-Property *RegExp::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
-{
- Q_UNUSED(m);
- Q_UNUSED(it);
- Q_UNUSED(name);
- Q_UNUSED(index);
- Q_UNUSED(attributes);
-
- return 0;
-}
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 9041ff2ef4..1bcc2c6f5a 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -93,7 +93,8 @@ public:
class RegExp : public Managed
{
- Q_MANAGED
+ V4_MANAGED
+ Q_MANAGED_TYPE(RegExp)
public:
static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
~RegExp();
@@ -111,15 +112,6 @@ public:
protected:
static void destroy(Managed *that);
static void markObjects(Managed *that, QV4::ExecutionEngine *e);
- static ReturnedValue get(Managed *, const StringRef, bool *);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
- static void putIndexed(Managed *m, uint index, const ValueRef value);
- static PropertyAttributes query(const Managed *m, StringRef name);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static bool deleteProperty(Managed *, const StringRef);
- static bool deleteIndexedProperty(Managed *m, uint index);
- static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
private:
friend class RegExpCache;
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 0ebad2f781..74c8a2d35e 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -69,17 +69,18 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn
using namespace QV4;
-DEFINE_MANAGED_VTABLE(RegExpObject);
+DEFINE_OBJECT_VTABLE(RegExpObject);
RegExpObject::RegExpObject(InternalClass *ic)
: Object(ic)
, value(RegExp::create(ic->engine, QString(), false, false))
, global(false)
{
+ Q_ASSERT(internalClass->vtable == staticVTable());
init(ic->engine);
}
-RegExpObject::RegExpObject(ExecutionEngine *engine, Referenced<RegExp> value, bool global)
+RegExpObject::RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global)
: Object(engine->regExpClass)
, value(value)
, global(global)
@@ -142,15 +143,14 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re)
void RegExpObject::init(ExecutionEngine *engine)
{
- setVTable(&static_vtbl);
- type = Type_RegExpObject;
+ setVTable(staticVTable());
Scope scope(engine);
ScopedObject protectThis(scope, this);
ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex")));
- Property *lastIndexProperty = insertMember(lastIndex, Attr_NotEnumerable|Attr_NotConfigurable);
- lastIndexProperty->value = Primitive::fromInt32(0);
+ ScopedValue v(scope, Primitive::fromInt32(0));
+ insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable);
if (!this->value)
return;
@@ -162,7 +162,6 @@ void RegExpObject::init(ExecutionEngine *engine)
p.replace('/', QLatin1String("\\/"));
}
- ScopedValue v(scope);
defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p)));
defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global));
defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value->ignoreCase()));
@@ -232,12 +231,12 @@ uint RegExpObject::flags() const
return f;
}
-DEFINE_MANAGED_VTABLE(RegExpCtor);
+DEFINE_OBJECT_VTABLE(RegExpCtor);
RegExpCtor::RegExpCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("RegExp"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
clearLastMatch();
}
@@ -387,11 +386,12 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
Scoped<ArrayObject> array(scope, ctx->engine->newArrayObject(ctx->engine->regExpExecArrayClass));
int len = r->value->captureCount();
array->arrayReserve(len);
+ ScopedValue v(scope);
for (int i = 0; i < len; ++i) {
int start = matchOffsets[i * 2];
int end = matchOffsets[i * 2 + 1];
- array->arrayData[i].value = (start != -1 && end != -1) ? ctx->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
- array->arrayDataLen = i + 1;
+ v = (start != -1 && end != -1) ? ctx->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result);
@@ -433,7 +433,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
return ctx->throwTypeError();
ScopedCallData callData(scope, ctx->callData->argc);
- memcpy(callData->args, ctx->callData->args, ctx->callData->argc*sizeof(SafeValue));
+ memcpy(callData->args, ctx->callData->args, ctx->callData->argc*sizeof(Value));
Scoped<RegExpObject> re(scope, ctx->engine->regExpCtor.asFunctionObject()->construct(callData));
@@ -457,7 +457,7 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
- ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->arrayLength() - 1) : Encode::undefined());
+ ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
return ctx->engine->newString(QString())->asReturnedValue();
return result.asReturnedValue();
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index f112ad804d..1b408749d3 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -66,7 +66,8 @@ namespace QV4 {
class RegExp;
struct RegExpObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(RegExpObject)
// needs to be compatible with the flags in qv4jsir_p.h
enum Flags {
RegExp_Global = 0x01,
@@ -83,7 +84,7 @@ struct RegExpObject: Object {
Property *lastIndexProperty(ExecutionContext *ctx);
bool global;
- RegExpObject(ExecutionEngine *engine, Referenced<RegExp> value, bool global);
+ RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global);
RegExpObject(ExecutionEngine *engine, const QRegExp &re);
~RegExpObject() {}
@@ -100,14 +101,15 @@ protected:
static void markObjects(Managed *that, ExecutionEngine *e);
};
+DEFINE_REF(RegExp, Object);
struct RegExpCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
RegExpCtor(ExecutionContext *scope);
- SafeValue lastMatch;
- SafeString lastInput;
+ Value lastMatch;
+ StringValue lastInput;
int lastMatchStart;
int lastMatchEnd;
void clearLastMatch();
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 011607f0ba..f89a51fd85 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -338,7 +338,7 @@ QV4::ReturnedValue __qmljs_in(ExecutionContext *ctx, const ValueRef left, const
ScopedString s(scope, left->toString(ctx));
if (scope.hasException())
return Encode::undefined();
- bool r = right->objectValue()->__hasProperty__(s);
+ bool r = right->objectValue()->hasProperty(s);
return Encode(r);
}
@@ -383,8 +383,8 @@ ReturnedValue __qmljs_object_default_value(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- SafeString *meth1 = &engine->id_toString;
- SafeString *meth2 = &engine->id_valueOf;
+ StringValue *meth1 = &engine->id_toString;
+ StringValue *meth2 = &engine->id_valueOf;
if (typeHint == NUMBER_HINT)
qSwap(meth1, meth2);
@@ -589,12 +589,10 @@ ReturnedValue __qmljs_get_element(ExecutionContext *ctx, const ValueRef object,
}
if (idx < UINT_MAX) {
- uint pidx = o->propertyIndexFromArrayIndex(idx);
- if (pidx < UINT_MAX) {
- if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
- if (!o->arrayData[pidx].value.isEmpty())
- return o->arrayData[pidx].value.asReturnedValue();
- }
+ if (!o->arrayData->hasAttributes()) {
+ ScopedValue v(scope, o->arrayData->get(idx));
+ if (!v->isEmpty())
+ return v->asReturnedValue();
}
return o->getIndexed(idx);
@@ -615,32 +613,10 @@ void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const Val
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
- uint pidx = o->propertyIndexFromArrayIndex(idx);
- if (pidx < UINT_MAX) {
- if (o->arrayAttributes && !o->arrayAttributes[pidx].isEmpty() && !o->arrayAttributes[pidx].isWritable()) {
- if (ctx->strictMode)
- ctx->throwTypeError();
- return;
- }
-
- Property *p = o->arrayData + pidx;
- if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
- p->value = *value;
- return;
- }
-
- if (o->arrayAttributes[pidx].isAccessor()) {
- FunctionObject *setter = p->setter();
- if (!setter) {
- if (ctx->strictMode)
- ctx->throwTypeError();
- return;
- }
-
- ScopedCallData callData(scope, 1);
- callData->thisObject = o;
- callData->args[0] = *value;
- setter->call(callData);
+ if (o->arrayType() == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
+ if (s && idx < s->len && !s->data[idx].isEmpty()) {
+ s->data[idx] = value;
return;
}
}
@@ -753,10 +729,10 @@ Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y)
QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef l, const QV4::ValueRef r)
{
TRACE2(l, r);
- if (QV4::Value::integerCompatible(*l, *r))
+ if (l->isInteger() && r->isInteger())
return l->integerValue() > r->integerValue();
- if (QV4::Value::bothDouble(*l, *r))
- return l->doubleValue() > r->doubleValue();
+ if (l->isNumber() && r->isNumber())
+ return l->asDouble() > r->asDouble();
if (l->isString() && r->isString())
return r->stringValue()->compare(l->stringValue());
@@ -776,10 +752,10 @@ QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef l, const QV4::ValueRef r)
QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef l, const QV4::ValueRef r)
{
TRACE2(l, r);
- if (QV4::Value::integerCompatible(*l, *r))
+ if (l->isInteger() && r->isInteger())
return l->integerValue() < r->integerValue();
- if (QV4::Value::bothDouble(*l, *r))
- return l->doubleValue() < r->doubleValue();
+ if (l->isNumber() && r->isNumber())
+ return l->asDouble() < r->asDouble();
if (l->isString() && r->isString())
return l->stringValue()->compare(r->stringValue());
@@ -799,10 +775,10 @@ QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef l, const QV4::ValueRef r)
QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef l, const QV4::ValueRef r)
{
TRACE2(l, r);
- if (QV4::Value::integerCompatible(*l, *r))
+ if (l->isInteger() && r->isInteger())
return l->integerValue() >= r->integerValue();
- if (QV4::Value::bothDouble(*l, *r))
- return l->doubleValue() >= r->doubleValue();
+ if (l->isNumber() && r->isNumber())
+ return l->asDouble() >= r->asDouble();
if (l->isString() && r->isString())
return !l->stringValue()->compare(r->stringValue());
@@ -822,10 +798,10 @@ QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef l, const QV4::ValueRef r)
QV4::Bool __qmljs_cmp_le(const QV4::ValueRef l, const QV4::ValueRef r)
{
TRACE2(l, r);
- if (QV4::Value::integerCompatible(*l, *r))
+ if (l->isInteger() && r->isInteger())
return l->integerValue() <= r->integerValue();
- if (QV4::Value::bothDouble(*l, *r))
- return l->doubleValue() <= r->doubleValue();
+ if (l->isNumber() && r->isNumber())
+ return l->asDouble() <= r->asDouble();
if (l->isString() && r->isString())
return !r->stringValue()->compare(l->stringValue());
@@ -918,12 +894,12 @@ ReturnedValue __qmljs_call_property(ExecutionContext *context, const StringRef n
ReturnedValue __qmljs_call_property_lookup(ExecutionContext *context, uint index, CallDataRef callData)
{
Lookup *l = context->lookups + index;
- SafeValue v;
+ Value v;
v = l->getter(l, callData->thisObject);
- if (!v.isManaged())
+ if (!v.isObject())
return context->throwTypeError();
- return v.managed()->call(callData);
+ return v.objectValue()->call(callData);
}
ReturnedValue __qmljs_call_element(ExecutionContext *context, const ValueRef index, CallDataRef callData)
@@ -945,10 +921,10 @@ ReturnedValue __qmljs_call_element(ExecutionContext *context, const ValueRef ind
ReturnedValue __qmljs_call_value(ExecutionContext *context, const ValueRef func, CallDataRef callData)
{
- if (!func->isManaged())
+ if (!func->isObject())
return context->throwTypeError();
- return func->managed()->call(callData);
+ return func->objectValue()->call(callData);
}
@@ -1006,12 +982,12 @@ ReturnedValue __qmljs_construct_property(ExecutionContext *context, const String
ReturnedValue __qmljs_construct_property_lookup(ExecutionContext *context, uint index, CallDataRef callData)
{
Lookup *l = context->lookups + index;
- SafeValue v;
+ Value v;
v = l->getter(l, callData->thisObject);
- if (!v.isManaged())
+ if (!v.isObject())
return context->throwTypeError();
- return v.managed()->construct(callData);
+ return v.objectValue()->construct(callData);
}
@@ -1118,8 +1094,14 @@ void __qmljs_builtin_define_property(ExecutionContext *ctx, const ValueRef objec
assert(o);
uint idx = name->asArrayIndex();
- Property *pd = (idx != UINT_MAX) ? o->arrayInsert(idx) : o->insertMember(name, Attr_Data);
- pd->value = val ? *val : Primitive::undefinedValue();
+ if (idx != UINT_MAX) {
+ if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
+ o->initSparseArray();
+ o->arraySet(idx, val);
+ } else {
+ ScopedValue v(scope, val ? *val : Primitive::undefinedValue());
+ o->insertMember(name, v);
+ }
}
ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values, uint length)
@@ -1127,16 +1109,9 @@ ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values,
Scope scope(ctx);
Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
- // ### FIXME: We need to allocate the array data to avoid crashes other places
- // This should rather be done when required
- a->arrayReserve(length);
if (length) {
- a->arrayDataLen = length;
- Property *pd = a->arrayData;
- for (uint i = 0; i < length; ++i) {
- pd->value = values[i];
- ++pd;
- }
+ a->arrayReserve(length);
+ a->arrayPut(0, values, length);
a->setArrayLengthUnchecked(length);
}
return a.asReturnedValue();
@@ -1149,9 +1124,14 @@ void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef
Q_ASSERT(!!o);
uint idx = name->asArrayIndex();
- Property *pd = (idx != UINT_MAX) ? o->arrayInsert(idx, Attr_Accessor) : o->insertMember(name, Attr_Accessor);
- pd->setGetter(getter ? getter->asFunctionObject() : 0);
- pd->setSetter(setter ? setter->asFunctionObject() : 0);
+ Property pd;
+ pd.value = getter;
+ pd.set = setter;
+ if (idx != UINT_MAX) {
+ o->arraySet(idx, pd, Attr_Accessor);
+ } else {
+ o->insertMember(name, pd, Attr_Accessor);
+ }
}
ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId)
@@ -1164,9 +1144,9 @@ ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx,
if (klass->propertyData[i].isData())
o->memberData[i].value = *args++;
else {
- o->memberData[i].setGetter(args->asFunctionObject());
+ o->memberData[i].value = *args;
args++;
- o->memberData[i].setSetter(args->asFunctionObject());
+ o->memberData[i].set = *args;
args++;
}
}
@@ -1330,7 +1310,7 @@ QV4::ReturnedValue __qmljs_get_qml_singleton(QV4::NoThrowContext *ctx, const QV4
void __qmljs_builtin_convert_this_to_object(ExecutionContext *ctx)
{
- SafeValue *t = &ctx->callData->thisObject;
+ Value *t = &ctx->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 9524b2459c..1c34e554c3 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -42,9 +42,10 @@
#define QMLJS_RUNTIME_H
#include "qv4global_p.h"
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4math_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4context_p.h"
#include <QtCore/QString>
#include <QtCore/qnumeric.h>
@@ -141,7 +142,7 @@ QV4::ExecutionContext *__qmljs_builtin_pop_scope(QV4::ExecutionContext *ctx);
ReturnedValue __qmljs_builtin_unwind_exception(ExecutionContext *ctx);
void __qmljs_builtin_declare_var(QV4::ExecutionContext *ctx, bool deletable, const QV4::StringRef name);
void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::StringRef name, QV4::ValueRef val);
-QV4::ReturnedValue __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::Value *values, uint length);
+QV4::ReturnedValue __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, Value *values, uint length);
void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::StringRef name, const QV4::ValueRef getter, const QV4::ValueRef setter);
QV4::ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId);
QV4::ReturnedValue __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx);
@@ -305,12 +306,7 @@ inline QV4::ReturnedValue __qmljs_compl(const QV4::ValueRef value)
{
TRACE1(value);
- int n;
- if (value->integerCompatible())
- n = value->int_32;
- else
- n = value->toInt32();
-
+ int n = value->toInt32();
return Encode((int)~n);
}
@@ -327,9 +323,6 @@ inline ReturnedValue __qmljs_bit_or(const QV4::ValueRef left, const QV4::ValueRe
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return Encode(left->integerValue() | right->integerValue());
-
int lval = left->toInt32();
int rval = right->toInt32();
return Encode(lval | rval);
@@ -339,9 +332,6 @@ inline ReturnedValue __qmljs_bit_xor(const QV4::ValueRef left, const QV4::ValueR
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return Encode(left->integerValue() ^ right->integerValue());
-
int lval = left->toInt32();
int rval = right->toInt32();
return Encode(lval ^ rval);
@@ -351,9 +341,6 @@ inline ReturnedValue __qmljs_bit_and(const QV4::ValueRef left, const QV4::ValueR
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return Encode(left->integerValue() & right->integerValue());
-
int lval = left->toInt32();
int rval = right->toInt32();
return Encode(lval & rval);
@@ -363,11 +350,10 @@ inline QV4::ReturnedValue __qmljs_add(QV4::ExecutionContext *ctx, const QV4::Val
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
+ if (left->isInteger() && right->isInteger())
return add_int32(left->integerValue(), right->integerValue()).asReturnedValue();
-
- if (QV4::Value::bothDouble(*left, *right))
- return QV4::Primitive::fromDouble(left->doubleValue() + right->doubleValue()).asReturnedValue();
+ if (left->isNumber() && right->isNumber())
+ return QV4::Primitive::fromDouble(left->asDouble() + right->asDouble()).asReturnedValue();
return __qmljs_add_helper(ctx, left, right);
}
@@ -376,11 +362,12 @@ inline QV4::ReturnedValue __qmljs_sub(const QV4::ValueRef left, const QV4::Value
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
+ if (left->isInteger() && right->isInteger())
return sub_int32(left->integerValue(), right->integerValue()).asReturnedValue();
- double lval = __qmljs_to_number(left);
- double rval = __qmljs_to_number(right);
+ double lval = left->isNumber() ? left->asDouble() : left->toNumberImpl();
+ double rval = right->isNumber() ? right->asDouble() : right->toNumberImpl();
+
return QV4::Primitive::fromDouble(lval - rval).asReturnedValue();
}
@@ -388,11 +375,12 @@ inline QV4::ReturnedValue __qmljs_mul(const QV4::ValueRef left, const QV4::Value
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
+ if (left->isInteger() && right->isInteger())
return mul_int32(left->integerValue(), right->integerValue()).asReturnedValue();
- double lval = __qmljs_to_number(left);
- double rval = __qmljs_to_number(right);
+ double lval = left->isNumber() ? left->asDouble() : left->toNumberImpl();
+ double rval = right->isNumber() ? right->asDouble() : right->toNumberImpl();
+
return QV4::Primitive::fromDouble(lval * rval).asReturnedValue();
}
@@ -400,8 +388,8 @@ inline QV4::ReturnedValue __qmljs_div(const QV4::ValueRef left, const QV4::Value
{
TRACE2(left, right);
- double lval = __qmljs_to_number(left);
- double rval = __qmljs_to_number(right);
+ double lval = left->toNumber();
+ double rval = right->toNumber();
return QV4::Primitive::fromDouble(lval / rval).asReturnedValue();
}
@@ -424,11 +412,8 @@ inline QV4::ReturnedValue __qmljs_shl(const QV4::ValueRef left, const QV4::Value
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return Encode((int)(left->integerValue() << ((uint(right->integerValue()) & 0x1f))));
-
int lval = left->toInt32();
- unsigned rval = right->toUInt32() & 0x1f;
+ int rval = right->toInt32() & 0x1f;
return Encode((int)(lval << rval));
}
@@ -436,9 +421,6 @@ inline QV4::ReturnedValue __qmljs_shr(const QV4::ValueRef left, const QV4::Value
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return Encode((int)(left->integerValue() >> ((uint(right->integerValue()) & 0x1f))));
-
int lval = left->toInt32();
unsigned rval = right->toUInt32() & 0x1f;
return Encode((int)(lval >> rval));
@@ -448,14 +430,9 @@ inline QV4::ReturnedValue __qmljs_ushr(const QV4::ValueRef left, const QV4::Valu
{
TRACE2(left, right);
- uint res;
- if (QV4::Value::integerCompatible(*left, *right)) {
- res = uint(left->integerValue()) >> (uint(right->integerValue()) & 0x1f);
- } else {
- unsigned lval = left->toUInt32();
- unsigned rval = right->toUInt32() & 0x1f;
- res = lval >> rval;
- }
+ unsigned lval = left->toUInt32();
+ unsigned rval = right->toUInt32() & 0x1f;
+ uint res = lval >> rval;
return Encode(res);
}
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 2c71a36a3d..5d471ab4fb 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -41,8 +41,9 @@
#ifndef QV4SCOPEDVALUE_P_H
#define QV4SCOPEDVALUE_P_H
-#include "qv4context_p.h"
-#include "qv4value_def_p.h"
+#include "qv4engine_p.h"
+#include "qv4value_p.h"
+#include "qv4persistent_p.h"
QT_BEGIN_NAMESPACE
@@ -54,15 +55,7 @@ namespace QV4 {
struct ScopedValue;
struct Scope {
- explicit Scope(ExecutionContext *ctx)
- : engine(ctx->engine)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
- {
- mark = engine->jsStackTop;
- }
-
+ inline explicit Scope(ExecutionContext *ctx);
explicit Scope(ExecutionEngine *e)
: engine(e)
#ifndef QT_NO_DEBUG
@@ -75,13 +68,13 @@ struct Scope {
~Scope() {
#ifndef QT_NO_DEBUG
Q_ASSERT(engine->jsStackTop >= mark);
- memset(mark, 0, (engine->jsStackTop - mark)*sizeof(SafeValue));
+ memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
engine->jsStackTop = mark;
}
- SafeValue *alloc(int nValues) {
- SafeValue *ptr = engine->jsStackTop;
+ Value *alloc(int nValues) {
+ Value *ptr = engine->jsStackTop;
engine->jsStackTop += nValues;
#ifndef QT_NO_DEBUG
size += nValues;
@@ -94,7 +87,7 @@ struct Scope {
}
ExecutionEngine *engine;
- SafeValue *mark;
+ Value *mark;
#ifndef QT_NO_DEBUG
mutable int size;
#endif
@@ -178,17 +171,17 @@ struct ScopedValue
return *this;
}
- SafeValue *operator->() {
+ Value *operator->() {
return ptr;
}
- const SafeValue *operator->() const {
+ const Value *operator->() const {
return ptr;
}
ReturnedValue asReturnedValue() const { return ptr->val; }
- SafeValue *ptr;
+ Value *ptr;
};
template<typename T>
@@ -234,7 +227,7 @@ struct Scoped
Scoped(const Scope &scope, const Value &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine->currentContext(), v);
+ ptr->val = value_convert<T>(scope.engine, v);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -281,7 +274,7 @@ struct Scoped
Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine->currentContext(), QV4::Value::fromReturnedValue(v));
+ ptr->val = value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -339,7 +332,7 @@ struct Scoped
#endif
}
- SafeValue *ptr;
+ Value *ptr;
};
struct CallData
@@ -356,14 +349,14 @@ struct CallData
return i < argc ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
}
- SafeValue thisObject;
- SafeValue args[1];
+ Value thisObject;
+ Value args[1];
};
struct ScopedCallData {
ScopedCallData(Scope &scope, int argc)
{
- int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue);
+ int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value);
ptr = reinterpret_cast<CallData *>(scope.engine->stackPush(size));
ptr->tag = QV4::Value::Integer_Type;
ptr->argc = argc;
@@ -385,141 +378,10 @@ struct ScopedCallData {
CallData *ptr;
};
-struct ValueRef {
- ValueRef(const ScopedValue &v)
- : ptr(v.ptr) {}
- template <typename T>
- ValueRef(const Scoped<T> &v)
- : ptr(v.ptr) {}
- ValueRef(const PersistentValue &v)
- : ptr(&v.d->value) {}
- ValueRef(PersistentValuePrivate *p)
- : ptr(&p->value) {}
- ValueRef(SafeValue &v) { ptr = &v; }
- // Important: Do NOT add a copy constructor to this class
- // adding a copy constructor actually changes the calling convention, ie.
- // is not even binary compatible. Adding it would break assumptions made
- // in the jit'ed code.
- ValueRef &operator=(const ScopedValue &o)
- { *ptr = *o.ptr; return *this; }
- ValueRef &operator=(const ValueRef &o)
- { *ptr = *o.ptr; return *this; }
- ValueRef &operator=(const Value &v)
- { *ptr = v; return *this; }
- ValueRef &operator=(const ReturnedValue &v) {
- ptr->val = v;
- return *this;
- }
- template <typename T>
- ValueRef &operator=(Returned<T> *v) {
- ptr->val = v->asReturnedValue();
- return *this;
- }
-
- operator const Value *() const {
- return ptr;
- }
- const Value *operator->() const {
- return ptr;
- }
-
- operator Value *() {
- return ptr;
- }
- SafeValue *operator->() {
- return ptr;
- }
-
- static ValueRef fromRawValue(Value *v) {
- return ValueRef(v);
- }
- static const ValueRef fromRawValue(const Value *v) {
- return ValueRef(const_cast<Value *>(v));
- }
-
- ReturnedValue asReturnedValue() const { return ptr->val; }
-
- // ### get rid of this one!
- ValueRef(Value *v) { ptr = reinterpret_cast<SafeValue *>(v); }
-private:
- SafeValue *ptr;
-};
-
-
-template<typename T>
-struct Referenced {
- // Important: Do NOT add a copy constructor to this class
- // adding a copy constructor actually changes the calling convention, ie.
- // is not even binary compatible. Adding it would break assumptions made
- // in the jit'ed code.
- Referenced(const Scoped<T> &v)
- : ptr(v.ptr) {}
- Referenced(Safe<T> &v) { ptr = &v; }
- Referenced(SafeValue &v) {
- ptr = value_cast<T>(v) ? &v : 0;
- }
-
- Referenced &operator=(const Referenced &o)
- { *ptr = *o.ptr; return *this; }
- Referenced &operator=(T *t)
- {
-#if QT_POINTER_SIZE == 4
- ptr->tag = Value::Managed_Type;
-#endif
- ptr->m = t;
- return *this;
- }
- Referenced &operator=(Returned<T> *t) {
-#if QT_POINTER_SIZE == 4
- ptr->tag = Value::Managed_Type;
-#endif
- ptr->m = t->getPointer();
- return *this;
- }
-
- operator const T *() const {
- return ptr ? static_cast<T*>(ptr->managed()) : 0;
- }
- const T *operator->() const {
- return static_cast<T*>(ptr->managed());
- }
-
- operator T *() {
- return ptr ? static_cast<T*>(ptr->managed()) : 0;
- }
- T *operator->() {
- return static_cast<T*>(ptr->managed());
- }
-
- T *getPointer() const {
- return static_cast<T *>(ptr->managed());
- }
- ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); }
- operator Returned<T> *() const { return ptr ? Returned<T>::create(getPointer()) : 0; }
-
- bool operator==(const Referenced<T> &other) {
- if (ptr == other.ptr)
- return true;
- return ptr && other.ptr && ptr->m == other.ptr->m;
- }
- bool operator!=(const Referenced<T> &other) {
- if (ptr == other.ptr)
- return false;
- return !ptr || ptr->m != other.ptr->m;
- }
- bool operator!() const { return !ptr || !ptr->managed(); }
-
- static Referenced null() { return Referenced(Null); }
- bool isNull() const { return !ptr; }
-private:
- enum _Null { Null };
- Referenced(_Null) { ptr = 0; }
- SafeValue *ptr;
-};
-typedef Referenced<String> StringRef;
-typedef Referenced<Object> ObjectRef;
-typedef Referenced<FunctionObject> FunctionObjectRef;
+struct StringRef;
+struct ObjectRef;
+struct FunctionObjectRef;
template<typename T>
inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v)
@@ -569,51 +431,6 @@ private:
CallData *ptr;
};
-struct Encode {
- static ReturnedValue undefined() {
- return quint64(Value::Undefined_Type) << Value::Tag_Shift;
- }
- static ReturnedValue null() {
- return quint64(Value::_Null_Type) << Value::Tag_Shift;
- }
-
- Encode(bool b) {
- val = (quint64(Value::_Boolean_Type) << Value::Tag_Shift) | (uint)b;
- }
- Encode(double d) {
- Value v;
- v.setDouble(d);
- val = v.val;
- }
- Encode(int i) {
- val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
- }
- Encode(uint i) {
- if (i <= INT_MAX) {
- val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | i;
- } else {
- Value v;
- v.setDouble(i);
- val = v.val;
- }
- }
- Encode(ReturnedValue v) {
- val = v;
- }
-
- template<typename T>
- Encode(Returned<T> *t) {
- val = t->getPointer()->asReturnedValue();
- }
-
- operator ReturnedValue() const {
- return val;
- }
- quint64 val;
-private:
- Encode(void *);
-};
-
template <typename T>
inline Value &Value::operator=(Returned<T> *t)
@@ -622,81 +439,68 @@ inline Value &Value::operator=(Returned<T> *t)
return *this;
}
-inline SafeValue &SafeValue::operator =(const ScopedValue &v)
+inline Value &Value::operator =(const ScopedValue &v)
{
val = v.ptr->val;
return *this;
}
template<typename T>
-inline SafeValue &SafeValue::operator=(Returned<T> *t)
-{
- val = t->getPointer()->asReturnedValue();
- return *this;
-}
-
-template<typename T>
-inline SafeValue &SafeValue::operator=(const Scoped<T> &t)
+inline Value &Value::operator=(const Scoped<T> &t)
{
val = t.ptr->val;
return *this;
}
-inline SafeValue &SafeValue::operator=(const ValueRef v)
+inline Value &Value::operator=(const ValueRef v)
{
val = v.asReturnedValue();
return *this;
}
template<typename T>
-inline Returned<T> *SafeValue::as()
+inline Returned<T> *Value::as()
{
return Returned<T>::create(value_cast<T>(*this));
}
-template<typename T> inline
-Referenced<T> SafeValue::asRef()
-{
- return Referenced<T>(*this);
-}
-
template<typename T>
-inline Safe<T> &Safe<T>::operator =(T *t)
+inline TypedValue<T> &TypedValue<T>::operator =(T *t)
{
val = t->asReturnedValue();
return *this;
}
template<typename T>
-inline Safe<T> &Safe<T>::operator =(const Scoped<T> &v)
+inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
{
val = v.ptr->val;
return *this;
}
template<typename T>
-inline Safe<T> &Safe<T>::operator=(Returned<T> *t)
+inline TypedValue<T> &TypedValue<T>::operator=(Returned<T> *t)
{
val = t->getPointer()->asReturnedValue();
return *this;
}
-template<typename T>
-inline Safe<T> &Safe<T>::operator =(const Referenced<T> &v)
-{
- val = v.asReturnedValue();
- return *this;
-}
+//template<typename T>
+//inline TypedValue<T> &TypedValue<T>::operator =(const ManagedRef<T> &v)
+//{
+// val = v.asReturnedValue();
+// return *this;
+//}
template<typename T>
-inline Safe<T> &Safe<T>::operator=(const Safe<T> &t)
+inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
{
val = t.val;
return *this;
}
template<typename T>
-inline Returned<T> * Safe<T>::ret() const
+inline Returned<T> * TypedValue<T>::ret() const
{
return Returned<T>::create(static_cast<T *>(managed()));
}
@@ -713,9 +517,8 @@ PersistentValue::PersistentValue(Returned<T> *obj)
{
}
-template<typename T>
-inline PersistentValue::PersistentValue(const Referenced<T> obj)
- : d(new PersistentValuePrivate(*obj.ptr))
+inline PersistentValue::PersistentValue(const ManagedRef obj)
+ : d(new PersistentValuePrivate(obj.asReturnedValue()))
{
}
@@ -725,12 +528,15 @@ inline PersistentValue &PersistentValue::operator=(Returned<T> *obj)
return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
}
-template<typename T>
-inline PersistentValue &PersistentValue::operator=(const Referenced<T> obj)
+inline PersistentValue &PersistentValue::operator=(const ManagedRef obj)
{
- return operator=(*obj.ptr);
+ return operator=(obj.asReturnedValue());
}
+inline PersistentValue &PersistentValue::operator=(const ScopedValue &other)
+{
+ return operator=(other.asReturnedValue());
+}
template<typename T>
inline WeakValue::WeakValue(Returned<T> *obj)
@@ -744,10 +550,53 @@ inline WeakValue &WeakValue::operator=(Returned<T> *obj)
return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
}
-inline ReturnedValue CallContext::argument(int i) {
- return i < callData->argc ? callData->args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
+inline ValueRef::ValueRef(const ScopedValue &v)
+ : ptr(v.ptr)
+{}
+
+template <typename T>
+inline ValueRef::ValueRef(const Scoped<T> &v)
+ : ptr(v.ptr)
+{}
+
+inline ValueRef::ValueRef(const PersistentValue &v)
+ : ptr(&v.d->value)
+{}
+
+inline ValueRef::ValueRef(PersistentValuePrivate *p)
+ : ptr(&p->value)
+{}
+
+inline ValueRef &ValueRef::operator=(const ScopedValue &o)
+{
+ *ptr = *o.ptr;
+ return *this;
+}
+
+
+inline Value *extractValuePointer(const ScopedValue &v)
+{
+ return v.ptr;
}
+template<typename T>
+Value *extractValuePointer(const Scoped<T> &v)
+{
+ return v.ptr;
+}
+
+struct ScopedProperty
+{
+ ScopedProperty(Scope &scope)
+ {
+ property = reinterpret_cast<Property*>(scope.alloc(sizeof(Property) / sizeof(Value)));
+ }
+
+ Property *operator->() { return property; }
+ operator const Property &() { return *property; }
+
+ Property *property;
+};
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 4fd0569627..cb5424b0ee 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -67,7 +67,7 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec
{
Q_ASSERT(scope->inUse);
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
function = f;
function->compilationUnit->ref();
needsActivation = function->needsActivation();
@@ -88,7 +88,7 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml)
{
Q_ASSERT(scope->inUse);
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
function = 0;
needsActivation = false;
@@ -129,18 +129,18 @@ void QmlBindingWrapper::markObjects(Managed *m, ExecutionEngine *e)
wrapper->qmlContext->mark(e);
}
-DEFINE_MANAGED_VTABLE(QmlBindingWrapper);
+DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
struct CompilationUnitHolder : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
: Object(engine)
, unit(unit)
{
unit->ref();
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
~CompilationUnitHolder()
{
@@ -155,7 +155,7 @@ struct CompilationUnitHolder : public QV4::Object
QV4::CompiledData::CompilationUnit *unit;
};
-DEFINE_MANAGED_VTABLE(CompilationUnitHolder);
+DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit)
: line(0), column(0), scope(v4->rootContext), strictMode(false), inheritContext(true), parsed(false)
@@ -168,7 +168,7 @@ Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit
Q_ASSERT(vmFunction);
Scope valueScope(v4);
ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
- compilationUnitHolder = holder;
+ compilationUnitHolder = holder.asReturnedValue();
} else
vmFunction = 0;
}
@@ -191,7 +191,7 @@ void Script::parse()
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
- V4IR::Module module(v4->debugger != 0);
+ IR::Module module(v4->debugger != 0);
QQmlJS::Engine ee, *engine = &ee;
Lexer lexer(engine);
@@ -236,7 +236,7 @@ void Script::parse()
QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
- compilationUnitHolder = holder;
+ compilationUnitHolder = holder.asReturnedValue();
}
if (!vmFunction) {
@@ -308,7 +308,7 @@ CompiledData::CompilationUnit *Script::precompile(ExecutionEngine *engine, const
using namespace QQmlJS;
using namespace QQmlJS::AST;
- QQmlJS::V4IR::Module module(engine->debugger != 0);
+ IR::Module module(engine->debugger != 0);
QQmlJS::Engine ee;
QQmlJS::Lexer lexer(&ee);
@@ -356,7 +356,7 @@ CompiledData::CompilationUnit *Script::precompile(ExecutionEngine *engine, const
}
Compiler::JSUnitGenerator jsGenerator(&module);
- QScopedPointer<QQmlJS::EvalInstructionSelection> isel(engine->iselFactory->create(QQmlEnginePrivate::get(engine), engine->executableAllocator, &module, &jsGenerator));
+ QScopedPointer<EvalInstructionSelection> isel(engine->iselFactory->create(QQmlEnginePrivate::get(engine), engine->executableAllocator, &module, &jsGenerator));
isel->setUseFastLookups(false);
return isel->compile();
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 8e11eddb8f..8afdb6126f 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -54,7 +54,7 @@ namespace QV4 {
struct ExecutionContext;
struct QmlBindingWrapper : FunctionObject {
- Q_MANAGED
+ V4_OBJECT
QmlBindingWrapper(ExecutionContext *scope, Function *f, ObjectRef qml);
// Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 8b0e31cb71..a82dcffbca 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -165,34 +165,33 @@ template <> bool convertValueToElement(const ValueRef value)
template <typename Container>
class QQmlSequence : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(QmlSequence)
public:
QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : QV4::Object(InternalClass::create(engine, &static_vtbl, engine->sequencePrototype.asObject()))
+ : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
, m_container(container)
, m_object(0)
, m_propertyIndex(-1)
, m_isReference(false)
{
- type = Type_QmlSequence;
- flags &= ~SimpleArray;
QV4::Scope scope(engine);
QV4::ScopedObject protectThis(scope, this);
Q_UNUSED(protectThis);
+ setArrayType(ArrayData::Custom);
init();
}
QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : QV4::Object(InternalClass::create(engine, &static_vtbl, engine->sequencePrototype.asObject()))
+ : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
, m_object(object)
, m_propertyIndex(propertyIndex)
, m_isReference(true)
{
- type = Type_QmlSequence;
- flags &= ~SimpleArray;
QV4::Scope scope(engine);
QV4::ScopedObject protectThis(scope, this);
Q_UNUSED(protectThis);
+ setArrayType(ArrayData::Custom);
loadReference();
init();
}
@@ -287,26 +286,27 @@ public:
return (signedIdx < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- Property *containerAdvanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
{
name = (String *)0;
*index = UINT_MAX;
if (m_isReference) {
- if (!m_object)
- return QV4::Object::advanceIterator(this, it, name, index, attrs);
+ if (!m_object) {
+ QV4::Object::advanceIterator(this, it, name, index, p, attrs);
+ return;
+ }
loadReference();
}
if (it->arrayIndex < static_cast<uint>(m_container.count())) {
- if (attrs)
- *attrs = QV4::Attr_Data;
*index = it->arrayIndex;
++it->arrayIndex;
- it->tmpDynamicProperty.value = convertElementToValue(engine(), m_container.at(*index));
- return &it->tmpDynamicProperty;
+ *attrs = QV4::Attr_Data;
+ p->value = convertElementToValue(engine(), m_container.at(*index));
+ return;
}
- return QV4::Object::advanceIterator(this, it, name, index, attrs);
+ QV4::Object::advanceIterator(this, it, name, index, p, attrs);
}
bool containerDeleteIndexedProperty(uint index)
@@ -469,7 +469,7 @@ public:
{
QV4::Scope scope(array->engine());
Container result;
- quint32 length = array->arrayLength();
+ quint32 length = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 i = 0; i < length; ++i)
result << convertValueToElement<typename Container::value_type>((v = array->getIndexed(i)));
@@ -510,8 +510,8 @@ private:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static Property *advanceIterator(Managed *that, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
- { return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, attrs); }
+ static void advanceIterator(Managed *that, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
+ { return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
static void destroy(Managed *that)
{
@@ -521,22 +521,22 @@ private:
typedef QQmlSequence<QStringList> QQmlQStringList;
template<>
-DEFINE_MANAGED_VTABLE(QQmlQStringList);
+DEFINE_OBJECT_VTABLE(QQmlQStringList);
typedef QQmlSequence<QList<QString> > QQmlStringList;
template<>
-DEFINE_MANAGED_VTABLE(QQmlStringList);
+DEFINE_OBJECT_VTABLE(QQmlStringList);
typedef QQmlSequence<QList<int> > QQmlIntList;
template<>
-DEFINE_MANAGED_VTABLE(QQmlIntList);
+DEFINE_OBJECT_VTABLE(QQmlIntList);
typedef QQmlSequence<QList<QUrl> > QQmlUrlList;
template<>
-DEFINE_MANAGED_VTABLE(QQmlUrlList);
+DEFINE_OBJECT_VTABLE(QQmlUrlList);
typedef QQmlSequence<QList<bool> > QQmlBoolList;
template<>
-DEFINE_MANAGED_VTABLE(QQmlBoolList);
+DEFINE_OBJECT_VTABLE(QQmlBoolList);
typedef QQmlSequence<QList<qreal> > QQmlRealList;
template<>
-DEFINE_MANAGED_VTABLE(QQmlRealList);
+DEFINE_OBJECT_VTABLE(QQmlRealList);
#define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>(#SequenceType);
SequencePrototype::SequencePrototype(InternalClass *ic)
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 54a96863df..4a5e82b688 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -56,7 +56,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4object_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index ee325db4c2..3d754389a2 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -45,7 +45,7 @@
#include <private/qqmllistmodel_p.h>
#include <private/qqmllistmodelworkeragent_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4sequenceobject_p.h>
@@ -55,13 +55,13 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-// We allow the following JavaScript types to be passed between the main and
+// We allow the following JavaScript types to be passed between the main and
// the secondary thread:
// + undefined
// + null
// + Boolean
// + String
-// + Function
+// + Function
// + Array
// + "Simple" Objects
// + Number
@@ -143,7 +143,7 @@ static inline void *popPtr(const char *&data)
return rv;
}
-// XXX TODO: Check that worker script is exception safe in the case of
+// XXX TODO: Check that worker script is exception safe in the case of
// serialization/deserialization failures
#define ALIGN(size) (((size) + 3) & ~3)
@@ -171,7 +171,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
reserve(data, utf16size + sizeof(quint32));
push(data, valueheader(WorkerString, length));
-
+
int offset = data.size();
data.resize(data.size() + utf16size);
char *buffer = data.data() + offset;
@@ -183,7 +183,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
push(data, valueheader(WorkerUndefined));
} else if (v->asArrayObject()) {
QV4::ScopedArrayObject array(scope, v);
- uint32_t length = array->arrayLength();
+ uint32_t length = array->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
return;
@@ -266,7 +266,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
// regular object
QV4::ScopedValue val(scope, *v);
QV4::ScopedArrayObject properties(scope, QV4::ObjectPrototype::getOwnPropertyNames(v4, val));
- quint32 length = properties->arrayLength();
+ quint32 length = properties->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
return;
@@ -390,8 +390,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
array->arrayReserve(seqLength);
for (quint32 ii = 0; ii < seqLength; ++ii) {
value = deserialize(data, engine);
- array->arrayData[ii].value = value.asReturnedValue();
- array->arrayDataLen = ii + 1;
+ array->arrayPut(ii, value);
}
array->setArrayLengthUnchecked(seqLength);
QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index a9f40e43cd..5ab8ae9258 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -54,7 +54,7 @@
//
#include <QtCore/qbytearray.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 3ee89d5b53..ffd1adf98b 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -53,32 +53,6 @@
using namespace QV4;
-bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) const
-{
- Scope scope(m_context);
-
- if (p1.value.isUndefined() || p1.value.isEmpty())
- return false;
- if (p2.value.isUndefined() || p2.value.isEmpty())
- return true;
- ScopedObject o(scope, m_comparefn);
- if (o) {
- Scope scope(o->engine());
- ScopedValue result(scope);
- ScopedCallData callData(scope, 2);
- callData->thisObject = Primitive::undefinedValue();
- callData->args[0] = p1.value;
- callData->args[1] = p2.value;
- result = __qmljs_call_value(m_context, m_comparefn, callData);
-
- return result->toNumber() < 0;
- }
- ScopedString p1s(scope, p1.value.toString(m_context));
- ScopedString p2s(scope, p2.value.toString(m_context));
- return p1s->toQString() < p2s->toQString();
-}
-
-
const SparseArrayNode *SparseArrayNode::nextNode() const
{
const SparseArrayNode *n = this;
@@ -245,51 +219,51 @@ void SparseArray::deleteNode(SparseArrayNode *z)
else
mostLeftNode = y->parent();
}
- } else {
- if (y->right == 0) {
+ } else if (y->right == 0) {
x = y->left;
- } else {
- y = y->right;
- while (y->left != 0)
- y = y->left;
- x = y->right;
- }
+ } else {
+ y = y->right;
+ while (y->left != 0)
+ y = y->left;
+ x = y->right;
}
if (y != z) {
- z->left->setParent(y);
- y->left = z->left;
+ // move y into the position of z
+ // adjust size_left so the keys are ok.
+ z->size_left += y->size_left;
+ SparseArrayNode *n = y->parent();
+ while (n != z) {
+ n->size_left -= y->size_left;
+ n = n->parent();
+ }
+ y->size_left = 0;
+ z->value = y->value;
+
if (y != z->right) {
x_parent = y->parent();
- if (x)
- x->setParent(y->parent());
y->parent()->left = x;
- y->right = z->right;
- z->right->setParent(y);
} else {
- x_parent = y;
+ x_parent = z;
+ z->right = x;
}
- if (root == z)
- root = y;
- else if (z->parent()->left == z)
- z->parent()->left = y;
- else
- z->parent()->right = y;
- y->setParent(z->parent());
- // Swap the colors
- SparseArrayNode::Color c = y->color();
- y->setColor(z->color());
- z->setColor(c);
- y = z;
+ if (x)
+ x->setParent(x_parent);
} else {
x_parent = y->parent();
if (x)
x->setParent(y->parent());
- if (root == z)
+ if (root == y)
root = x;
- else if (z->parent()->left == z)
- z->parent()->left = x;
- else
- z->parent()->right = x;
+ else if (y->parent()->left == y) {
+ y->parent()->left = x;
+ if (x)
+ x->size_left += y->size_left;
+ } else {
+ y->parent()->right = x;
+ if (x)
+ x->size_left += y->size_left;
+ }
+ y->size_left = 0;
}
if (y->color() != SparseArrayNode::Red) {
while (x != root && (x == 0 || x->color() == SparseArrayNode::Black)) {
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 4746498963..0bcbc805f3 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -39,16 +39,17 @@
**
****************************************************************************/
-#ifndef QV4ARRAY_H
-#define QV4ARRAY_H
+#ifndef QV4SPARSEARRAY_H
+#define QV4SPARSEARRAY_H
#include "qv4global_p.h"
#include <QtCore/qmap.h>
-#include "qv4value_p.h"
+#include "qv4value_inl_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4property_p.h"
#include <assert.h>
+//#define Q_MAP_DEBUG
#ifdef Q_MAP_DEBUG
#include <QtCore/qdebug.h>
#endif
@@ -61,21 +62,6 @@ namespace QV4 {
struct SparseArray;
-class ArrayElementLessThan
-{
-public:
- inline ArrayElementLessThan(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn)
- : m_context(context), thisObject(thisObject), m_comparefn(comparefn) {}
-
- bool operator()(const Property &v1, const Property &v2) const;
-
-private:
- ExecutionContext *m_context;
- ObjectRef thisObject;
- const ValueRef m_comparefn;
-};
-
-
struct SparseArrayNode
{
quintptr p;
@@ -182,6 +168,8 @@ public:
SparseArrayNode *findNode(uint akey) const;
+ uint nEntries() const { return numEntries; }
+
uint pop_front();
void push_front(uint at);
uint pop_back(uint len);
@@ -208,7 +196,7 @@ public:
typedef qptrdiff difference_type;
typedef int size_type;
-#ifdef Q_MAP_DEBUG
+#ifndef QT_NO_DEBUG
void dump() const;
#endif
};
@@ -281,23 +269,22 @@ inline void SparseArray::push_back(uint index, uint len)
n->value = index;
}
-#ifdef Q_MAP_DEBUG
-
-void SparseArray::dump() const
+#ifndef QT_NO_DEBUG
+inline void SparseArray::dump() const
{
- const_iterator it = begin();
+ const SparseArrayNode *it = begin();
qDebug() << "map dump:";
while (it != end()) {
- const SparseArrayNode *n = it.i;
+ const SparseArrayNode *n = it;
int depth = 0;
while (n && n != root()) {
++depth;
n = n->parent();
}
QByteArray space(4*depth, ' ');
- qDebug() << space << (it.i->color() == SparseArrayNode::Red ? "Red " : "Black") << it.i << it.i->left << it.i->right
- << it.key() << it.value();
- ++it;
+ qDebug() << space << (it->color() == SparseArrayNode::Red ? "Red " : "Black") << it << it->size_left << it->left << it->right
+ << it->key() << it->value;
+ it = it->nextNode();
}
qDebug() << "---------";
}
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index e5633eb06f..3d0328dfcf 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -101,12 +101,11 @@ static uint toArrayIndex(const char *ch, const char *end, bool *ok)
}
-const ManagedVTable String::static_vtbl =
+const ObjectVTable String::static_vtbl =
{
- call,
- construct,
- markObjects,
- destroy,
+ DEFINE_MANAGED_VTABLE_INT(String),
+ 0,
+ 0,
0 /*collectDeletables*/,
get,
getIndexed,
@@ -118,9 +117,8 @@ const ManagedVTable String::static_vtbl =
deleteIndexedProperty,
0 /*getLookup*/,
0 /*setLookup*/,
- isEqualTo,
+ 0,
0 /*advanceIterator*/,
- "String",
};
void String::destroy(Managed *that)
@@ -233,10 +231,9 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- if (o->type != Type_String)
+ if (!o->internalClass->vtable->isString)
return false;
- Q_ASSERT(t->type == Type_String);
String *that = static_cast<String *>(t);
String *other = static_cast<String *>(o);
if (that->hashValue() != other->hashValue())
@@ -257,7 +254,6 @@ String::String(ExecutionEngine *engine, const QString &text)
{
_text->ref.ref();
len = _text->size;
- type = Type_String;
subtype = StringType_Unknown;
}
@@ -267,7 +263,6 @@ String::String(ExecutionEngine *engine, String *l, String *r)
, stringHash(UINT_MAX), largestSubLength(qMax(l->largestSubLength, r->largestSubLength))
, len(l->len + r->len)
{
- type = Type_String;
subtype = StringType_Unknown;
if (!l->largestSubLength && l->len > largestSubLength)
@@ -418,3 +413,8 @@ uint String::toArrayIndex(const QString &str)
bool ok;
return ::toArrayIndex(str.constData(), str.constData() + str.length(), &ok);
}
+
+uint String::getLength(const Managed *m)
+{
+ return static_cast<const String *>(m)->length();
+}
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 64e15b04c2..ade64d1352 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -52,7 +52,13 @@ struct ExecutionEngine;
struct Identifier;
struct Q_QML_EXPORT String : public Managed {
- Q_MANAGED
+ // ### FIXME: Should this be a V4_OBJECT
+ V4_OBJECT
+ Q_MANAGED_TYPE(String)
+ enum {
+ IsString = true
+ };
+
enum StringType {
StringType_Unknown,
StringType_Regular,
@@ -60,10 +66,6 @@ struct Q_QML_EXPORT String : public Managed {
StringType_ArrayIndex
};
- String()
- : Managed(0), _text(QStringData::sharedNull()), identifier(0)
- , stringHash(UINT_MAX), largestSubLength(0), len(0)
- { type = Type_String; subtype = StringType_Unknown; }
String(ExecutionEngine *engine, const QString &text);
String(ExecutionEngine *engine, String *l, String *n);
~String() {
@@ -86,6 +88,7 @@ struct Q_QML_EXPORT String : public Managed {
return toQString() == other->toQString();
}
+
inline bool compare(const String *other) {
return toQString() < other->toQString();
}
@@ -167,6 +170,7 @@ protected:
static bool deleteProperty(Managed *, const StringRef);
static bool deleteIndexedProperty(Managed *m, uint index);
static bool isEqualTo(Managed *that, Managed *o);
+ static uint getLength(const Managed *m);
private:
QChar *recursiveAppend(QChar *ch) const;
@@ -178,11 +182,13 @@ inline String *value_cast(const Value &v) {
}
template<>
-inline ReturnedValue value_convert<String>(ExecutionContext *ctx, const Value &v)
+inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
{
- return v.toString(ctx)->asReturnedValue();
+ return v.toString(e)->asReturnedValue();
}
+DEFINE_REF(String, Managed);
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index d468fb6b83..07cdf31a03 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -75,13 +75,12 @@
using namespace QV4;
-DEFINE_MANAGED_VTABLE(StringObject);
+DEFINE_OBJECT_VTABLE(StringObject);
StringObject::StringObject(InternalClass *ic)
: Object(ic)
{
- setVTable(&static_vtbl);
- type = Type_StringObject;
+ Q_ASSERT(internalClass->vtable == staticVTable());
Scope scope(engine());
ScopedObject protectThis(scope, this);
@@ -96,8 +95,7 @@ StringObject::StringObject(InternalClass *ic)
StringObject::StringObject(ExecutionEngine *engine, const ValueRef val)
: Object(engine->stringObjectClass)
{
- setVTable(&static_vtbl);
- type = Type_StringObject;
+ setVTable(staticVTable());
Scope scope(engine);
ScopedObject protectThis(scope, this);
@@ -137,26 +135,32 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
return true;
}
-Property *StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
{
name = (String *)0;
StringObject *s = static_cast<StringObject *>(m);
uint slen = s->value.stringValue()->toQString().length();
- if (it->arrayIndex < slen) {
+ if (it->arrayIndex <= slen) {
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
- if (attrs)
- *attrs = s->arrayAttributes ? s->arrayAttributes[it->arrayIndex] : PropertyAttributes(Attr_NotWritable|Attr_NotConfigurable);
- return s->__getOwnProperty__(*index);
+ PropertyAttributes a;
+ Property *pd = s->__getOwnProperty__(*index, &a);
+ if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
+ *attrs = a;
+ *p = *pd;
+ return;
+ }
+ }
+ if (s->arrayData) {
+ it->arrayNode = s->sparseBegin();
+ // iterate until we're past the end of the string
+ while (it->arrayNode && it->arrayNode->key() < slen)
+ it->arrayNode = it->arrayNode->nextNode();
}
- it->arrayNode = s->sparseArrayBegin();
- // iterate until we're past the end of the string
- while (it->arrayNode && it->arrayNode->key() < slen)
- it->arrayNode = it->arrayNode->nextNode();
}
- return Object::advanceIterator(m, it, name, index, attrs);
+ return Object::advanceIterator(m, it, name, index, p, attrs);
}
void StringObject::markObjects(Managed *that, ExecutionEngine *e)
@@ -167,12 +171,12 @@ void StringObject::markObjects(Managed *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-DEFINE_MANAGED_VTABLE(StringCtor);
+DEFINE_OBJECT_VTABLE(StringCtor);
StringCtor::StringCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("String"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
@@ -694,18 +698,18 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
array->push_back((s = ctx->engine->newString(text.mid(offset, matchOffsets[0] - offset))));
offset = qMax(offset + 1, matchOffsets[1]);
- if (array->arrayLength() >= limit)
+ if (array->getLength() >= limit)
break;
for (int i = 1; i < re->value->captureCount(); ++i) {
uint start = matchOffsets[i * 2];
uint end = matchOffsets[i * 2 + 1];
array->push_back((s = ctx->engine->newString(text.mid(start, end - start))));
- if (array->arrayLength() >= limit)
+ if (array->getLength() >= limit)
break;
}
}
- if (array->arrayLength() < limit)
+ if (array->getLength() < limit)
array->push_back((s = ctx->engine->newString(text.mid(offset))));
} else {
QString separator = separatorValue->toString(ctx)->toQString();
@@ -720,10 +724,10 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
while ((end = text.indexOf(separator, start)) != -1) {
array->push_back((s = ctx->engine->newString(text.mid(start, end - start))));
start = end + separator.size();
- if (array->arrayLength() >= limit)
+ if (array->getLength() >= limit)
break;
}
- if (array->arrayLength() < limit && start != -1)
+ if (array->getLength() < limit && start != -1)
array->push_back((s = ctx->engine->newString(text.mid(start))));
}
return array.asReturnedValue();
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index e8e46b85e7..c38fd5b75f 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -50,9 +50,10 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct StringObject: Object {
- Q_MANAGED
+ V4_OBJECT
+ Q_MANAGED_TYPE(StringObject)
- SafeValue value;
+ Value value;
mutable Property tmpProperty;
StringObject(ExecutionEngine *engine, const ValueRef value);
@@ -62,13 +63,13 @@ struct StringObject: Object {
protected:
StringObject(InternalClass *ic);
- static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs);
+ static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs);
static void markObjects(Managed *that, ExecutionEngine *e);
};
struct StringCtor: FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
StringCtor(ExecutionContext *scope);
static ReturnedValue construct(Managed *m, CallData *callData);
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 30f7e8cdb0..a610f0b73a 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -98,6 +98,7 @@ double Value::toNumberImpl() const
case QV4::Value::Null_Type:
case QV4::Value::Boolean_Type:
case QV4::Value::Integer_Type:
+ return int_32;
default: // double
Q_UNREACHABLE();
}
@@ -262,6 +263,11 @@ double Primitive::toInteger(double number)
return std::signbit(number) ? -v : v;
}
+String *Value::toString(ExecutionEngine *e) const
+{
+ return toString(e->currentContext());
+}
+
String *Value::toString(ExecutionContext *ctx) const
{
if (isString())
@@ -276,213 +282,3 @@ Object *Value::toObject(ExecutionContext *ctx) const
return __qmljs_convert_to_object(ctx, ValueRef::fromRawValue(this))->getPointer();
}
-
-PersistentValue::PersistentValue(const ValueRef val)
- : d(new PersistentValuePrivate(val.asReturnedValue()))
-{
-}
-
-PersistentValue::PersistentValue(ReturnedValue val)
- : d(new PersistentValuePrivate(val))
-{
-}
-
-PersistentValue::PersistentValue(const PersistentValue &other)
- : d(other.d)
-{
- if (d)
- d->ref();
-}
-
-PersistentValue &PersistentValue::operator=(const PersistentValue &other)
-{
- if (d == other.d)
- return *this;
-
- // the memory manager cleans up those with a refcount of 0
-
- if (d)
- d->deref();
- d = other.d;
- if (d)
- d->ref();
-
- return *this;
-}
-
-PersistentValue &PersistentValue::operator =(const ValueRef other)
-{
- if (!d) {
- d = new PersistentValuePrivate(other.asReturnedValue());
- return *this;
- }
- d = d->detach(other.asReturnedValue());
- return *this;
-}
-
-PersistentValue &PersistentValue::operator =(ReturnedValue other)
-{
- if (!d) {
- d = new PersistentValuePrivate(other);
- return *this;
- }
- d = d->detach(other);
- return *this;
-}
-
-PersistentValue::~PersistentValue()
-{
- if (d)
- d->deref();
-}
-
-WeakValue::WeakValue(const ValueRef val)
- : d(new PersistentValuePrivate(val.asReturnedValue(), /*engine*/0, /*weak*/true))
-{
-}
-
-WeakValue::WeakValue(const WeakValue &other)
- : d(other.d)
-{
- if (d)
- d->ref();
-}
-
-WeakValue::WeakValue(ReturnedValue val)
- : d(new PersistentValuePrivate(val, /*engine*/0, /*weak*/true))
-{
-}
-
-WeakValue &WeakValue::operator=(const WeakValue &other)
-{
- if (d == other.d)
- return *this;
-
- // the memory manager cleans up those with a refcount of 0
-
- if (d)
- d->deref();
- d = other.d;
- if (d)
- d->ref();
-
- return *this;
-}
-
-WeakValue &WeakValue::operator =(const ValueRef other)
-{
- if (!d) {
- d = new PersistentValuePrivate(other.asReturnedValue(), /*engine*/0, /*weak*/true);
- return *this;
- }
- d = d->detach(other.asReturnedValue(), /*weak*/true);
- return *this;
-}
-
-WeakValue &WeakValue::operator =(const ReturnedValue &other)
-{
- if (!d) {
- d = new PersistentValuePrivate(other, /*engine*/0, /*weak*/true);
- return *this;
- }
- d = d->detach(other, /*weak*/true);
- return *this;
-}
-
-
-WeakValue::~WeakValue()
-{
- if (d)
- d->deref();
-}
-
-void WeakValue::markOnce(ExecutionEngine *e)
-{
- if (!d)
- return;
- d->value.mark(e);
-}
-
-PersistentValuePrivate::PersistentValuePrivate(ReturnedValue v, ExecutionEngine *e, bool weak)
- : refcount(1)
- , weak(weak)
- , engine(e)
- , prev(0)
- , next(0)
-{
- value.val = v;
- init();
-}
-
-void PersistentValuePrivate::init()
-{
- if (!engine) {
- Managed *m = value.asManaged();
- if (!m)
- return;
-
- engine = m->engine();
- }
- if (engine && !prev) {
- PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues;
-
- prev = listRoot;
- next = *listRoot;
- *prev = this;
- if (next)
- next->prev = &this->next;
- }
-}
-
-PersistentValuePrivate::~PersistentValuePrivate()
-{
-}
-
-void PersistentValuePrivate::removeFromList()
-{
- if (prev) {
- if (next)
- next->prev = prev;
- *prev = next;
- next = 0;
- prev = 0;
- }
-}
-
-void PersistentValuePrivate::deref()
-{
- // if engine is not 0, they are registered with the memory manager
- // and will get cleaned up in the next gc run
- if (!--refcount) {
- removeFromList();
- delete this;
- }
-}
-
-PersistentValuePrivate *PersistentValuePrivate::detach(const QV4::ReturnedValue val, bool weak)
-{
- if (refcount == 1) {
- value.val = val;
-
- Managed *m = value.asManaged();
- if (!prev) {
- if (m) {
- ExecutionEngine *engine = m->engine();
- if (engine) {
- PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues;
- prev = listRoot;
- next = *listRoot;
- *prev = this;
- if (next)
- next->prev = &this->next;
- }
- }
- } else if (!m)
- removeFromList();
-
- return this;
- }
- --refcount;
- return new PersistentValuePrivate(val, engine, weak);
-}
-
diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h
deleted file mode 100644
index cf351c125a..0000000000
--- a/src/qml/jsruntime/qv4value_def_p.h
+++ /dev/null
@@ -1,476 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QV4VALUE_DEF_P_H
-#define QV4VALUE_DEF_P_H
-
-#include <QtCore/QString>
-#include "qv4global_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-typedef uint Bool;
-
-template <typename T>
-struct Returned : private T
-{
- static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
- T *getPointer() { return this; }
- template<typename X>
- static T *getPointer(Returned<X> *x) { return x->getPointer(); }
- template<typename X>
- Returned<X> *as() { return Returned<X>::create(Returned<X>::getPointer(this)); }
- using T::asReturnedValue;
-};
-
-struct Q_QML_EXPORT Value
-{
- /*
- We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
-
- In both cases, we 8 bytes for a value and different variant of NaN boxing. A Double NaN (actually -qNaN)
- is indicated by a number that has the top 13 bits set. THe other values are usually set to 0 by the
- processor, and are thus free for us to store other data. We keep pointers in there for managed objects,
- and encode the other types using the free space given to use by the unused bits for NaN values. This also
- works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory.
-
- On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that
- will make the number a NaN. The Masks below are used for encoding the other types.
-
- On 64 bit, we xor Doubles with (0xffff8000 << 32). Thas has the effect that no doubles will get encoded
- with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These
- can be used, as the highest valid pointer on a 64 bit system is 2^48-1.
-
- If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer.
- This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set).
-
- Bit 15-17 is then used to encode other immediates.
- */
-
-
- union {
- quint64 val;
-#if QT_POINTER_SIZE == 8
- Managed *m;
- Object *o;
- String *s;
-#else
- double dbl;
-#endif
- struct {
-#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
- uint tag;
-#endif
- union {
- uint uint_32;
- int int_32;
-#if QT_POINTER_SIZE == 4
- Managed *m;
- Object *o;
- String *s;
-#endif
- };
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- uint tag;
-#endif
- };
- };
-
-#if QT_POINTER_SIZE == 4
- enum Masks {
- NaN_Mask = 0x7ff80000,
- NotDouble_Mask = 0x7ffc0000,
- Type_Mask = 0xffff8000,
- Immediate_Mask = NotDouble_Mask | 0x00008000,
- IsNullOrUndefined_Mask = Immediate_Mask | 0x20000,
- Tag_Shift = 32
- };
- enum ValueType {
- Undefined_Type = Immediate_Mask | 0x00000,
- Null_Type = Immediate_Mask | 0x10000,
- Boolean_Type = Immediate_Mask | 0x20000,
- Integer_Type = Immediate_Mask | 0x30000,
- Managed_Type = NotDouble_Mask | 0x00000,
- Empty_Type = NotDouble_Mask | 0x30000
- };
-
- enum ImmediateFlags {
- ConvertibleToInt = Immediate_Mask | 0x1
- };
-
- enum ValueTypeInternal {
- _Null_Type = Null_Type | ConvertibleToInt,
- _Boolean_Type = Boolean_Type | ConvertibleToInt,
- _Integer_Type = Integer_Type | ConvertibleToInt,
-
- };
-#else
- static const quint64 NaNEncodeMask = 0xffff800000000000ll;
- static const quint64 IsInt32Mask = 0x0002000000000000ll;
- static const quint64 IsDoubleMask = 0xfffc000000000000ll;
- static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask;
- static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll;
- static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll;
- static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask;
-
- enum Masks {
- NaN_Mask = 0x7ff80000,
- Type_Mask = 0xffff8000,
- IsDouble_Mask = 0xfffc0000,
- Immediate_Mask = 0x00018000,
- IsNullOrUndefined_Mask = 0x00008000,
- IsNullOrBoolean_Mask = 0x00010000,
- Tag_Shift = 32
- };
- enum ValueType {
- Undefined_Type = IsNullOrUndefined_Mask,
- Null_Type = IsNullOrUndefined_Mask|IsNullOrBoolean_Mask,
- Boolean_Type = IsNullOrBoolean_Mask,
- Integer_Type = 0x20000|IsNullOrBoolean_Mask,
- Managed_Type = 0,
- Empty_Type = Undefined_Type | 0x4000
- };
- enum {
- IsDouble_Shift = 64-14,
- IsNumber_Shift = 64-15,
- IsConvertibleToInt_Shift = 64-16,
- IsManaged_Shift = 64-17
- };
-
-
- enum ValueTypeInternal {
- _Null_Type = Null_Type,
- _Boolean_Type = Boolean_Type,
- _Integer_Type = Integer_Type
- };
-#endif
-
- inline unsigned type() const {
- return tag & Type_Mask;
- }
-
- // used internally in property
- inline bool isEmpty() const { return tag == Empty_Type; }
-
- inline bool isUndefined() const { return tag == Undefined_Type; }
- inline bool isNull() const { return tag == _Null_Type; }
- inline bool isBoolean() const { return tag == _Boolean_Type; }
-#if QT_POINTER_SIZE == 8
- inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
- inline bool isDouble() const { return (val >> IsDouble_Shift); }
- inline bool isNumber() const { return (val >> IsNumber_Shift); }
- inline bool isManaged() const { return !(val >> IsManaged_Shift); }
- inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
- inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
- static inline bool integerCompatible(Value a, Value b) {
- return a.integerCompatible() && b.integerCompatible();
- }
- static inline bool bothDouble(Value a, Value b) {
- return a.isDouble() && b.isDouble();
- }
- double doubleValue() const {
- Q_ASSERT(isDouble());
- union {
- quint64 i;
- double d;
- } v;
- v.i = val ^ NaNEncodeMask;
- return v.d;
- }
- void setDouble(double d) {
- union {
- quint64 i;
- double d;
- } v;
- v.d = d;
- val = v.i ^ NaNEncodeMask;
- Q_ASSERT(isDouble());
- }
- bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
-#else
- inline bool isInteger() const { return tag == _Integer_Type; }
- inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isManaged() const { return tag == Managed_Type; }
- inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
- inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
- static inline bool integerCompatible(Value a, Value b) {
- return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
- }
- static inline bool bothDouble(Value a, Value b) {
- return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
- }
- double doubleValue() const { return dbl; }
- void setDouble(double d) { dbl = d; }
- bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
-#endif
- inline bool isString() const;
- inline bool isObject() const;
- inline bool isInt32() {
- if (tag == _Integer_Type)
- return true;
- if (isDouble()) {
- double d = doubleValue();
- int i = (int)d;
- if (i == d) {
- int_32 = i;
- tag = _Integer_Type;
- return true;
- }
- }
- return false;
- }
- double asDouble() const {
- if (tag == _Integer_Type)
- return int_32;
- return doubleValue();
- }
-
- bool booleanValue() const {
- return int_32;
- }
- int integerValue() const {
- return int_32;
- }
-
- String *stringValue() const {
- return s;
- }
- Object *objectValue() const {
- return o;
- }
- Managed *managed() const {
- return m;
- }
-
- quint64 rawValue() const {
- return val;
- }
-
- static inline Value fromManaged(Managed *o);
-
- int toUInt16() const;
- inline int toInt32() const;
- inline unsigned int toUInt32() const;
-
- inline bool toBoolean() const;
- double toInteger() const;
- inline double toNumber() const;
- double toNumberImpl() const;
- QString toQStringNoThrow() const;
- QString toQString() const;
- String *toString(ExecutionContext *ctx) const;
- Object *toObject(ExecutionContext *ctx) const;
-
- inline bool isPrimitive() const;
- inline bool tryIntegerConversion() {
- bool b = integerCompatible();
- if (b)
- tag = _Integer_Type;
- return b;
- }
-
- inline String *asString() const;
- inline Managed *asManaged() const;
- inline Object *asObject() const;
- inline FunctionObject *asFunctionObject() const;
- inline NumberObject *asNumberObject() const;
- inline StringObject *asStringObject() const;
- inline DateObject *asDateObject() const;
- inline ArrayObject *asArrayObject() const;
- inline ErrorObject *asErrorObject() const;
-
- template<typename T> inline T *as() const;
-
- inline uint asArrayIndex() const;
- inline uint asArrayLength(bool *ok) const;
-
- inline ExecutionEngine *engine() const;
-
- ReturnedValue asReturnedValue() const { return val; }
- static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
- Value &operator=(ReturnedValue v) { val = v; return *this; }
- template <typename T>
- inline Value &operator=(Returned<T> *t);
-
- // Section 9.12
- bool sameValue(Value other) const;
-
- inline void mark(ExecutionEngine *e) const;
-};
-
-inline Managed *Value::asManaged() const
-{
- if (isManaged())
- return managed();
- return 0;
-}
-
-inline String *Value::asString() const
-{
- if (isString())
- return stringValue();
- return 0;
-}
-
-struct Q_QML_EXPORT Primitive : public Value
-{
- inline static Primitive emptyValue();
- static inline Primitive fromBoolean(bool b);
- static inline Primitive fromInt32(int i);
- inline static Primitive undefinedValue();
- static inline Primitive nullValue();
- static inline Primitive fromDouble(double d);
- static inline Primitive fromUInt32(uint i);
-
- static double toInteger(double fromNumber);
- static int toInt32(double value);
- static unsigned int toUInt32(double value);
-
- inline operator ValueRef();
- Value asValue() const { return *this; }
-};
-
-inline Primitive Primitive::undefinedValue()
-{
- Primitive v;
-#if QT_POINTER_SIZE == 8
- v.val = quint64(Undefined_Type) << Tag_Shift;
-#else
- v.tag = Undefined_Type;
- v.int_32 = 0;
-#endif
- return v;
-}
-
-inline Primitive Primitive::emptyValue()
-{
- Primitive v;
- v.tag = Value::Empty_Type;
- v.uint_32 = 0;
- return v;
-}
-
-inline Value Value::fromManaged(Managed *m)
-{
- if (!m)
- return QV4::Primitive::undefinedValue();
- Value v;
-#if QT_POINTER_SIZE == 8
- v.m = m;
-#else
- v.tag = Managed_Type;
- v.m = m;
-#endif
- return v;
-}
-
-struct SafeValue : public Value
-{
- SafeValue &operator =(const ScopedValue &v);
- template<typename T>
- SafeValue &operator=(Returned<T> *t);
- SafeValue &operator=(ReturnedValue v) {
- val = v;
- return *this;
- }
- template<typename T>
- SafeValue &operator=(T *t) {
- val = Value::fromManaged(t).val;
- return *this;
- }
-
- template<typename T>
- SafeValue &operator=(const Scoped<T> &t);
- SafeValue &operator=(const ValueRef v);
- SafeValue &operator=(const Value &v) {
- val = v.val;
- return *this;
- }
- template<typename T>
- inline Returned<T> *as();
- template<typename T>
- inline Referenced<T> asRef();
-};
-
-template <typename T>
-struct Safe : public SafeValue
-{
- template<typename X>
- Safe &operator =(X *x) {
- val = Value::fromManaged(x).val;
- }
- Safe &operator =(T *t);
- Safe &operator =(const Scoped<T> &v);
- Safe &operator =(const Referenced<T> &v);
- Safe &operator =(Returned<T> *t);
-
- Safe &operator =(const Safe<T> &t);
-
- bool operator!() const { return !managed(); }
-
- T *operator->() { return static_cast<T *>(managed()); }
- const T *operator->() const { return static_cast<T *>(managed()); }
- T *getPointer() const { return static_cast<T *>(managed()); }
- Returned<T> *ret() const;
-
- void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
-};
-typedef Safe<String> SafeString;
-typedef Safe<Object> SafeObject;
-
-template<typename T>
-T *value_cast(const Value &v)
-{
- return v.as<T>();
-}
-
-template<typename T>
-ReturnedValue value_convert(ExecutionContext *ctx, const Value &v);
-
-
-
-}
-
-QT_END_NAMESPACE
-
-#endif // QV4VALUE_DEF_P_H
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
new file mode 100644
index 0000000000..35508f442a
--- /dev/null
+++ b/src/qml/jsruntime/qv4value_inl_p.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4VALUE_INL_H
+#define QV4VALUE_INL_H
+
+#include <cmath> // this HAS to come
+
+#include <QtCore/QString>
+#include <QtCore/qnumeric.h>
+#include "qv4global_p.h"
+#include "qv4string_p.h"
+#include <QtCore/QDebug>
+#include "qv4managed_p.h"
+#include "qv4engine_p.h"
+#include <private/qtqmlglobal_p.h>
+
+//#include <wtf/MathExtras.h>
+
+#include "qv4value_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+inline bool Value::isString() const
+{
+ if (!isManaged())
+ return false;
+ return managed() && managed()->internalClass->vtable->isString;
+}
+inline bool Value::isObject() const
+{
+ if (!isManaged())
+ return false;
+ return managed() && managed()->internalClass->vtable->isObject;
+}
+
+inline bool Value::isPrimitive() const
+{
+ return !isObject();
+}
+
+inline ExecutionEngine *Value::engine() const
+{
+ Managed *m = asManaged();
+ return m ? m->engine() : 0;
+}
+
+inline void Value::mark(ExecutionEngine *e) const
+{
+ if (!val)
+ return;
+ Managed *m = asManaged();
+ if (m)
+ m->mark(e);
+}
+
+inline Primitive Primitive::nullValue()
+{
+ Primitive v;
+#if QT_POINTER_SIZE == 8
+ v.val = quint64(_Null_Type) << Tag_Shift;
+#else
+ v.tag = _Null_Type;
+ v.int_32 = 0;
+#endif
+ return v;
+}
+
+inline Primitive Primitive::fromBoolean(bool b)
+{
+ Primitive v;
+ v.tag = _Boolean_Type;
+ v.int_32 = (bool)b;
+ return v;
+}
+
+inline Primitive Primitive::fromDouble(double d)
+{
+ Primitive v;
+ v.setDouble(d);
+ return v;
+}
+
+inline Primitive Primitive::fromInt32(int i)
+{
+ Primitive v;
+ v.tag = _Integer_Type;
+ v.int_32 = i;
+ return v;
+}
+
+inline Primitive Primitive::fromUInt32(uint i)
+{
+ Primitive v;
+ if (i < INT_MAX) {
+ v.tag = _Integer_Type;
+ v.int_32 = (int)i;
+ } else {
+ v.setDouble(i);
+ }
+ return v;
+}
+
+inline double Value::toNumber() const
+{
+ if (isInteger())
+ return int_32;
+ if (isDouble())
+ return doubleValue();
+ return toNumberImpl();
+}
+
+inline int Value::toInt32() const
+{
+ if (isInteger())
+ return int_32;
+ double d = isNumber() ? doubleValue() : toNumberImpl();
+
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
+
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Primitive::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
+{
+ return (unsigned int)toInt32();
+}
+
+
+inline bool Value::toBoolean() const
+{
+ switch (type()) {
+ case Value::Undefined_Type:
+ case Value::Null_Type:
+ return false;
+ case Value::Boolean_Type:
+ case Value::Integer_Type:
+ return (bool)int_32;
+ case Value::Managed_Type:
+ if (isString())
+ return stringValue()->toQString().length() > 0;
+ return true;
+ default: // double
+ return doubleValue() && !std::isnan(doubleValue());
+ }
+}
+
+inline uint Value::asArrayIndex() const
+{
+#if QT_POINTER_SIZE == 8
+ if (!isNumber())
+ return UINT_MAX;
+ if (isInteger())
+ return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
+#else
+ if (isInteger() && int_32 >= 0)
+ return (uint)int_32;
+ if (!isDouble())
+ return UINT_MAX;
+#endif
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d)
+ return UINT_MAX;
+ return idx;
+}
+
+inline uint Value::asArrayLength(bool *ok) const
+{
+ *ok = true;
+ if (isInteger()) {
+ if (int_32 >= 0) {
+ return (uint)int_32;
+ } else {
+ *ok = false;
+ return UINT_MAX;
+ }
+ }
+ if (isNumber()) {
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+ }
+ if (isString())
+ return stringValue()->toUInt(ok);
+
+ uint idx = toUInt32();
+ double d = toNumber();
+ if (d != idx) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+}
+
+inline Object *Value::asObject() const
+{
+ return isObject() ? objectValue() : 0;
+}
+
+inline FunctionObject *Value::asFunctionObject() const
+{
+ return isObject() ? managed()->asFunctionObject() : 0;
+}
+
+inline NumberObject *Value::asNumberObject() const
+{
+ return isObject() ? managed()->asNumberObject() : 0;
+}
+
+inline StringObject *Value::asStringObject() const
+{
+ return isObject() ? managed()->asStringObject() : 0;
+}
+
+inline DateObject *Value::asDateObject() const
+{
+ return isObject() ? managed()->asDateObject() : 0;
+}
+
+inline ArrayObject *Value::asArrayObject() const
+{
+ return isObject() ? managed()->asArrayObject() : 0;
+}
+
+inline ErrorObject *Value::asErrorObject() const
+{
+ return isObject() ? managed()->asErrorObject() : 0;
+}
+
+template<typename T>
+inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 680c7465ca..27c81d59a5 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -38,360 +38,530 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QMLJS_VALUE_H
-#define QMLJS_VALUE_H
+#ifndef QV4VALUE_P_H
+#define QV4VALUE_P_H
-#include <cmath> // this HAS to come
+#include <limits.h>
#include <QtCore/QString>
-#include <QtCore/qnumeric.h>
#include "qv4global_p.h"
-#include "qv4string_p.h"
-#include <QtCore/QDebug>
-#include "qv4managed_p.h"
-#include "qv4engine_p.h"
-#include <private/qtqmlglobal_p.h>
-
-//#include <wtf/MathExtras.h>
-
-#include "qv4value_def_p.h"
QT_BEGIN_NAMESPACE
namespace QV4 {
-inline bool Value::isString() const
-{
- if (!isManaged())
- return false;
- return managed() && managed()->type == Managed::Type_String;
-}
-inline bool Value::isObject() const
-{
- if (!isManaged())
- return false;
- return managed() && managed()->type != Managed::Type_String;
-}
+typedef uint Bool;
-inline bool Value::isPrimitive() const
+template <typename T>
+struct Returned : private T
{
- return !isObject();
-}
+ static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
+ T *getPointer() { return this; }
+ template<typename X>
+ static T *getPointer(Returned<X> *x) { return x->getPointer(); }
+ template<typename X>
+ Returned<X> *as() { return Returned<X>::create(Returned<X>::getPointer(this)); }
+ using T::asReturnedValue;
+};
-inline ExecutionEngine *Value::engine() const
+struct Q_QML_EXPORT Value
{
- Managed *m = asManaged();
- return m ? m->engine() : 0;
-}
+ /*
+ We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
-inline void Value::mark(ExecutionEngine *e) const
-{
- if (!val)
- return;
- Managed *m = asManaged();
- if (m)
- m->mark(e);
-}
+ In both cases, we 8 bytes for a value and different variant of NaN boxing. A Double NaN (actually -qNaN)
+ is indicated by a number that has the top 13 bits set. THe other values are usually set to 0 by the
+ processor, and are thus free for us to store other data. We keep pointers in there for managed objects,
+ and encode the other types using the free space given to use by the unused bits for NaN values. This also
+ works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory.
-inline Primitive Primitive::nullValue()
-{
- Primitive v;
+ On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that
+ will make the number a NaN. The Masks below are used for encoding the other types.
+
+ On 64 bit, we xor Doubles with (0xffff8000 << 32). Thas has the effect that no doubles will get encoded
+ with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These
+ can be used, as the highest valid pointer on a 64 bit system is 2^48-1.
+
+ If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer.
+ This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set).
+
+ Bit 15-17 is then used to encode other immediates.
+ */
+
+
+ union {
+ quint64 val;
#if QT_POINTER_SIZE == 8
- v.val = quint64(_Null_Type) << Tag_Shift;
+ Managed *m;
+ Object *o;
+ String *s;
#else
- v.tag = _Null_Type;
- v.int_32 = 0;
+ double dbl;
+#endif
+ struct {
+#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
+ uint tag;
+#endif
+ union {
+ uint uint_32;
+ int int_32;
+#if QT_POINTER_SIZE == 4
+ Managed *m;
+ Object *o;
+ String *s;
+#endif
+ };
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint tag;
+#endif
+ };
+ };
+
+#if QT_POINTER_SIZE == 4
+ enum Masks {
+ NaN_Mask = 0x7ff80000,
+ NotDouble_Mask = 0x7ffc0000,
+ Type_Mask = 0xffff8000,
+ Immediate_Mask = NotDouble_Mask | 0x00008000,
+ IsNullOrUndefined_Mask = Immediate_Mask | 0x20000,
+ Tag_Shift = 32
+ };
+ enum ValueType {
+ Undefined_Type = Immediate_Mask | 0x00000,
+ Null_Type = Immediate_Mask | 0x10000,
+ Boolean_Type = Immediate_Mask | 0x20000,
+ Integer_Type = Immediate_Mask | 0x30000,
+ Managed_Type = NotDouble_Mask | 0x00000,
+ Empty_Type = NotDouble_Mask | 0x30000
+ };
+
+ enum ImmediateFlags {
+ ConvertibleToInt = Immediate_Mask | 0x1
+ };
+
+ enum ValueTypeInternal {
+ _Null_Type = Null_Type | ConvertibleToInt,
+ _Boolean_Type = Boolean_Type | ConvertibleToInt,
+ _Integer_Type = Integer_Type | ConvertibleToInt,
+
+ };
+#else
+ static const quint64 NaNEncodeMask = 0xffff800000000000ll;
+ static const quint64 IsInt32Mask = 0x0002000000000000ll;
+ static const quint64 IsDoubleMask = 0xfffc000000000000ll;
+ static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask;
+ static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll;
+ static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll;
+ static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask;
+
+ enum Masks {
+ NaN_Mask = 0x7ff80000,
+ Type_Mask = 0xffff8000,
+ IsDouble_Mask = 0xfffc0000,
+ Immediate_Mask = 0x00018000,
+ IsNullOrUndefined_Mask = 0x00008000,
+ IsNullOrBoolean_Mask = 0x00010000,
+ Tag_Shift = 32
+ };
+ enum ValueType {
+ Undefined_Type = IsNullOrUndefined_Mask,
+ Null_Type = IsNullOrUndefined_Mask|IsNullOrBoolean_Mask,
+ Boolean_Type = IsNullOrBoolean_Mask,
+ Integer_Type = 0x20000|IsNullOrBoolean_Mask,
+ Managed_Type = 0,
+ Empty_Type = Undefined_Type | 0x4000
+ };
+ enum {
+ IsDouble_Shift = 64-14,
+ IsNumber_Shift = 64-15,
+ IsConvertibleToInt_Shift = 64-16,
+ IsManaged_Shift = 64-17
+ };
+
+
+ enum ValueTypeInternal {
+ _Null_Type = Null_Type,
+ _Boolean_Type = Boolean_Type,
+ _Integer_Type = Integer_Type
+ };
#endif
- return v;
-}
-
-inline Primitive Primitive::fromBoolean(bool b)
-{
- Primitive v;
- v.tag = _Boolean_Type;
- v.int_32 = (bool)b;
- return v;
-}
-inline Primitive Primitive::fromDouble(double d)
-{
- Primitive v;
- v.setDouble(d);
- return v;
-}
+ inline unsigned type() const {
+ return tag & Type_Mask;
+ }
-inline Primitive Primitive::fromInt32(int i)
-{
- Primitive v;
- v.tag = _Integer_Type;
- v.int_32 = i;
- return v;
-}
+ // used internally in property
+ inline bool isEmpty() const { return tag == Empty_Type; }
-inline Primitive Primitive::fromUInt32(uint i)
-{
- Primitive v;
- if (i < INT_MAX) {
- v.tag = _Integer_Type;
- v.int_32 = (int)i;
- } else {
- v.setDouble(i);
+ inline bool isUndefined() const { return tag == Undefined_Type; }
+ inline bool isNull() const { return tag == _Null_Type; }
+ inline bool isBoolean() const { return tag == _Boolean_Type; }
+#if QT_POINTER_SIZE == 8
+ inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
+ inline bool isDouble() const { return (val >> IsDouble_Shift); }
+ inline bool isNumber() const { return (val >> IsNumber_Shift); }
+ inline bool isManaged() const { return !(val >> IsManaged_Shift); }
+ inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
+ inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
+ static inline bool integerCompatible(Value a, Value b) {
+ return a.integerCompatible() && b.integerCompatible();
}
- return v;
-}
-
-inline double Value::toNumber() const
-{
- if (integerCompatible())
- return int_32;
- if (isDouble())
+ static inline bool bothDouble(Value a, Value b) {
+ return a.isDouble() && b.isDouble();
+ }
+ double doubleValue() const {
+ Q_ASSERT(isDouble());
+ union {
+ quint64 i;
+ double d;
+ } v;
+ v.i = val ^ NaNEncodeMask;
+ return v.d;
+ }
+ void setDouble(double d) {
+ union {
+ quint64 i;
+ double d;
+ } v;
+ v.d = d;
+ val = v.i ^ NaNEncodeMask;
+ Q_ASSERT(isDouble());
+ }
+ bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
+#else
+ inline bool isInteger() const { return tag == _Integer_Type; }
+ inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isManaged() const { return tag == Managed_Type; }
+ inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
+ inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ static inline bool integerCompatible(Value a, Value b) {
+ return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
+ }
+ static inline bool bothDouble(Value a, Value b) {
+ return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ }
+ double doubleValue() const { return dbl; }
+ void setDouble(double d) { dbl = d; }
+ bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+#endif
+ inline bool isString() const;
+ inline bool isObject() const;
+ inline bool isInt32() {
+ if (tag == _Integer_Type)
+ return true;
+ if (isDouble()) {
+ double d = doubleValue();
+ int i = (int)d;
+ if (i == d) {
+ int_32 = i;
+ tag = _Integer_Type;
+ return true;
+ }
+ }
+ return false;
+ }
+ double asDouble() const {
+ if (tag == _Integer_Type)
+ return int_32;
return doubleValue();
- return toNumberImpl();
-}
+ }
-inline int Value::toInt32() const
-{
- if (integerCompatible())
+ bool booleanValue() const {
+ return int_32;
+ }
+ int integerValue() const {
return int_32;
- double d;
- if (isDouble())
- d = doubleValue();
- else
- d = toNumberImpl();
+ }
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
+ String *stringValue() const {
+ return s;
+ }
+ Object *objectValue() const {
+ return o;
+ }
+ Managed *managed() const {
+ return m;
+ }
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
+ quint64 rawValue() const {
+ return val;
+ }
- return Primitive::toInt32(d);
-}
+ static inline Value fromManaged(Managed *o);
+
+ int toUInt16() const;
+ inline int toInt32() const;
+ inline unsigned int toUInt32() const;
+
+ inline bool toBoolean() const;
+ double toInteger() const;
+ inline double toNumber() const;
+ double toNumberImpl() const;
+ QString toQStringNoThrow() const;
+ QString toQString() const;
+ String *toString(ExecutionEngine *e) const;
+ String *toString(ExecutionContext *ctx) const;
+ Object *toObject(ExecutionContext *ctx) const;
+
+ inline bool isPrimitive() const;
+ inline bool tryIntegerConversion() {
+ bool b = integerCompatible();
+ if (b)
+ tag = _Integer_Type;
+ return b;
+ }
-inline unsigned int Value::toUInt32() const
-{
- return (unsigned int)toInt32();
-}
+ inline String *asString() const;
+ inline Managed *asManaged() const;
+ inline Object *asObject() const;
+ inline FunctionObject *asFunctionObject() const;
+ inline NumberObject *asNumberObject() const;
+ inline StringObject *asStringObject() const;
+ inline DateObject *asDateObject() const;
+ inline ArrayObject *asArrayObject() const;
+ inline ErrorObject *asErrorObject() const;
+ template<typename T> inline T *as() const;
-inline bool Value::toBoolean() const
-{
- switch (type()) {
- case Value::Undefined_Type:
- case Value::Null_Type:
- return false;
- case Value::Boolean_Type:
- case Value::Integer_Type:
- return (bool)int_32;
- case Value::Managed_Type:
- if (isString())
- return stringValue()->toQString().length() > 0;
- return true;
- default: // double
- return doubleValue() && !std::isnan(doubleValue());
- }
-}
+ inline uint asArrayIndex() const;
+ inline uint asArrayLength(bool *ok) const;
-inline uint Value::asArrayIndex() const
-{
-#if QT_POINTER_SIZE == 8
- if (!isNumber())
- return UINT_MAX;
- if (isInteger())
- return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
-#else
- if (isInteger() && int_32 >= 0)
- return (uint)int_32;
- if (!isDouble())
- return UINT_MAX;
-#endif
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d)
- return UINT_MAX;
- return idx;
-}
+ inline ExecutionEngine *engine() const;
-inline uint Value::asArrayLength(bool *ok) const
-{
- *ok = true;
- if (integerCompatible() && int_32 >= 0)
- return (uint)int_32;
- if (isDouble()) {
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
+ ReturnedValue asReturnedValue() const { return val; }
+ static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
+
+ // Section 9.12
+ bool sameValue(Value other) const;
+
+ inline void mark(ExecutionEngine *e) const;
+
+ Value &operator =(const ScopedValue &v);
+ Value &operator=(ReturnedValue v) { val = v; return *this; }
+ template<typename T>
+ Value &operator=(Returned<T> *t);
+ template<typename T>
+ Value &operator=(T *t) {
+ val = Value::fromManaged(t).val;
+ return *this;
}
- if (isString())
- return stringValue()->toUInt(ok);
- uint idx = toUInt32();
- double d = toNumber();
- if (d != idx) {
- *ok = false;
- return UINT_MAX;
+ template<typename T>
+ Value &operator=(const Scoped<T> &t);
+ Value &operator=(const ValueRef v);
+ Value &operator=(const Value &v) {
+ val = v.val;
+ return *this;
}
- return idx;
-}
+ template<typename T>
+ inline Returned<T> *as();
+};
-inline Object *Value::asObject() const
+inline Managed *Value::asManaged() const
{
- return isObject() ? objectValue() : 0;
+ if (isManaged())
+ return managed();
+ return 0;
}
-inline FunctionObject *Value::asFunctionObject() const
+inline String *Value::asString() const
{
- return isObject() ? managed()->asFunctionObject() : 0;
+ if (isString())
+ return stringValue();
+ return 0;
}
-inline NumberObject *Value::asNumberObject() const
+struct Q_QML_EXPORT Primitive : public Value
{
- return isObject() ? managed()->asNumberObject() : 0;
-}
+ inline static Primitive emptyValue();
+ static inline Primitive fromBoolean(bool b);
+ static inline Primitive fromInt32(int i);
+ inline static Primitive undefinedValue();
+ static inline Primitive nullValue();
+ static inline Primitive fromDouble(double d);
+ static inline Primitive fromUInt32(uint i);
+
+ static double toInteger(double fromNumber);
+ static int toInt32(double value);
+ static unsigned int toUInt32(double value);
+
+ inline operator ValueRef();
+ Value asValue() const { return *this; }
+};
-inline StringObject *Value::asStringObject() const
+inline Primitive Primitive::undefinedValue()
{
- return isObject() ? managed()->asStringObject() : 0;
+ Primitive v;
+#if QT_POINTER_SIZE == 8
+ v.val = quint64(Undefined_Type) << Tag_Shift;
+#else
+ v.tag = Undefined_Type;
+ v.int_32 = 0;
+#endif
+ return v;
}
-inline DateObject *Value::asDateObject() const
+inline Primitive Primitive::emptyValue()
{
- return isObject() ? managed()->asDateObject() : 0;
+ Primitive v;
+ v.tag = Value::Empty_Type;
+ v.uint_32 = 0;
+ return v;
}
-inline ArrayObject *Value::asArrayObject() const
+inline Value Value::fromManaged(Managed *m)
{
- return isObject() ? managed()->asArrayObject() : 0;
+ if (!m)
+ return QV4::Primitive::undefinedValue();
+ Value v;
+#if QT_POINTER_SIZE == 8
+ v.m = m;
+#else
+ v.tag = Managed_Type;
+ v.m = m;
+#endif
+ return v;
}
-inline ErrorObject *Value::asErrorObject() const
+template <typename T>
+struct TypedValue : public Value
{
- return isObject() ? managed()->asErrorObject() : 0;
-}
+ template<typename X>
+ TypedValue &operator =(X *x) {
+ val = Value::fromManaged(x).val;
+ }
+ TypedValue &operator =(T *t);
+ TypedValue &operator =(const Scoped<T> &v);
+// TypedValue &operator =(const ManagedRef<T> &v);
+ TypedValue &operator =(Returned<T> *t);
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
+ TypedValue &operator =(const TypedValue<T> &t);
-struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate
-{
- PersistentValuePrivate(ReturnedValue v, ExecutionEngine *engine = 0, bool weak = false);
- virtual ~PersistentValuePrivate();
- SafeValue value;
- uint refcount;
- bool weak;
- QV4::ExecutionEngine *engine;
- PersistentValuePrivate **prev;
- PersistentValuePrivate *next;
-
- void init();
- void removeFromList();
- void ref() { ++refcount; }
- void deref();
- PersistentValuePrivate *detach(const ReturnedValue value, bool weak = false);
-
- bool checkEngine(QV4::ExecutionEngine *otherEngine) {
- if (!engine) {
- Q_ASSERT(!value.isObject());
- engine = otherEngine;
- }
- return (engine == otherEngine);
- }
-};
+ bool operator!() const { return !managed(); }
-class Q_QML_EXPORT PersistentValue
-{
-public:
- PersistentValue() : d(0) {}
- PersistentValue(const PersistentValue &other);
- PersistentValue &operator=(const PersistentValue &other);
+ T *operator->() { return static_cast<T *>(managed()); }
+ const T *operator->() const { return static_cast<T *>(managed()); }
+ T *getPointer() const { return static_cast<T *>(managed()); }
+ Returned<T> *ret() const;
+
+ void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
+};
+typedef TypedValue<String> StringValue;
- PersistentValue(const ValueRef val);
- PersistentValue(ReturnedValue val);
- template<typename T>
- PersistentValue(Returned<T> *obj);
- template<typename T>
- PersistentValue(const Referenced<T> obj);
- PersistentValue &operator=(const ValueRef other);
- PersistentValue &operator =(ReturnedValue other);
- template<typename T>
- PersistentValue &operator=(Returned<T> *obj);
- template<typename T>
- PersistentValue &operator=(const Referenced<T> obj);
- ~PersistentValue();
- ReturnedValue value() const {
- return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue());
+struct Encode {
+ static ReturnedValue undefined() {
+ return quint64(Value::Undefined_Type) << Value::Tag_Shift;
+ }
+ static ReturnedValue null() {
+ return quint64(Value::_Null_Type) << Value::Tag_Shift;
}
- ExecutionEngine *engine() {
- if (!d)
- return 0;
- if (d->engine)
- return d->engine;
- Managed *m = d->value.asManaged();
- return m ? m->engine() : 0;
+ Encode(bool b) {
+ val = (quint64(Value::_Boolean_Type) << Value::Tag_Shift) | (uint)b;
+ }
+ Encode(double d) {
+ Value v;
+ v.setDouble(d);
+ val = v.val;
+ }
+ Encode(int i) {
+ val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
+ }
+ Encode(uint i) {
+ if (i <= INT_MAX) {
+ val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | i;
+ } else {
+ Value v;
+ v.setDouble(i);
+ val = v.val;
+ }
+ }
+ Encode(ReturnedValue v) {
+ val = v;
}
- bool isUndefined() const { return !d || d->value.isUndefined(); }
- bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); }
- void clear() {
- *this = PersistentValue();
+ template<typename T>
+ Encode(Returned<T> *t) {
+ val = t->getPointer()->asReturnedValue();
}
+ operator ReturnedValue() const {
+ return val;
+ }
+ quint64 val;
private:
- friend struct ValueRef;
- PersistentValuePrivate *d;
+ Encode(void *);
};
-class Q_QML_EXPORT WeakValue
-{
-public:
- WeakValue() : d(0) {}
- WeakValue(const ValueRef val);
- WeakValue(const WeakValue &other);
- WeakValue(ReturnedValue val);
- template<typename T>
- WeakValue(Returned<T> *obj);
- WeakValue &operator=(const WeakValue &other);
- WeakValue &operator=(const ValueRef other);
- WeakValue &operator =(const ReturnedValue &other);
- template<typename T>
- WeakValue &operator=(Returned<T> *obj);
-
- ~WeakValue();
+struct ValueRef {
+ ValueRef(const ScopedValue &v);
+ template <typename T>
+ ValueRef(const Scoped<T> &v);
+ ValueRef(const PersistentValue &v);
+ ValueRef(PersistentValuePrivate *p);
+ ValueRef(Value &v) { ptr = &v; }
+ // Important: Do NOT add a copy constructor to this class
+ // adding a copy constructor actually changes the calling convention, ie.
+ // is not even binary compatible. Adding it would break assumptions made
+ // in the jit'ed code.
+ ValueRef &operator=(const ScopedValue &o);
+ ValueRef &operator=(const Value &v)
+ { *ptr = v; return *this; }
+ ValueRef &operator=(const ReturnedValue &v) {
+ ptr->val = v;
+ return *this;
+ }
+ template <typename T>
+ ValueRef &operator=(Returned<T> *v) {
+ ptr->val = v->asReturnedValue();
+ return *this;
+ }
- ReturnedValue value() const {
- return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue());
+ operator const Value *() const {
+ return ptr;
+ }
+ const Value *operator->() const {
+ return ptr;
}
- ExecutionEngine *engine() {
- if (!d)
- return 0;
- if (d->engine)
- return d->engine;
- Managed *m = d->value.asManaged();
- return m ? m->engine() : 0;
+ operator Value *() {
+ return ptr;
+ }
+ Value *operator->() {
+ return ptr;
}
- bool isUndefined() const { return !d || d->value.isUndefined(); }
- bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); }
- void clear() {
- *this = WeakValue();
+ static ValueRef fromRawValue(Value *v) {
+ return ValueRef(v);
+ }
+ static const ValueRef fromRawValue(const Value *v) {
+ return ValueRef(const_cast<Value *>(v));
}
- void markOnce(ExecutionEngine *e);
+ ReturnedValue asReturnedValue() const { return ptr->val; }
+ // ### get rid of this one!
+ ValueRef(Value *v) { ptr = reinterpret_cast<Value *>(v); }
private:
- friend struct ValueRef;
- PersistentValuePrivate *d;
+ Value *ptr;
};
-} // namespace QV4
+
+template<typename T>
+T *value_cast(const Value &v)
+{
+ return v.as<T>();
+}
+
+template<typename T>
+ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
+
+
+
+}
QT_END_NAMESPACE
-#endif
+#endif // QV4VALUE_DEF_P_H
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index dfa4ac5775..92cc19d8b9 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_MANAGED_VTABLE(VariantObject);
+DEFINE_OBJECT_VTABLE(VariantObject);
VariantObject::VariantObject(InternalClass *ic)
: Object(ic)
@@ -77,7 +77,7 @@ QVariant VariantObject::toVariant(const QV4::ValueRef v)
if (v->isBoolean())
return QVariant(v->booleanValue());
if (v->isNumber()) {
- QV4::SafeValue val;
+ QV4::Value val;
val = v;
if (val.isInt32())
return QVariant(val.integerValue());
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 4e14839184..656608d49b 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -57,7 +57,7 @@
#include <QtQml/qqmllist.h>
#include <QtCore/qvariant.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -66,7 +66,7 @@ namespace QV4 {
struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
{
- Q_MANAGED
+ V4_OBJECT
public:
VariantObject(InternalClass *ic);
VariantObject(ExecutionEngine *engine, const QVariant &value);
@@ -82,6 +82,8 @@ public:
static bool isEqualTo(Managed *m, Managed *other);
};
+DEFINE_REF(VariantObject, Object);
+
struct VariantPrototype : VariantObject
{
public:
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 9d6540ebe9..3c44063606 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -41,7 +41,7 @@
#include "qv4vme_moth_p.h"
#include "qv4instr_moth_p.h"
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -58,14 +58,12 @@
# define TRACE(n, str, ...)
#endif // DO_TRACE_INSTR
-using namespace QQmlJS;
-using namespace QQmlJS::Moth;
+using namespace QV4;
+using namespace QV4::Moth;
#define MOTH_BEGIN_INSTR_COMMON(I) { \
const InstrMeta<(int)Instr::I>::DataType &instr = InstrMeta<(int)Instr::I>::data(*genericInstr); \
code += InstrMeta<(int)Instr::I>::Size; \
- if (debugger && (instr.breakPoint || debugger->pauseAtNextOpportunity())) \
- debugger->maybeBreakAtInstruction(code, instr.breakPoint); \
Q_UNUSED(instr); \
TRACE_INSTR(I)
@@ -74,11 +72,6 @@ using namespace QQmlJS::Moth;
# define MOTH_BEGIN_INSTR(I) op_##I: \
MOTH_BEGIN_INSTR_COMMON(I)
-# define MOTH_NEXT_INSTR(I) { \
- genericInstr = reinterpret_cast<const Instr *>(code); \
- goto *genericInstr->common.code; \
- }
-
# define MOTH_END_INSTR(I) } \
genericInstr = reinterpret_cast<const Instr *>(code); \
goto *genericInstr->common.code; \
@@ -89,10 +82,6 @@ using namespace QQmlJS::Moth;
case Instr::I: \
MOTH_BEGIN_INSTR_COMMON(I)
-# define MOTH_NEXT_INSTR(I) { \
- continue; \
- }
-
# define MOTH_END_INSTR(I) } \
continue;
@@ -161,16 +150,15 @@ Param traceParam(const Param &param)
#define STOREVALUE(param, value) { \
QV4::ReturnedValue tmp = (value); \
- if (context->engine->hasException) \
+ if (engine->hasException) \
goto catchException; \
VALUE(param) = tmp; \
}
#define CHECK_EXCEPTION \
- if (context->engine->hasException) \
+ if (engine->hasException) \
goto catchException
-QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
- QV4::SafeValue *stack, unsigned stackSize
+QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable
#endif
@@ -192,15 +180,18 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
}
#endif
+ QV4::Value *stack = 0;
+ unsigned stackSize = 0;
+
const uchar *exceptionHandler = 0;
- QV4::Debugging::Debugger *debugger = context->engine->debugger;
+ QV4::ExecutionEngine *engine = context->engine;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
#endif // DO_TRACE_INSTR
- QV4::SafeString * const runtimeStrings = context->compilationUnit->runtimeStrings;
+ QV4::StringValue * const runtimeStrings = context->compilationUnit->runtimeStrings;
context->interpreterInstructionPointer = &code;
// setup lookup scopes
@@ -213,9 +204,9 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
}
}
- QV4::SafeValue **scopes = static_cast<QV4::SafeValue **>(alloca(sizeof(QV4::SafeValue *)*(2 + 2*scopeDepth)));
+ QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth)));
{
- scopes[0] = const_cast<QV4::SafeValue *>(context->compilationUnit->data->constants());
+ scopes[0] = const_cast<QV4::Value *>(context->compilationUnit->data->constants());
// stack gets setup in push instruction
scopes[1] = 0;
QV4::ExecutionContext *scope = context;
@@ -247,6 +238,10 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
VALUE(instr.result) = VALUE(instr.source);
MOTH_END_INSTR(Move)
+ MOTH_BEGIN_INSTR(MoveConst)
+ VALUE(instr.result) = instr.source;
+ MOTH_END_INSTR(MoveConst)
+
MOTH_BEGIN_INSTR(SwapTemps)
qSwap(VALUE(instr.left), VALUE(instr.right));
MOTH_END_INSTR(MoveTemp)
@@ -286,11 +281,22 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
STOREVALUE(instr.result, __qmljs_get_element(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(LoadElement)
+ MOTH_BEGIN_INSTR(LoadElementLookup)
+ QV4::Lookup *l = context->lookups + instr.lookup;
+ STOREVALUE(instr.result, l->indexedGetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index)));
+ MOTH_END_INSTR(LoadElementLookup)
+
MOTH_BEGIN_INSTR(StoreElement)
__qmljs_set_element(context, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
+ MOTH_BEGIN_INSTR(StoreElementLookup)
+ QV4::Lookup *l = context->lookups + instr.lookup;
+ l->indexedSetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreElementLookup)
+
MOTH_BEGIN_INSTR(LoadProperty)
STOREVALUE(instr.result, __qmljs_get_property(context, VALUEPTR(instr.base), runtimeStrings[instr.name]));
MOTH_END_INSTR(LoadProperty)
@@ -328,7 +334,9 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
stack = context->engine->stackPush(stackSize);
- memset(stack, 0, stackSize * sizeof(QV4::SafeValue));
+#ifndef QT_NO_DEBUG
+ memset(stack, 0, stackSize * sizeof(QV4::Value));
+#endif
scopes[1] = stack;
MOTH_END_INSTR(Push)
@@ -343,7 +351,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
}
}
#endif // DO_TRACE_INSTR
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -353,7 +361,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(CallProperty)
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -363,7 +371,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(CallPropertyLookup)
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -372,7 +380,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -382,7 +390,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(CallActivationProperty)
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -392,7 +400,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(CallGlobalLookup)
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -475,12 +483,12 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::SafeValue *args = stack + instr.args;
+ QV4::Value *args = stack + instr.args;
STOREVALUE(instr.result, __qmljs_builtin_define_array(context, args, instr.argc));
MOTH_END_INSTR(CallBuiltinDefineArray)
MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral)
- QV4::SafeValue *args = stack + instr.args;
+ QV4::Value *args = stack + instr.args;
STOREVALUE(instr.result, __qmljs_builtin_define_object_literal(context, args, instr.internalClassId));
MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
@@ -494,7 +502,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_END_INSTR(CallBuiltinConvertThisToObject)
MOTH_BEGIN_INSTR(CreateValue)
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -503,7 +511,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -512,7 +520,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -522,7 +530,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -532,7 +540,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
- Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::SafeValue) <= stackSize);
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
@@ -544,14 +552,19 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(Jump)
- MOTH_BEGIN_INSTR(CJump)
- uint cond = __qmljs_to_boolean(VALUEPTR(instr.condition));
+ MOTH_BEGIN_INSTR(JumpEq)
+ bool cond = VALUEPTR(instr.condition)->toBoolean();
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
- if (instr.invert)
- cond = !cond;
if (cond)
code = ((uchar *)&instr.offset) + instr.offset;
- MOTH_END_INSTR(CJump)
+ MOTH_END_INSTR(JumpEq)
+
+ MOTH_BEGIN_INSTR(JumpNe)
+ bool cond = VALUEPTR(instr.condition)->toBoolean();
+ TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
+ if (!cond)
+ code = ((uchar *)&instr.offset) + instr.offset;
+ MOTH_END_INSTR(JumpNe)
MOTH_BEGIN_INSTR(UNot)
STOREVALUE(instr.result, __qmljs_not(VALUEPTR(instr.source)));
@@ -606,6 +619,14 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
STOREVALUE(instr.result, __qmljs_bit_xor(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BitXor)
+ MOTH_BEGIN_INSTR(Shr)
+ STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() >> (VALUEPTR(instr.rhs)->toInt32() & 0x1f))));
+ MOTH_END_INSTR(Shr)
+
+ MOTH_BEGIN_INSTR(Shl)
+ STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() << (VALUEPTR(instr.rhs)->toInt32() & 0x1f))));
+ MOTH_END_INSTR(Shl)
+
MOTH_BEGIN_INSTR(BitAndConst)
int lhs = VALUEPTR(instr.lhs)->toInt32();
STOREVALUE(instr.result, QV4::Encode((int)(lhs & instr.rhs)));
@@ -621,6 +642,14 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
STOREVALUE(instr.result, QV4::Encode((int)(lhs ^ instr.rhs)));
MOTH_END_INSTR(BitXor)
+ MOTH_BEGIN_INSTR(ShrConst)
+ STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() >> instr.rhs)));
+ MOTH_END_INSTR(ShrConst)
+
+ MOTH_BEGIN_INSTR(ShlConst)
+ STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() << instr.rhs)));
+ MOTH_END_INSTR(ShlConst)
+
MOTH_BEGIN_INSTR(Mul)
STOREVALUE(instr.result, __qmljs_mul(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Mul)
@@ -633,30 +662,18 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
STOREVALUE(instr.result, instr.alu(context, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BinopContext)
- MOTH_BEGIN_INSTR(AddNumberParams)
- double lhs = VALUE(instr.lhs).asDouble();
- double rhs = VALUE(instr.rhs).asDouble();
- VALUEPTR(instr.result)->setDouble(lhs + rhs);
- MOTH_END_INSTR(AddNumberParams)
-
- MOTH_BEGIN_INSTR(MulNumberParams)
- double lhs = VALUE(instr.lhs).asDouble();
- double rhs = VALUE(instr.rhs).asDouble();
- VALUEPTR(instr.result)->setDouble(lhs * rhs);
- MOTH_END_INSTR(MulNumberParams)
-
- MOTH_BEGIN_INSTR(SubNumberParams)
- double lhs = VALUE(instr.lhs).asDouble();
- double rhs = VALUE(instr.rhs).asDouble();
- VALUEPTR(instr.result)->setDouble(lhs - rhs);
- MOTH_END_INSTR(SubNumberParams)
-
MOTH_BEGIN_INSTR(Ret)
context->engine->stackPop(stackSize);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
return VALUE(instr.result).asReturnedValue();
MOTH_END_INSTR(Ret)
+ MOTH_BEGIN_INSTR(Debug)
+ QV4::Debugging::Debugger *debugger = context->engine->debugger;
+ if (debugger && (instr.breakPoint || debugger->pauseAtNextOpportunity()))
+ debugger->maybeBreakAtInstruction(code, instr.breakPoint);
+ MOTH_END_INSTR(Debug)
+
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->callData->thisObject;
MOTH_END_INSTR(LoadThis)
@@ -709,7 +726,7 @@ void **VME::instructionJumpTable()
static void **jumpTable = 0;
if (!jumpTable) {
const uchar *code = 0;
- VME().run(0, code, 0, 0, &jumpTable);
+ VME().run(0, code, &jumpTable);
}
return jumpTable;
}
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 974dfdd615..711163cde0 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -47,7 +47,7 @@
QT_BEGIN_NAMESPACE
-namespace QQmlJS {
+namespace QV4 {
namespace Moth {
class VME
@@ -60,8 +60,7 @@ public:
#endif
private:
- QV4::ReturnedValue run(QV4::ExecutionContext *, const uchar *code,
- QV4::SafeValue *stack = 0, unsigned stackSize = 0
+ QV4::ReturnedValue run(QV4::ExecutionContext *, const uchar *code
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable = 0
#endif
@@ -69,7 +68,7 @@ private:
};
} // namespace Moth
-} // namespace QQmlJS
+} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 8e8ed954ad..73d0a8c3dd 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -707,7 +707,7 @@ again:
_validTokenText = true;
_tokenText.resize(0);
startCode--;
- while (startCode != _codePtr - 1)
+ while (startCode != _codePtr - 1)
_tokenText += *startCode++;
while (_codePtr <= _endPtr) {
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index 820ae8ed71..29103930ad 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -108,6 +108,8 @@ public:
_ptr = _end = 0;
}
+ template <typename _Tp> _Tp *New() { return new (this->allocate(sizeof(_Tp))) _Tp(); }
+
private:
void *allocate_helper(size_t size)
{
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 79e83a1d47..17d35f8c54 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -34,6 +34,7 @@ include(util/util.pri)
include(parser/parser.pri)
include(compiler/compiler.pri)
include(jsapi/jsapi.pri)
+include(jit/jit.pri)
include(jsruntime/jsruntime.pri)
include(qml/qml.pri)
include(debugger/debugger.pri)
diff --git a/src/qml/qml/ftw/qbitfield_p.h b/src/qml/qml/ftw/qbitfield_p.h
index b224f5b57d..12e98dc655 100644
--- a/src/qml/qml/ftw/qbitfield_p.h
+++ b/src/qml/qml/ftw/qbitfield_p.h
@@ -91,13 +91,13 @@ QBitField::QBitField(const quint32 *bitData, int bitCount)
QBitField::QBitField(const QBitField &other)
: bits(other.bits), ownData(other.ownData), data(other.data)
{
- if (ownData)
+ if (ownData)
++(*ownData);
}
QBitField::~QBitField()
{
- if (ownData)
+ if (ownData)
if(0 == --(*ownData)) delete [] ownData;
}
@@ -106,14 +106,14 @@ QBitField &QBitField::operator=(const QBitField &other)
if (other.data == data)
return *this;
- if (ownData)
+ if (ownData)
if(0 == --(*ownData)) delete [] ownData;
bits = other.bits;
ownData = other.ownData;
data = other.data;
- if (ownData)
+ if (ownData)
++(*ownData);
return *this;
diff --git a/src/qml/qml/ftw/qfieldlist_p.h b/src/qml/qml/ftw/qfieldlist_p.h
index 5d37751f05..c90b6773a1 100644
--- a/src/qml/qml/ftw/qfieldlist_p.h
+++ b/src/qml/qml/ftw/qfieldlist_p.h
@@ -90,7 +90,7 @@ private:
// QFieldList is a simple linked list, that can append and prepend and also
// maintains a count
template<class N, N *N::*nextMember>
-class QFieldList
+class QFieldList
{
public:
inline QFieldList();
@@ -253,7 +253,7 @@ N *QFieldList<N, nextMember>::takeFirst()
}
value->*nextMember = 0;
--_count;
- }
+ }
return value;
}
diff --git a/src/qml/qml/ftw/qfinitestack_p.h b/src/qml/qml/ftw/qfinitestack_p.h
index 8b499d9b6d..6bfd353771 100644
--- a/src/qml/qml/ftw/qfinitestack_p.h
+++ b/src/qml/qml/ftw/qfinitestack_p.h
@@ -83,7 +83,7 @@ private:
template<typename T>
QFiniteStack<T>::QFiniteStack()
-: _array(0), _alloc(0), _size(0)
+: _array(0), _alloc(0), _size(0)
{
}
@@ -114,6 +114,7 @@ T &QFiniteStack<T>::top()
template<typename T>
void QFiniteStack<T>::push(const T &o)
{
+ Q_ASSERT(_size < _alloc);
if (QTypeInfo<T>::isComplex) {
new (_array + _size++) T(o);
} else {
@@ -124,6 +125,7 @@ void QFiniteStack<T>::push(const T &o)
template<typename T>
T QFiniteStack<T>::pop()
{
+ Q_ASSERT(_size > 0);
--_size;
if (QTypeInfo<T>::isComplex) {
@@ -134,7 +136,7 @@ T QFiniteStack<T>::pop()
return _array[_size];
}
}
-
+
template<typename T>
int QFiniteStack<T>::count() const
{
@@ -154,7 +156,7 @@ T &QFiniteStack<T>::operator[](int index)
}
template<typename T>
-void QFiniteStack<T>::allocate(int size)
+void QFiniteStack<T>::allocate(int size)
{
Q_ASSERT(_array == 0);
Q_ASSERT(_alloc == 0);
@@ -171,7 +173,7 @@ void QFiniteStack<T>::deallocate()
{
if (QTypeInfo<T>::isComplex) {
T *i = _array + _size;
- while (i != _array)
+ while (i != _array)
(--i)->~T();
}
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp
index 012412b6b5..fa3524ff3e 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -198,19 +198,19 @@ bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
QHashedStringRef QHashedStringRef::mid(int offset, int length) const
{
Q_ASSERT(offset < m_length);
- return QHashedStringRef(m_data + offset,
+ return QHashedStringRef(m_data + offset,
(length == -1 || (offset + length) > m_length)?(m_length - offset):length);
}
bool QHashedStringRef::endsWith(const QString &s) const
{
- return s.length() < m_length &&
+ return s.length() < m_length &&
QHashedString::compare(s.constData(), m_data + m_length - s.length(), s.length());
}
bool QHashedStringRef::startsWith(const QString &s) const
{
- return s.length() < m_length &&
+ return s.length() < m_length &&
QHashedString::compare(s.constData(), m_data, s.length());
}
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index 46f0533740..61a492013d 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -97,7 +97,7 @@ private:
};
class QHashedCStringRef;
-class Q_AUTOTEST_EXPORT QHashedStringRef
+class Q_AUTOTEST_EXPORT QHashedStringRef
{
public:
inline QHashedStringRef();
@@ -258,15 +258,15 @@ public:
}
inline bool equals(const QHashedStringRef &string) const {
- return length == string.length() &&
- hash == string.hash() &&
+ return length == string.length() &&
+ hash == string.hash() &&
(isQString()?QHashedString::compare(string.constData(), (QChar *)utf16Data(), length):
QHashedString::compare(string.constData(), cStrData(), length));
}
inline bool equals(const QHashedCStringRef &string) const {
- return length == string.length() &&
- hash == string.hash() &&
+ return length == string.length() &&
+ hash == string.hash() &&
(isQString()?QHashedString::compare((QChar *)utf16Data(), string.constData(), length):
QHashedString::compare(string.constData(), cStrData(), length));
}
@@ -275,7 +275,7 @@ public:
class Q_AUTOTEST_EXPORT QStringHashData
{
public:
- QStringHashData()
+ QStringHashData()
: buckets(0), numBuckets(0), size(0), numBits(0)
#ifdef QSTRINGHASH_LINK_DEBUG
, linkCount(0)
@@ -1026,33 +1026,33 @@ typename QStringHash<T>::ConstIterator QStringMultiHash<T>::findNext(const Const
return ConstIterator();
}
-inline uint qHash(const QHashedString &string)
-{
- return uint(string.hash());
+inline uint qHash(const QHashedString &string)
+{
+ return uint(string.hash());
}
-inline uint qHash(const QHashedStringRef &string)
-{
- return uint(string.hash());
+inline uint qHash(const QHashedStringRef &string)
+{
+ return uint(string.hash());
}
-QHashedString::QHashedString()
-: QString(), m_hash(0)
+QHashedString::QHashedString()
+: QString(), m_hash(0)
{
}
-QHashedString::QHashedString(const QString &string)
-: QString(string), m_hash(0)
+QHashedString::QHashedString(const QString &string)
+: QString(string), m_hash(0)
{
}
-QHashedString::QHashedString(const QString &string, quint32 hash)
-: QString(string), m_hash(hash)
+QHashedString::QHashedString(const QString &string, quint32 hash)
+: QString(string), m_hash(hash)
{
}
-QHashedString::QHashedString(const QHashedString &string)
-: QString(string), m_hash(string.m_hash)
+QHashedString::QHashedString(const QHashedString &string)
+: QString(string), m_hash(string.m_hash)
{
}
@@ -1065,29 +1065,29 @@ QHashedString &QHashedString::operator=(const QHashedString &string)
bool QHashedString::operator==(const QHashedString &string) const
{
- return (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
+ return (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
static_cast<const QString &>(*this) == static_cast<const QString &>(string);
}
bool QHashedString::operator==(const QHashedStringRef &string) const
{
return length() == string.m_length &&
- (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
+ (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
QHashedString::compare(constData(), string.m_data, string.m_length);
}
quint32 QHashedString::hash() const
-{
+{
if (!m_hash) computeHash();
return m_hash;
}
quint32 QHashedString::existingHash() const
-{
+{
return m_hash;
}
-QHashedStringRef::QHashedStringRef()
+QHashedStringRef::QHashedStringRef()
: m_data(0), m_length(0), m_hash(0)
{
}
@@ -1138,21 +1138,21 @@ bool QHashedStringRef::operator==(const QString &string) const
bool QHashedStringRef::operator==(const QHashedString &string) const
{
- return m_length == string.length() &&
+ return m_length == string.length() &&
(m_hash == string.m_hash || !m_hash || !string.m_hash) &&
QHashedString::compare(string.constData(), m_data, m_length);
}
bool QHashedStringRef::operator==(const QHashedStringRef &string) const
{
- return m_length == string.m_length &&
+ return m_length == string.m_length &&
(m_hash == string.m_hash || !m_hash || !string.m_hash) &&
QHashedString::compare(string.m_data, m_data, m_length);
}
bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
{
- return m_length == string.m_length &&
+ return m_length == string.m_length &&
(m_hash == string.m_hash || !m_hash || !string.m_hash) &&
QHashedString::compare(m_data, string.m_data, m_length);
}
@@ -1165,7 +1165,7 @@ bool QHashedStringRef::operator!=(const QString &string) const
bool QHashedStringRef::operator!=(const QHashedString &string) const
{
- return m_length != string.length() ||
+ return m_length != string.length() ||
(m_hash != string.m_hash && m_hash && string.m_hash) ||
!QHashedString::compare(string.constData(), m_data, m_length);
}
@@ -1224,7 +1224,7 @@ bool QHashedStringRef::startsWithUpper() const
}
quint32 QHashedStringRef::hash() const
-{
+{
if (!m_hash) computeHash();
return m_hash;
}
@@ -1279,20 +1279,20 @@ void QHashedCStringRef::writeUtf16(quint16 *output) const
{
int l = m_length;
const char *d = m_data;
- while (l--)
+ while (l--)
*output++ = *d++;
}
-bool QHashedString::compare(const QChar *lhs, const char *rhs, int length)
+bool QHashedString::compare(const QChar *lhs, const char *rhs, int length)
{
Q_ASSERT(lhs && rhs);
const quint16 *l = (const quint16*)lhs;
- while (length--)
+ while (length--)
if (*l++ != *rhs++) return false;
return true;
}
-bool QHashedString::compare(const char *lhs, const char *rhs, int length)
+bool QHashedString::compare(const char *lhs, const char *rhs, int length)
{
Q_ASSERT(lhs && rhs);
return 0 == ::memcmp(lhs, rhs, length);
diff --git a/src/qml/qml/ftw/qhashfield_p.h b/src/qml/qml/ftw/qhashfield_p.h
index 32c7a0fbe2..aa8840688a 100644
--- a/src/qml/qml/ftw/qhashfield_p.h
+++ b/src/qml/qml/ftw/qhashfield_p.h
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
// example where you would write:
// QSet<QString> strings;
// for (int ii = 0; ii < mystrings.count(); ++ii) {
-// if (strings.contains(mystrings.at(ii)))
+// if (strings.contains(mystrings.at(ii)))
// qFatal("Duplication!");
// strings.insert(mystrings);
// }
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
// if (strings.testAndSet(qHash(mystrings.at(ii)))) {
// // The string *might* be duplicated
// for (int jj = 0; jj < ii; ++jj) {
-// if (mystrings.at(ii) == mystrings.at(jj))
+// if (mystrings.at(ii) == mystrings.at(jj))
// qFatal("Duplication!");
// }
// }
diff --git a/src/qml/qml/ftw/qintrusivelist.cpp b/src/qml/qml/ftw/qintrusivelist.cpp
index 12d710ca47..7c80b57c9d 100644
--- a/src/qml/qml/ftw/qintrusivelist.cpp
+++ b/src/qml/qml/ftw/qintrusivelist.cpp
@@ -46,7 +46,7 @@
\brief The QIntrusiveList class is a template class that provides a list of objects using static storage.
\internal
-QIntrusiveList creates a linked list of objects. Adding and removing objects from the
+QIntrusiveList creates a linked list of objects. Adding and removing objects from the
QIntrusiveList is a constant time operation and is very quick. The list performs no memory
allocations, but does require the objects being added to the list to contain a QIntrusiveListNode
instance for the list's use. Even so, for small lists QIntrusiveList uses less memory than Qt's
@@ -102,7 +102,7 @@ Destroy the list. All entries are removed.
/*!
\fn void QIntrusiveList::insert(N *object);
-Insert \a object into the list. If \a object is a member of this, or another list, it will be
+Insert \a object into the list. If \a object is a member of this, or another list, it will be
removed and inserted at the head of this list.
*/
diff --git a/src/qml/qml/ftw/qintrusivelist_p.h b/src/qml/qml/ftw/qintrusivelist_p.h
index ccaeee2e40..67de569951 100644
--- a/src/qml/qml/ftw/qintrusivelist_p.h
+++ b/src/qml/qml/ftw/qintrusivelist_p.h
@@ -82,7 +82,7 @@ public:
inline iterator &operator++();
inline iterator &erase();
-
+
private:
N *_value;
};
@@ -114,60 +114,60 @@ public:
};
template<class N, QIntrusiveListNode N::*member>
-QIntrusiveList<N, member>::iterator::iterator()
-: _value(0)
+QIntrusiveList<N, member>::iterator::iterator()
+: _value(0)
{
}
template<class N, QIntrusiveListNode N::*member>
-QIntrusiveList<N, member>::iterator::iterator(N *value)
-: _value(value)
+QIntrusiveList<N, member>::iterator::iterator(N *value)
+: _value(value)
{
}
template<class N, QIntrusiveListNode N::*member>
-N *QIntrusiveList<N, member>::iterator::operator*() const
-{
- return _value;
+N *QIntrusiveList<N, member>::iterator::operator*() const
+{
+ return _value;
}
template<class N, QIntrusiveListNode N::*member>
-N *QIntrusiveList<N, member>::iterator::operator->() const
-{
- return _value;
+N *QIntrusiveList<N, member>::iterator::operator->() const
+{
+ return _value;
}
template<class N, QIntrusiveListNode N::*member>
-bool QIntrusiveList<N, member>::iterator::operator==(const iterator &other) const
-{
- return other._value == _value;
+bool QIntrusiveList<N, member>::iterator::operator==(const iterator &other) const
+{
+ return other._value == _value;
}
template<class N, QIntrusiveListNode N::*member>
-bool QIntrusiveList<N, member>::iterator::operator!=(const iterator &other) const
-{
- return other._value != _value;
+bool QIntrusiveList<N, member>::iterator::operator!=(const iterator &other) const
+{
+ return other._value != _value;
}
template<class N, QIntrusiveListNode N::*member>
-typename QIntrusiveList<N, member>::iterator &QIntrusiveList<N, member>::iterator::operator++()
-{
- _value = QIntrusiveList<N, member>::next(_value);
- return *this;
+typename QIntrusiveList<N, member>::iterator &QIntrusiveList<N, member>::iterator::operator++()
+{
+ _value = QIntrusiveList<N, member>::next(_value);
+ return *this;
}
template<class N, QIntrusiveListNode N::*member>
-typename QIntrusiveList<N, member>::iterator &QIntrusiveList<N, member>::iterator::erase()
-{
- N *old = _value;
- _value = QIntrusiveList<N, member>::next(_value);
- (old->*member).remove();
+typename QIntrusiveList<N, member>::iterator &QIntrusiveList<N, member>::iterator::erase()
+{
+ N *old = _value;
+ _value = QIntrusiveList<N, member>::next(_value);
+ (old->*member).remove();
return *this;
}
-
+
template<class N, QIntrusiveListNode N::*member>
-QIntrusiveList<N, member>::QIntrusiveList()
-: __first(0)
+QIntrusiveList<N, member>::QIntrusiveList()
+: __first(0)
{
}
@@ -184,7 +184,7 @@ bool QIntrusiveList<N, member>::isEmpty() const
}
template<class N, QIntrusiveListNode N::*member>
-void QIntrusiveList<N, member>::insert(N *n)
+void QIntrusiveList<N, member>::insert(N *n)
{
QIntrusiveListNode *nnode = &(n->*member);
nnode->remove();
@@ -215,13 +215,13 @@ bool QIntrusiveList<N, member>::contains(N *n) const
}
template<class N, QIntrusiveListNode N::*member>
-N *QIntrusiveList<N, member>::first() const
-{
- return __first?nodeToN(__first):0;
+N *QIntrusiveList<N, member>::first() const
+{
+ return __first?nodeToN(__first):0;
}
template<class N, QIntrusiveListNode N::*member>
-N *QIntrusiveList<N, member>::next(N *current)
+N *QIntrusiveList<N, member>::next(N *current)
{
QIntrusiveListNode *nextnode = (current->*member)._next;
N *nextstruct = nextnode?nodeToN(nextnode):0;
@@ -229,19 +229,19 @@ N *QIntrusiveList<N, member>::next(N *current)
}
template<class N, QIntrusiveListNode N::*member>
-typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::begin()
-{
- return __first?iterator(nodeToN(__first)):iterator();
+typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::begin()
+{
+ return __first?iterator(nodeToN(__first)):iterator();
}
template<class N, QIntrusiveListNode N::*member>
-typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::end()
-{
- return iterator();
+typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::end()
+{
+ return iterator();
}
template<class N, QIntrusiveListNode N::*member>
-N *QIntrusiveList<N, member>::nodeToN(QIntrusiveListNode *node)
+N *QIntrusiveList<N, member>::nodeToN(QIntrusiveListNode *node)
{
return (N *)((char *)node - ((char *)&(((N *)0)->*member) - (char *)0));
}
diff --git a/src/qml/qml/ftw/qqmlpool_p.h b/src/qml/qml/ftw/qqmlpool_p.h
index 408ac74771..7a04291cd4 100644
--- a/src/qml/qml/ftw/qqmlpool_p.h
+++ b/src/qml/qml/ftw/qqmlpool_p.h
@@ -63,7 +63,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPool
{
public:
// The class has a destructor that needs to be called
- class Class {
+ class Class {
public:
inline QQmlPool *pool() const;
@@ -82,7 +82,7 @@ public:
class POD {
public:
inline QQmlPool *pool() const;
-
+
private:
void *operator new(size_t);
void *operator new(size_t, void *m) { return m; }
@@ -120,16 +120,16 @@ public:
int count() const {
return m_length;
}
- int length() const {
- return m_length;
+ int length() const {
+ return m_length;
}
- const T &at(int index) const {
- Q_ASSERT(index < m_length);
- return m_data[index];
+ const T &at(int index) const {
+ Q_ASSERT(index < m_length);
+ return m_data[index];
};
T &operator[](int index) {
- Q_ASSERT(index < m_length);
- return m_data[index];
+ Q_ASSERT(index < m_length);
+ return m_data[index];
};
const T *data() const { return m_data; }
private:
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 24c3e7a2cc..de32f0e915 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -86,7 +86,7 @@ public:
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
inline QQmlRefPointer<T> &operator=(T *);
-
+
inline bool isNull() const { return !o; }
inline T* operator->() const { return o; }
@@ -100,27 +100,27 @@ private:
T *o;
};
-QQmlRefCount::QQmlRefCount()
-: refCount(1)
+QQmlRefCount::QQmlRefCount()
+: refCount(1)
{
}
-QQmlRefCount::~QQmlRefCount()
+QQmlRefCount::~QQmlRefCount()
{
Q_ASSERT(refCount.load() == 0);
}
-void QQmlRefCount::addref()
-{
+void QQmlRefCount::addref()
+{
Q_ASSERT(refCount.load() > 0);
- refCount.ref();
+ refCount.ref();
}
-void QQmlRefCount::release()
-{
+void QQmlRefCount::release()
+{
Q_ASSERT(refCount.load() > 0);
- if (!refCount.deref())
- destroy();
+ if (!refCount.deref())
+ destroy();
}
int QQmlRefCount::count() const
@@ -128,20 +128,20 @@ int QQmlRefCount::count() const
return refCount.load();
}
-void QQmlRefCount::destroy()
-{
- delete this;
+void QQmlRefCount::destroy()
+{
+ delete this;
}
template<class T>
QQmlRefPointer<T>::QQmlRefPointer()
-: o(0)
+: o(0)
{
}
template<class T>
QQmlRefPointer<T>::QQmlRefPointer(T *o)
-: o(o)
+: o(o)
{
if (o) o->addref();
}
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 1ea3f25405..c49463c913 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -83,10 +83,10 @@ public:
void threadEvent();
protected:
- virtual bool event(QEvent *);
+ virtual bool event(QEvent *);
private:
- struct MainObject : public QObject {
+ struct MainObject : public QObject {
MainObject(QQmlThreadPrivate *p);
virtual bool event(QEvent *e);
QQmlThreadPrivate *p;
@@ -97,8 +97,8 @@ private:
QWaitCondition _wait;
};
-QQmlThreadPrivate::MainObject::MainObject(QQmlThreadPrivate *p)
-: p(p)
+QQmlThreadPrivate::MainObject::MainObject(QQmlThreadPrivate *p)
+: p(p)
{
}
@@ -116,22 +116,22 @@ void QQmlThreadPrivate::triggerThreadEvent()
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
-bool QQmlThreadPrivate::MainObject::event(QEvent *e)
+bool QQmlThreadPrivate::MainObject::event(QEvent *e)
{
- if (e->type() == QEvent::User)
+ if (e->type() == QEvent::User)
p->mainEvent();
return QObject::event(e);
}
-
+
QQmlThreadPrivate::QQmlThreadPrivate(QQmlThread *q)
-: q(q), m_threadProcessing(false), m_mainProcessing(false), m_shutdown(false),
+: q(q), m_threadProcessing(false), m_mainProcessing(false), m_shutdown(false),
m_mainThreadWaiting(false), mainSync(0), m_mainObject(this)
{
}
bool QQmlThreadPrivate::event(QEvent *e)
{
- if (e->type() == QEvent::User)
+ if (e->type() == QEvent::User)
threadEvent();
return QThread::event(e);
}
@@ -175,7 +175,7 @@ void QQmlThreadPrivate::mainEvent()
unlock();
}
-void QQmlThreadPrivate::threadEvent()
+void QQmlThreadPrivate::threadEvent()
{
lock();
diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h
index 688fce6d5a..ee5996d9ef 100644
--- a/src/qml/qml/ftw/qqmlthread_p.h
+++ b/src/qml/qml/ftw/qqmlthread_p.h
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QThread;
class QQmlThreadPrivate;
-class QQmlThread
+class QQmlThread
{
public:
QQmlThread();
diff --git a/src/qml/qml/ftw/qrecursionwatcher_p.h b/src/qml/qml/ftw/qrecursionwatcher_p.h
index c6b3db38d4..8a8d6575da 100644
--- a/src/qml/qml/ftw/qrecursionwatcher_p.h
+++ b/src/qml/qml/ftw/qrecursionwatcher_p.h
@@ -76,7 +76,7 @@ private:
};
QRecursionNode::QRecursionNode()
-: _r(0)
+: _r(0)
{
}
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 641209d1f3..633953c81c 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -55,10 +55,10 @@
#define QML_DECLARE_TYPE(TYPE) \
Q_DECLARE_METATYPE(TYPE *) \
- Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
+ Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
#define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \
- Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
+ Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
#define QML_DECLARE_INTERFACE(INTERFACE) \
QML_DECLARE_TYPE(INTERFACE)
@@ -109,7 +109,7 @@ int qmlRegisterType()
QML_GETTYPENAMES
QQmlPrivate::RegisterType type = {
- 0,
+ 0,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
@@ -121,7 +121,7 @@ int qmlRegisterType()
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
- QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
@@ -204,7 +204,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
QML_GETTYPENAMES
QQmlPrivate::RegisterType type = {
- 0,
+ 0,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
@@ -216,7 +216,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
- QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
@@ -298,7 +298,7 @@ int qmlRegisterExtendedType()
QML_GETTYPENAMES
QQmlPrivate::RegisterType type = {
- 0,
+ 0,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
@@ -310,7 +310,7 @@ int qmlRegisterExtendedType()
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
- QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
@@ -324,20 +324,20 @@ int qmlRegisterExtendedType()
}
template<typename T, typename E>
-int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
+int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName)
{
QML_GETTYPENAMES
QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
- const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
+ const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
if (!attached) {
attached = QQmlPrivate::attachedPropertiesFunc<T>();
attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<T>();
}
QQmlPrivate::RegisterType type = {
- 0,
+ 0,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
@@ -349,7 +349,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
attached,
attachedMetaObject,
- QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
@@ -383,13 +383,13 @@ int qmlRegisterInterface(const char *typeName)
}
template<typename T>
-int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
+int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName, QQmlCustomParser *parser)
{
QML_GETTYPENAMES
QQmlPrivate::RegisterType type = {
- 0,
+ 0,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
@@ -401,7 +401,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
- QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
@@ -506,7 +506,7 @@ inline int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versio
inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
- if (url.isRelative()) {
+ if (url.isRelative()) {
// User input check must go here, because QQmlPrivate::qmlregister is also used internally for composite types
qWarning("qmlRegisterType requires absolute URLs.");
return 0;
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index ebe81d647a..7354f9af1e 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -60,7 +60,7 @@
QT_BEGIN_NAMESPACE
-class QmlObjectCreator;
+class QQmlObjectCreator;
class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding
{
@@ -152,7 +152,7 @@ private:
friend class QQmlVME;
friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>;
friend class QV4Bindings;
- friend class QmlObjectCreator;
+ friend class QQmlObjectCreator;
typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
// To save memory, we also store the rarely used weakPointer() instance in here
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 9e2fb07066..11b9353dfe 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -46,7 +46,7 @@
#include "qqmlinfo.h"
#include "qqmlcompiler_p.h"
#include "qqmldata_p.h"
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
#include <private/qqmltrace_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -146,7 +146,8 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
typeData->release();
}
- }
+ } else
+ code = scriptPrivate->script;
setNotifyOnValueChanged(true);
QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
@@ -225,7 +226,8 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
trace.addDetail("Column", columnNo);
if (!updatingFlag()) {
- QQmlBindingProfiler prof(m_url, lineNo, columnNo, QQmlProfilerService::QmlBinding);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
+ QQmlBindingProfiler prof(ep->profiler, m_url, lineNo, columnNo);
setUpdatingFlag(true);
QQmlAbstractExpression::DeleteWatcher watcher(this);
@@ -241,7 +243,6 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a);
} else {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources();
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index bc56fe1f2d..e5a0df8c32 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -50,11 +50,11 @@
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
#include <private/qv4debugservice_p.h>
#include "qqmlinfo.h"
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <QtCore/qstringbuilder.h>
#include <QtCore/qdebug.h>
@@ -356,14 +356,13 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
if (QQmlDebugService::isDebuggingEnabled())
QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->m_index).methodSignature()));
- QQmlHandlingSignalProfiler prof(s->m_expression);
-
s->m_isEvaluating = true;
- if (s->m_expression && s->m_expression->engine()) {
+ QQmlEngine *engine;
+ if (s->m_expression && (engine = s->m_expression->engine())) {
+ QQmlHandlingSignalProfiler prof(QQmlEnginePrivate::get(engine)->profiler, s->m_expression);
s->m_expression->evaluate(a);
if (s->m_expression && s->m_expression->hasError()) {
- QQmlEngine *engine = s->m_expression->engine();
QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));
}
}
diff --git a/src/qml/qml/qqmlcleanup.cpp b/src/qml/qml/qqmlcleanup.cpp
index 36f633c29f..94762d4fc7 100644
--- a/src/qml/qml/qqmlcleanup.cpp
+++ b/src/qml/qml/qqmlcleanup.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
/*!
\internal
\class QQmlCleanup
-\brief The QQmlCleanup provides a callback when a QQmlEngine is deleted.
+\brief The QQmlCleanup provides a callback when a QQmlEngine is deleted.
Any object that needs cleanup to occur before the QQmlEngine's V8 engine is
destroyed should inherit from QQmlCleanup. The clear() virtual method will be
@@ -111,7 +111,7 @@ QQmlCleanup::~QQmlCleanup()
if (prev) *prev = next;
if (next) next->prev = prev;
- prev = 0;
+ prev = 0;
next = 0;
}
diff --git a/src/qml/qml/qqmlcleanup_p.h b/src/qml/qml/qqmlcleanup_p.h
index 249ef97cc3..1f210ea7ce 100644
--- a/src/qml/qml/qqmlcleanup_p.h
+++ b/src/qml/qml/qqmlcleanup_p.h
@@ -44,7 +44,7 @@
#include <private/qtqmlglobal_p.h>
-//
+//
// W A R N I N G
// -------------
//
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
index 76bf24fe6b..75740e17e6 100644
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ b/src/qml/qml/qqmlcompileddata.cpp
@@ -88,7 +88,7 @@ int QQmlCompiledData::indexForUrl(const QUrl &data)
QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
: engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false),
- rootPropertyCache(0), compilationUnit(0), qmlUnit(0)
+ rootPropertyCache(0), compilationUnit(0), qmlUnit(0), totalBindingsCount(0), totalParserStatusCount(0)
{
Q_ASSERT(engine);
@@ -117,15 +117,17 @@ QQmlCompiledData::~QQmlCompiledData()
types.at(ii).typePropertyCache->release();
}
- for (QHash<int, TypeReference>::Iterator resolvedType = resolvedTypes.begin(), end = resolvedTypes.end();
+ for (QHash<int, TypeReference*>::Iterator resolvedType = resolvedTypes.begin(), end = resolvedTypes.end();
resolvedType != end; ++resolvedType) {
- if (resolvedType->component)
- resolvedType->component->release();
- if (resolvedType->typePropertyCache)
- resolvedType->typePropertyCache->release();
+ if ((*resolvedType)->component)
+ (*resolvedType)->component->release();
+ if ((*resolvedType)->typePropertyCache)
+ (*resolvedType)->typePropertyCache->release();
}
+ qDeleteAll(resolvedTypes);
+ resolvedTypes.clear();
- for (int ii = 0; ii < propertyCaches.count(); ++ii)
+ for (int ii = 0; ii < propertyCaches.count(); ++ii)
if (propertyCaches.at(ii))
propertyCaches.at(ii)->release();
@@ -161,7 +163,7 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
/*!
Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
*/
-QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngine *engine)
+QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngine *engine)
{
if (typePropertyCache) {
return typePropertyCache;
@@ -232,13 +234,13 @@ int QQmlCompiledData::addInstructionHelper(QQmlInstruction::Type type, QQmlInstr
return ptrOffset;
}
-int QQmlCompiledData::nextInstructionIndex()
-{
+int QQmlCompiledData::nextInstructionIndex()
+{
return bytecode.size();
}
-QQmlInstruction *QQmlCompiledData::instruction(int index)
-{
+QQmlInstruction *QQmlCompiledData::instruction(int index)
+{
return (QQmlInstruction *)(bytecode.constData() + index);
}
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 71e803a4c8..b26b5530a3 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -102,7 +102,7 @@ QQmlCompiler::QQmlCompiler(QQmlPool *pool)
: compileState(0), pool(pool), output(0), engine(0), enginePrivate(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1),
cachedTranslationContextIndex(-1), componentStats(0)
{
- if (compilerStatDump())
+ if (compilerStatDump())
componentStats = pool->New<ComponentStats>();
}
@@ -807,7 +807,7 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
this->unit = unit;
this->unitRoot = root;
this->output = out;
- this->jsModule.reset(new QQmlJS::V4IR::Module(enginePrivate->v4engine()->debugger));
+ this->jsModule.reset(new IR::Module(enginePrivate->v4engine()->debugger));
this->jsModule->isQmlModule = true;
// Compile types
@@ -933,7 +933,7 @@ void QQmlCompiler::compileTree(QQmlScript::Object *tree)
if (!jsModule->functions.isEmpty()) {
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Compiler::JSUnitGenerator jsUnitGenerator(jsModule.data());
- QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(enginePrivate, v4->executableAllocator, jsModule.data(), &jsUnitGenerator));
+ QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(enginePrivate, v4->executableAllocator, jsModule.data(), &jsUnitGenerator));
isel->setUseFastLookups(false);
QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/true);
output->compilationUnit = jsUnit;
@@ -1007,13 +1007,13 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
COMPILE_CHECK(buildComponent(obj, ctxt));
return true;
- }
+ }
if (tr.component) {
- typedef QQmlInstruction I;
+ typedef QQmlInstruction I;
const I *init = ((const I *)tr.component->bytecode.constData());
Q_ASSERT(init && tr.component->instructionType(init) == QQmlInstruction::Init);
-
+
// Adjust stack depths to include nested components
compileState->objectDepth.pushPop(init->init.objectStackSize);
compileState->listDepth.pushPop(init->init.listStackSize);
@@ -1027,7 +1027,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
BindingContext objCtxt(obj);
// Create the synthesized meta object, ignoring aliases
- COMPILE_CHECK(checkDynamicMeta(obj));
+ COMPILE_CHECK(checkDynamicMeta(obj));
COMPILE_CHECK(mergeDynamicMetaProperties(obj));
COMPILE_CHECK(buildDynamicMeta(obj, Normal));
@@ -1051,20 +1051,20 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
// Must do id property first. This is to ensure that the id given to any
// id reference created matches the order in which the objects are
// instantiated
- for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+ for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
if (prop->name() == id_string) {
COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
break;
}
}
- // Merge
- Property *defaultProperty = 0;
- Property *skipProperty = 0;
+ // Merge
+ QQmlScript::Property *defaultProperty = 0;
+ QQmlScript::Property *skipProperty = 0;
if (obj->defaultProperty) {
defaultProperty = obj->defaultProperty;
- Property *explicitProperty = 0;
+ QQmlScript::Property *explicitProperty = 0;
QString defaultPropertyName = obj->metatype->defaultPropertyName();
if (!defaultPropertyName.isEmpty()) {
@@ -1072,7 +1072,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
QHashedStringRef r(*s);
if (obj->propertiesHashField.test(r.hash())) {
- for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
+ for (QQmlScript::Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
if (ep->name() == r) {
explicitProperty = ep;
break;
@@ -1089,16 +1089,16 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
skipProperty = explicitProperty; // We merge the values into defaultProperty
// Find the correct insertion point
- Value *insertPos = 0;
+ QQmlScript::Value *insertPos = 0;
- for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = defaultProperty->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
if (!(v->location.start < explicitProperty->values.first()->location.start))
break;
insertPos = v;
}
defaultProperty->values.insertAfter(insertPos, explicitProperty->values);
- }
+ }
}
QQmlCustomParser *cp = 0;
@@ -1106,7 +1106,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
cp = output->types.at(obj->type).type->customParser();
// Build all explicit properties specified
- for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+ for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
if (prop == skipProperty)
continue;
@@ -1144,7 +1144,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
// Build the default property
if (defaultProperty) {
- Property *prop = defaultProperty;
+ QQmlScript::Property *prop = defaultProperty;
bool canDefer = false;
if (isCustomParser) {
@@ -1282,7 +1282,7 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj, bool parentToSuper)
void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
{
- for (Property *prop = obj->scriptStringProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->scriptStringProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
Q_ASSERT(prop->scriptStringScope != -1);
const QString &script = prop->values.first()->value.asScript();
Instruction::StoreScriptString ss;
@@ -1299,7 +1299,7 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
}
bool seenDefer = false;
- for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->valueProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
if (prop->isDeferred) {
seenDefer = true;
continue;
@@ -1316,12 +1316,12 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
Instruction::DeferInit dinit;
// XXX - these are now massive over allocations
dinit.bindingsSize = compileState->totalBindingsCount;
- dinit.parserStatusSize = compileState->parserStatusCount;
- dinit.objectStackSize = compileState->objectDepth.maxDepth();
- dinit.listStackSize = compileState->listDepth.maxDepth();
+ dinit.parserStatusSize = compileState->parserStatusCount;
+ dinit.objectStackSize = compileState->objectDepth.maxDepth();
+ dinit.listStackSize = compileState->listDepth.maxDepth();
output->addInstruction(dinit);
- for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->valueProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
if (!prop->isDeferred)
continue;
genValueProperty(prop, obj);
@@ -1333,11 +1333,11 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex;
}
- for (Property *prop = obj->signalProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->signalProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
QQmlScript::Value *v = prop->values.first();
- if (v->type == Value::SignalObject) {
+ if (v->type == QQmlScript::Value::SignalObject) {
genObject(v->object);
@@ -1346,7 +1346,7 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
assign.signal = output->indexForString(prop->name().toString());
output->addInstruction(assign);
- } else if (v->type == Value::SignalExpression) {
+ } else if (v->type == QQmlScript::Value::SignalExpression) {
Instruction::StoreSignal store;
store.runtimeFunctionIndex = compileState->jsCompileData[v->signalData.signalScopeObject].runtimeFunctionIndices.at(v->signalData.functionIndex);
@@ -1363,7 +1363,7 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
}
- for (Property *prop = obj->attachedProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->attachedProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
Instruction::FetchAttached fetch;
fetch.id = prop->index;
fetch.line = prop->location.start.line;
@@ -1375,10 +1375,11 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
output->addInstruction(pop);
}
- for (Property *prop = obj->groupedProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->groupedProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
Instruction::FetchObject fetch;
fetch.property = prop->index;
fetch.line = prop->location.start.line;
+ fetch.column = prop->location.start.column;
output->addInstruction(fetch);
if (!prop->value->synthdata.isEmpty()) {
@@ -1398,25 +1399,25 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
output->addInstruction(pop);
}
- for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->valueTypeProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
if (!prop->isAlias)
genValueTypeProperty(obj, prop);
}
- for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
- if (prop->isDeferred)
+ for (QQmlScript::Property *prop = obj->valueProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
+ if (prop->isDeferred)
continue;
if (prop->isAlias)
genValueProperty(prop, obj);
}
- for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
+ for (QQmlScript::Property *prop = obj->valueTypeProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
if (prop->isAlias)
genValueTypeProperty(obj, prop);
}
}
-void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *prop)
+void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj, QQmlScript::Property *prop)
{
Instruction::FetchValueType fetch;
fetch.property = prop->index;
@@ -1426,7 +1427,7 @@ void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Prop
if (obj->type == -1 || output->types.at(obj->type).component) {
// We only have to do this if this is a composite type. If it is a builtin
// type it can't possibly already have bindings that need to be cleared.
- for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
+ for (QQmlScript::Property *vprop = prop->value->valueProperties.first(); vprop; vprop = QQmlScript::Object::PropertyList::next(vprop)) {
if (!vprop->values.isEmpty()) {
Q_ASSERT(vprop->index >= 0 && vprop->index < 32);
fetch.bindingSkipList |= (1 << vprop->index);
@@ -1436,7 +1437,7 @@ void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Prop
output->addInstruction(fetch);
- for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
+ for (QQmlScript::Property *vprop = prop->value->valueProperties.first(); vprop; vprop = QQmlScript::Object::PropertyList::next(vprop)) {
genPropertyAssignment(vprop, prop->value, prop);
}
@@ -1485,7 +1486,7 @@ void QQmlCompiler::genComponent(QQmlScript::Object *obj)
Instruction::Done done;
output->addInstruction(done);
- output->instruction(createInstruction)->createComponent.count =
+ output->instruction(createInstruction)->createComponent.count =
output->nextInstructionIndex() - nextInstructionIndex;
compileState = oldCompileState;
@@ -1512,16 +1513,16 @@ bool QQmlCompiler::buildComponent(QQmlScript::Object *obj,
compileState->objectDepth.push();
// Find, check and set the "id" property (if any)
- Property *idProp = 0;
+ QQmlScript::Property *idProp = 0;
if (obj->properties.isMany() ||
(obj->properties.isOne() && obj->properties.first()->name() != id_string))
COMPILE_EXCEPTION(obj->properties.first(), tr("Component elements may not contain properties other than id"));
-
+
if (!obj->properties.isEmpty())
idProp = obj->properties.first();
if (idProp) {
- if (idProp->value || idProp->values.isMany() || idProp->values.first()->object)
+ if (idProp->value || idProp->values.isMany() || idProp->values.first()->object)
COMPILE_EXCEPTION(idProp, tr("Invalid component id specification"));
COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive()))
@@ -1605,7 +1606,7 @@ bool QQmlCompiler::buildSubObject(QQmlScript::Object *obj, const BindingContext
Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
// sub-context
- for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+ for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
if (isSignalPropertyName(prop->name())) {
COMPILE_CHECK(buildSignal(prop, obj, ctxt));
} else {
@@ -1737,9 +1738,9 @@ bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *o
if (prop->values.first()->object) {
COMPILE_CHECK(buildObject(prop->values.first()->object, ctxt));
- prop->values.first()->type = Value::SignalObject;
+ prop->values.first()->type = QQmlScript::Value::SignalObject;
} else {
- prop->values.first()->type = Value::SignalExpression;
+ prop->values.first()->type = QQmlScript::Value::SignalExpression;
if (!prop->values.first()->value.isScript())
COMPILE_EXCEPTION(prop, tr("Cannot assign a value to a signal (expecting a script to be run)"));
@@ -1791,7 +1792,7 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
QQmlScript::Object *obj,
const BindingContext &ctxt)
{
- if (prop->isEmpty())
+ if (prop->isEmpty())
COMPILE_EXCEPTION(prop, tr("Empty property assignment"));
if (isAttachedPropertyName(prop->name())) {
@@ -1809,7 +1810,7 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
unit->imports().resolveType(prop->name(), &type, 0, 0, &typeNamespace);
if (typeNamespace) {
- COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj,
+ COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj,
ctxt));
return true;
} else if (!type || !type->attachedPropertiesType()) {
@@ -1853,13 +1854,13 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
// We can't error here as the "id" property does not require a
// successful index resolution
- if (prop->index != -1)
+ if (prop->index != -1)
prop->type = prop->core.propType;
// Check if this is an alias
- if (prop->index != -1 &&
- prop->parent &&
- prop->parent->type != -1 &&
+ if (prop->index != -1 &&
+ prop->parent &&
+ prop->parent->type != -1 &&
output->types.at(prop->parent->type).component) {
QQmlPropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache;
@@ -1867,7 +1868,7 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
prop->isAlias = true;
}
- if (prop->index != -1 && !prop->values.isEmpty())
+ if (prop->index != -1 && !prop->values.isEmpty())
prop->parent->setBindingBit(prop->index);
}
@@ -1922,17 +1923,17 @@ bool QQmlCompiler::buildPropertyInNamespace(QQmlImportNamespace *ns,
if (!nsProp->value)
COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace"));
- for (Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) {
+ for (QQmlScript::Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) {
if (!isAttachedPropertyName(prop->name()))
- COMPILE_EXCEPTION(prop, tr("Not an attached property name"));
+ COMPILE_EXCEPTION(prop, tr("Expected type name"));
// Setup attached property data
QQmlType *type = 0;
unit->imports().resolveType(ns, prop->name(), &type, 0, 0);
- if (!type || !type->attachedPropertiesType())
+ if (!type || !type->attachedPropertiesType())
COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
if (!prop->value)
@@ -1969,9 +1970,9 @@ void QQmlCompiler::genListProperty(QQmlScript::Property *prop,
fetch.type = listType;
output->addInstruction(fetch);
- for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- if (v->type == Value::CreatedObject) {
+ if (v->type == QQmlScript::Value::CreatedObject) {
genObject(v->object);
if (listTypeIsInterface) {
@@ -1983,7 +1984,7 @@ void QQmlCompiler::genListProperty(QQmlScript::Property *prop,
output->addInstruction(store);
}
- } else if (v->type == Value::PropertyBinding) {
+ } else if (v->type == QQmlScript::Value::PropertyBinding) {
genBindingAssignment(v, prop, obj);
@@ -1999,13 +2000,13 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
QQmlScript::Object *obj,
QQmlScript::Property *valueTypeProperty)
{
- for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- Q_ASSERT(v->type == Value::CreatedObject ||
- v->type == Value::PropertyBinding ||
- v->type == Value::Literal);
+ Q_ASSERT(v->type == QQmlScript::Value::CreatedObject ||
+ v->type == QQmlScript::Value::PropertyBinding ||
+ v->type == QQmlScript::Value::Literal);
- if (v->type == Value::CreatedObject) {
+ if (v->type == QQmlScript::Value::CreatedObject) {
genObject(v->object);
@@ -2039,11 +2040,11 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
output->addInstruction(store);
}
- } else if (v->type == Value::PropertyBinding) {
+ } else if (v->type == QQmlScript::Value::PropertyBinding) {
genBindingAssignment(v, prop, obj, valueTypeProperty);
- } else if (v->type == Value::Literal) {
+ } else if (v->type == QQmlScript::Value::Literal) {
genLiteralAssignment(prop, v);
@@ -2051,12 +2052,12 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
}
- for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- Q_ASSERT(v->type == Value::ValueSource ||
- v->type == Value::ValueInterceptor);
+ Q_ASSERT(v->type == QQmlScript::Value::ValueSource ||
+ v->type == QQmlScript::Value::ValueInterceptor);
- if (v->type == Value::ValueSource) {
+ if (v->type == QQmlScript::Value::ValueSource) {
genObject(v->object, valueTypeProperty?true:false);
Instruction::StoreValueSource store;
@@ -2068,7 +2069,7 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
store.castValue = valueType->propertyValueSourceCast();
output->addInstruction(store);
- } else if (v->type == Value::ValueInterceptor) {
+ } else if (v->type == QQmlScript::Value::ValueInterceptor) {
genObject(v->object, valueTypeProperty?true:false);
Instruction::StoreValueInterceptor store;
@@ -2100,7 +2101,7 @@ bool QQmlCompiler::buildIdProperty(QQmlScript::Property *prop,
if (compileState->ids.value(val))
COMPILE_EXCEPTION(prop, tr("id is not unique"));
- prop->values.first()->type = Value::Id;
+ prop->values.first()->type = QQmlScript::Value::Id;
obj->id = val;
addId(val, obj);
@@ -2132,7 +2133,7 @@ void QQmlCompiler::saveComponentState()
compileState->root->componentCompileState = compileState;
- if (componentStats)
+ if (componentStats)
componentStats->savedComponentStats.append(componentStats->componentStat);
}
@@ -2185,7 +2186,7 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
if (prop->type >= 0 && valueType) {
if (!prop->values.isEmpty()) {
// Only error if we are assigning values, and not e.g. a property interceptor
- for (Property *dotProp = prop->value->properties.first(); dotProp; dotProp = prop->value->properties.next(dotProp)) {
+ for (QQmlScript::Property *dotProp = prop->value->properties.first(); dotProp; dotProp = prop->value->properties.next(dotProp)) {
if (!dotProp->values.isEmpty()) {
if (prop->values.first()->location < prop->value->location) {
COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value"));
@@ -2201,7 +2202,7 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
}
if (prop->isAlias) {
- for (Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) {
+ for (QQmlScript::Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) {
vtProp->isAlias = true;
}
}
@@ -2213,14 +2214,14 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
// assignment to the value type as a whole. Therefore we need to look
// for (and build) assignments to the entire value type before looking
// for any onValue assignments.
- for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
if (v->object) {
COMPILE_EXCEPTION(v->object, tr("Objects cannot be assigned to value types"));
}
COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
}
- for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
Q_ASSERT(v->object);
COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
}
@@ -2235,7 +2236,7 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
if (!prop->value->metatype)
COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
- if (!prop->values.isEmpty())
+ if (!prop->values.isEmpty())
COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign a value directly to a grouped property"));
obj->addGroupedProperty(prop);
@@ -2261,10 +2262,10 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
COMPILE_EXCEPTION(obj, tr("Invalid property use"));
obj->metatype = enginePrivate->cache(type);
- for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
+ for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
QQmlPropertyData *d = property(obj, prop->name());
- if (d == 0)
+ if (d == 0)
COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
prop->index = d->coreIndex;
@@ -2292,7 +2293,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment));
if (isEnumAssignment) {
- value->type = Value::Literal;
+ value->type = QQmlScript::Value::Literal;
} else {
JSBindingReference *reference = pool->New<JSBindingReference>();
reference->expression = value->value;
@@ -2301,18 +2302,18 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
reference->bindingContext = ctxt;
reference->bindingContext.owner++;
addBindingReference(reference);
- value->type = Value::PropertyBinding;
+ value->type = QQmlScript::Value::PropertyBinding;
}
} else {
COMPILE_CHECK(testLiteralAssignment(prop, value));
- value->type = Value::Literal;
+ value->type = QQmlScript::Value::Literal;
}
}
- for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
Q_ASSERT(v->object);
- COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt));
+ COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt));
}
obj->addValueProperty(prop);
@@ -2324,7 +2325,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
}
// Build assignments to QML lists. QML lists are properties of type
-// QQmlListProperty<T>. List properties can accept a list of
+// QQmlListProperty<T>. List properties can accept a list of
// objects, or a single binding.
bool QQmlCompiler::buildListProperty(QQmlScript::Property *prop,
QQmlScript::Object *obj,
@@ -2342,9 +2343,9 @@ bool QQmlCompiler::buildListProperty(QQmlScript::Property *prop,
bool listTypeIsInterface = QQmlMetaType::isInterface(listType);
bool assignedBinding = false;
- for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
if (v->object) {
- v->type = Value::CreatedObject;
+ v->type = QQmlScript::Value::CreatedObject;
COMPILE_CHECK(buildObject(v->object, ctxt));
// We check object coercian here. We check interface assignment
@@ -2377,7 +2378,7 @@ bool QQmlCompiler::buildScriptStringProperty(QQmlScript::Property *prop,
const BindingContext &ctxt)
{
if (prop->values.isMany())
- COMPILE_EXCEPTION(prop->values.first()->nextValue, tr( "Cannot assign multiple values to a script property"));
+ COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a script property"));
if (prop->values.first()->object)
COMPILE_EXCEPTION(prop->values.first(), tr( "Invalid property assignment: script expected"));
@@ -2398,7 +2399,7 @@ bool QQmlCompiler::buildPropertyAssignment(QQmlScript::Property *prop,
if (prop->values.isMany())
COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a singular property") );
- for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
if (v->object) {
COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
@@ -2410,7 +2411,7 @@ bool QQmlCompiler::buildPropertyAssignment(QQmlScript::Property *prop,
}
}
- for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
+ for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
Q_ASSERT(v->object);
COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
}
@@ -2435,14 +2436,14 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
// Assigning an object to an interface ptr property
COMPILE_CHECK(buildObject(v->object, ctxt));
- v->type = Value::CreatedObject;
+ v->type = QQmlScript::Value::CreatedObject;
} else if (prop->type == QMetaType::QVariant) {
// Assigning an object to a QVariant
COMPILE_CHECK(buildObject(v->object, ctxt));
- v->type = Value::CreatedObject;
+ v->type = QQmlScript::Value::CreatedObject;
} else {
// Normally buildObject() will set this up, but we need the static
// meta object earlier to test for assignability. It doesn't matter
@@ -2471,15 +2472,15 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
// Simple assignment
COMPILE_CHECK(buildObject(v->object, ctxt));
- v->type = Value::CreatedObject;
+ v->type = QQmlScript::Value::CreatedObject;
} else if (propertyMetaObject && propertyMetaObject->metaObject() == &QQmlComponent::staticMetaObject) {
// Automatic "Component" insertion
QQmlScript::Object *root = v->object;
- QQmlScript::Object *component = pool->New<Object>();
+ QQmlScript::Object *component = pool->New<QQmlScript::Object>();
component->type = componentTypeRef();
component->metatype = enginePrivate->cache(&QQmlComponent::staticMetaObject);
component->location = root->location;
- QQmlScript::Value *componentValue = pool->New<Value>();
+ QQmlScript::Value *componentValue = pool->New<QQmlScript::Value>();
componentValue->object = root;
component->getDefaultProperty()->addValue(componentValue);
v->object = component;
@@ -2535,7 +2536,7 @@ bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
buildDynamicMeta(baseObj, ForceCreation);
- v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ v->type = isPropertyValue ? QQmlScript::Value::ValueSource : QQmlScript::Value::ValueInterceptor;
} else {
COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(elementName(v->object)).arg(prop->name().toString()));
}
@@ -2558,7 +2559,7 @@ bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
bool isEnumAssignment = false;
COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment));
if (isEnumAssignment) {
- v->type = Value::Literal;
+ v->type = QQmlScript::Value::Literal;
return true;
}
}
@@ -2571,7 +2572,7 @@ bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
COMPILE_CHECK(testLiteralAssignment(prop, v));
- v->type = Value::Literal;
+ v->type = QQmlScript::Value::Literal;
}
return true;
@@ -2615,9 +2616,9 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
if (isIntProp) {
// Allow enum assignment to ints.
bool ok;
- int enumval = evaluateEnum(typeName, enumValue.toUtf8(), &ok);
+ int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok);
if (ok) {
- v->type = Value::Literal;
+ v->type = QQmlScript::Value::Literal;
v->value = QQmlScript::Variant((double)enumval);
*isAssignment = true;
}
@@ -2659,53 +2660,21 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
if (!ok)
return true;
- v->type = Value::Literal;
+ v->type = QQmlScript::Value::Literal;
v->value = QQmlScript::Variant((double)value);
*isAssignment = true;
return true;
}
-// Similar logic to above, but not knowing target property.
-int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const
-{
- Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
- *ok = false;
-
- if (scope != QLatin1String("Qt")) {
- QQmlType *type = 0;
- unit->imports().resolveType(scope, &type, 0, 0, 0);
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
- }
-
- const QMetaObject *mo = StaticQtMetaObject::get();
- int i = mo->enumeratorCount();
- while (i--) {
- int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
- if (*ok)
- return v;
- }
- return -1;
-}
-
-const QMetaObject *QQmlCompiler::resolveType(const QString& name) const
-{
- QQmlType *qmltype = 0;
- if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0))
- return 0;
- if (!qmltype)
- return 0;
- return qmltype->metaObject();
-}
-
-int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, const BindingContext &ctxt)
+QQmlBinding::Identifier QQmlCompiler::bindingIdentifier(const Variant &value, const QString &name, QQmlCustomParser *customParser)
{
JSBindingReference *reference = pool->New<JSBindingReference>();
reference->expression = value;
- reference->property = pool->New<Property>();
+ reference->property = pool->New<QQmlScript::Property>();
reference->property->setName(name);
reference->value = 0;
- reference->bindingContext = ctxt;
+ reference->bindingContext = QQmlCompilerTypes::BindingContext(customParser->object);
reference->bindingContext.owner++;
// Unfortunately this is required for example for PropertyChanges where the bindings
// will be executed in the dynamic scope of the target, so we can't resolve any lookups
@@ -2743,7 +2712,7 @@ bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
QHashField methodNames;
// Check properties
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
const QQmlScript::Object::DynamicProperty &prop = *p;
if (prop.isDefaultProperty) {
@@ -2753,7 +2722,7 @@ bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
}
if (propNames.testAndSet(prop.name.hash())) {
- for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p;
+ for (QQmlScript::Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p;
p2 = obj->dynamicProperties.next(p2)) {
if (p2->name == prop.name) {
COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
@@ -2776,11 +2745,11 @@ bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
}
}
- for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
const QQmlScript::Object::DynamicSignal &currSig = *s;
if (methodNames.testAndSet(currSig.name.hash())) {
- for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s;
+ for (QQmlScript::Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s;
s2 = obj->dynamicSignals.next(s2)) {
if (s2->name == currSig.name)
COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
@@ -2793,16 +2762,16 @@ bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
}
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
const QQmlScript::Object::DynamicSlot &currSlot = *s;
if (methodNames.testAndSet(currSlot.name.hash())) {
- for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2;
+ for (QQmlScript::Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2;
s2 = obj->dynamicSignals.next(s2)) {
if (s2->name == currSlot.name)
COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
}
- for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s;
+ for (QQmlScript::Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s;
s2 = obj->dynamicSlots.next(s2)) {
if (s2->name == currSlot.name)
COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
@@ -2820,18 +2789,18 @@ bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj)
{
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
p = obj->dynamicProperties.next(p)) {
- if (!p->defaultValue || p->type == Object::DynamicProperty::Alias)
+ if (!p->defaultValue || p->type == QQmlScript::Object::DynamicProperty::Alias)
continue;
- Property *property = 0;
+ QQmlScript::Property *property = 0;
if (p->isDefaultProperty) {
property = obj->getDefaultProperty();
} else {
property = obj->getProperty(p->name);
- if (!property->values.isEmpty())
+ if (!property->values.isEmpty())
COMPILE_EXCEPTION(property, tr("Property value set multiple times"));
}
@@ -2880,29 +2849,29 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
Q_ASSERT(obj->synthCache == 0);
struct TypeData {
- Object::DynamicProperty::Type dtype;
+ QQmlScript::Object::DynamicProperty::Type dtype;
int metaType;
} builtinTypes[] = {
- { Object::DynamicProperty::Var, QMetaType::QVariant },
- { Object::DynamicProperty::Variant, QMetaType::QVariant },
- { Object::DynamicProperty::Int, QMetaType::Int },
- { Object::DynamicProperty::Bool, QMetaType::Bool },
- { Object::DynamicProperty::Real, QMetaType::Double },
- { Object::DynamicProperty::String, QMetaType::QString },
- { Object::DynamicProperty::Url, QMetaType::QUrl },
- { Object::DynamicProperty::Color, QMetaType::QColor },
- { Object::DynamicProperty::Font, QMetaType::QFont },
- { Object::DynamicProperty::Time, QMetaType::QTime },
- { Object::DynamicProperty::Date, QMetaType::QDate },
- { Object::DynamicProperty::DateTime, QMetaType::QDateTime },
- { Object::DynamicProperty::Rect, QMetaType::QRectF },
- { Object::DynamicProperty::Point, QMetaType::QPointF },
- { Object::DynamicProperty::Size, QMetaType::QSizeF },
- { Object::DynamicProperty::Vector2D, QMetaType::QVector2D },
- { Object::DynamicProperty::Vector3D, QMetaType::QVector3D },
- { Object::DynamicProperty::Vector4D, QMetaType::QVector4D },
- { Object::DynamicProperty::Matrix4x4, QMetaType::QMatrix4x4 },
- { Object::DynamicProperty::Quaternion, QMetaType::QQuaternion }
+ { QQmlScript::Object::DynamicProperty::Var, qMetaTypeId<QJSValue>() },
+ { QQmlScript::Object::DynamicProperty::Variant, QMetaType::QVariant },
+ { QQmlScript::Object::DynamicProperty::Int, QMetaType::Int },
+ { QQmlScript::Object::DynamicProperty::Bool, QMetaType::Bool },
+ { QQmlScript::Object::DynamicProperty::Real, QMetaType::Double },
+ { QQmlScript::Object::DynamicProperty::String, QMetaType::QString },
+ { QQmlScript::Object::DynamicProperty::Url, QMetaType::QUrl },
+ { QQmlScript::Object::DynamicProperty::Color, QMetaType::QColor },
+ { QQmlScript::Object::DynamicProperty::Font, QMetaType::QFont },
+ { QQmlScript::Object::DynamicProperty::Time, QMetaType::QTime },
+ { QQmlScript::Object::DynamicProperty::Date, QMetaType::QDate },
+ { QQmlScript::Object::DynamicProperty::DateTime, QMetaType::QDateTime },
+ { QQmlScript::Object::DynamicProperty::Rect, QMetaType::QRectF },
+ { QQmlScript::Object::DynamicProperty::Point, QMetaType::QPointF },
+ { QQmlScript::Object::DynamicProperty::Size, QMetaType::QSizeF },
+ { QQmlScript::Object::DynamicProperty::Vector2D, QMetaType::QVector2D },
+ { QQmlScript::Object::DynamicProperty::Vector3D, QMetaType::QVector3D },
+ { QQmlScript::Object::DynamicProperty::Vector4D, QMetaType::QVector4D },
+ { QQmlScript::Object::DynamicProperty::Matrix4x4, QMetaType::QMatrix4x4 },
+ { QQmlScript::Object::DynamicProperty::Quaternion, QMetaType::QQuaternion }
};
static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
@@ -2937,12 +2906,12 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
int aliasCount = 0;
int varPropCount = 0;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
p = obj->dynamicProperties.next(p)) {
- if (p->type == Object::DynamicProperty::Alias)
+ if (p->type == QQmlScript::Object::DynamicProperty::Alias)
aliasCount++;
- else if (p->type == Object::DynamicProperty::Var)
+ else if (p->type == QQmlScript::Object::DynamicProperty::Var)
varPropCount++;
if (p->name.isLatin1()) {
@@ -2956,14 +2925,14 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
}
- for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
if (s->name.isLatin1()) {
s->nameIndex = cStringNameCount;
cStringNameCount += s->name.length();
}
}
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
if (s->name.isLatin1()) {
s->nameIndex = cStringNameCount;
cStringNameCount += s->name.length();
@@ -2975,7 +2944,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
cache->_dynamicStringData.resize(cStringNameCount);
cStringData = cache->_dynamicStringData.data();
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
p = obj->dynamicProperties.next(p)) {
if (p->nameIndex == -1) continue;
@@ -2987,7 +2956,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
*myData++ = 'g'; *myData++ = 'e'; *myData++ = 'd';
}
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
if (s->nameIndex == -1) continue;
@@ -2996,7 +2965,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
*myData++ = s->name.at(ii).unicode();
}
- for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s;
+ for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s;
s = obj->dynamicSignals.next(s)) {
if (s->nameIndex == -1) continue;
@@ -3048,13 +3017,13 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
if (ii == NSS_Var && varPropCount == 0) continue;
else if (ii == NSS_Alias && aliasCount == 0) continue;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
p = obj->dynamicProperties.next(p)) {
- if ((ii == NSS_Normal && (p->type == Object::DynamicProperty::Alias ||
- p->type == Object::DynamicProperty::Var)) ||
- ((ii == NSS_Var) && (p->type != Object::DynamicProperty::Var)) ||
- ((ii == NSS_Alias) && (p->type != Object::DynamicProperty::Alias)))
+ if ((ii == NSS_Normal && (p->type == QQmlScript::Object::DynamicProperty::Alias ||
+ p->type == QQmlScript::Object::DynamicProperty::Var)) ||
+ ((ii == NSS_Var) && (p->type != QQmlScript::Object::DynamicProperty::Var)) ||
+ ((ii == NSS_Alias) && (p->type != QQmlScript::Object::DynamicProperty::Alias)))
continue;
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
@@ -3074,7 +3043,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
}
// Dynamic signals
- for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
int paramCount = s->parameterNames.count();
QList<QByteArray> names;
@@ -3090,7 +3059,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
names.append(s->parameterNames.at(i).toString().toUtf8());
} else {
// lazily resolved type
- Q_ASSERT(s->parameterTypes.at(i) == Object::DynamicProperty::Custom);
+ Q_ASSERT(s->parameterTypes.at(i) == QQmlScript::Object::DynamicProperty::Custom);
QQmlType *qmltype = 0;
if (!unit->imports().resolveType(s->parameterTypeNames.at(i).toString(), &qmltype, 0, 0, 0))
COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(s->parameterTypeNames.at(i).toString()));
@@ -3141,7 +3110,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
// Dynamic slots
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
int paramCount = s->parameterNames.count();
quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
@@ -3168,11 +3137,11 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
// Dynamic properties (except var and aliases)
int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
p = obj->dynamicProperties.next(p)) {
- if (p->type == Object::DynamicProperty::Alias ||
- p->type == Object::DynamicProperty::Var)
+ if (p->type == QQmlScript::Object::DynamicProperty::Alias ||
+ p->type == QQmlScript::Object::DynamicProperty::Var)
continue;
int propertyType = 0;
@@ -3183,11 +3152,11 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
propertyType = builtinTypes[p->type].metaType;
vmePropertyType = propertyType;
- if (p->type == Object::DynamicProperty::Variant)
+ if (p->type == QQmlScript::Object::DynamicProperty::Variant)
propertyFlags |= QQmlPropertyData::IsQVariant;
} else {
- Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
- p->type == Object::DynamicProperty::Custom);
+ Q_ASSERT(p->type == QQmlScript::Object::DynamicProperty::CustomList ||
+ p->type == QQmlScript::Object::DynamicProperty::Custom);
QQmlType *qmltype = 0;
if (!unit->imports().resolveType(p->customType.toString(), &qmltype, 0, 0, 0))
@@ -3201,7 +3170,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
QQmlCompiledData *data = tdata->compiledData();
- if (p->type == Object::DynamicProperty::Custom) {
+ if (p->type == QQmlScript::Object::DynamicProperty::Custom) {
propertyType = data->metaTypeId;
vmePropertyType = QMetaType::QObjectStar;
} else {
@@ -3211,7 +3180,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
tdata->release();
} else {
- if (p->type == Object::DynamicProperty::Custom) {
+ if (p->type == QQmlScript::Object::DynamicProperty::Custom) {
propertyType = qmltype->typeId();
vmePropertyType = QMetaType::QObjectStar;
} else {
@@ -3220,13 +3189,13 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
}
}
- if (p->type == Object::DynamicProperty::Custom)
+ if (p->type == QQmlScript::Object::DynamicProperty::Custom)
propertyFlags |= QQmlPropertyData::IsQObjectDerived;
else
propertyFlags |= QQmlPropertyData::IsQList;
}
- if (!p->isReadOnly && p->type != Object::DynamicProperty::CustomList)
+ if (!p->isReadOnly && p->type != QQmlScript::Object::DynamicProperty::CustomList)
propertyFlags |= QQmlPropertyData::IsWritable;
if (p->nameIndex != -1) {
@@ -3250,10 +3219,10 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
}
// Now do var properties
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p && varPropCount;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p && varPropCount;
p = obj->dynamicProperties.next(p)) {
- if (p->type != Object::DynamicProperty::Var)
+ if (p->type != QQmlScript::Object::DynamicProperty::Var)
continue;
quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
@@ -3285,7 +3254,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
// Dynamic slot data - comes after the property data
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
VMD::MethodData methodData = { /*runtimeFunctionIndex*/ 0, // To be filled in later
s->parameterNames.count(),
s->location.start.line };
@@ -3327,10 +3296,10 @@ bool QQmlCompiler::buildDynamicMetaAliases(QQmlScript::Object *obj)
int effectivePropertyIndex = cache->propertyIndexCacheStart + cache->propertyIndexCache.count();
int effectiveAliasIndex = 0;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
p = obj->dynamicProperties.next(p)) {
- if (p->type != Object::DynamicProperty::Alias)
+ if (p->type != QQmlScript::Object::DynamicProperty::Alias)
continue;
if (!p->defaultValue)
@@ -3488,7 +3457,7 @@ bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
Q_ASSERT(prop->parent->metatype);
if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
- COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
+ COMPILE_EXCEPTION(value, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
JSBindingReference *reference = pool->New<JSBindingReference>();
reference->expression = value->value;
@@ -3496,7 +3465,7 @@ bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
reference->value = value;
reference->bindingContext = ctxt;
addBindingReference(reference);
- value->type = Value::PropertyBinding;
+ value->type = QQmlScript::Value::PropertyBinding;
return true;
}
@@ -3534,7 +3503,7 @@ bool QQmlCompiler::buildLiteralBinding(QQmlScript::Value *v,
reference->text = text;
reference->n = n;
v->bindingReference = reference;
- v->type = Value::PropertyBinding;
+ v->type = QQmlScript::Value::PropertyBinding;
return true;
}
@@ -3563,7 +3532,7 @@ bool QQmlCompiler::buildLiteralBinding(QQmlScript::Value *v,
reference->comment = comment;
reference->n = n;
v->bindingReference = reference;
- v->type = Value::PropertyBinding;
+ v->type = QQmlScript::Value::PropertyBinding;
return true;
}
@@ -3645,7 +3614,7 @@ int QQmlCompiler::genContextCache()
QVector<QQmlContextData::ObjectIdMapping> cache(compileState->ids.count());
int i = 0;
- for (Object *o = compileState->ids.first(); o; o = compileState->ids.next(o), ++i)
+ for (QQmlScript::Object *o = compileState->ids.first(); o; o = compileState->ids.next(o), ++i)
cache[i] = QQmlContextData::ObjectIdMapping(o->id, o->idIndex);
output->contextCaches.append(cache);
@@ -3653,7 +3622,7 @@ int QQmlCompiler::genContextCache()
}
QQmlPropertyData
-QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp,
+QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp,
QQmlScript::Property *prop)
{
QQmlValueType *vt = QQmlValueTypeFactory::valueType(prop->type);
@@ -3666,8 +3635,8 @@ bool QQmlCompiler::completeComponentBuild()
if (componentStats)
componentStats->componentStat.ids = compileState->ids.count();
- for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject;
- aliasObject = compileState->aliasingObjects.next(aliasObject))
+ for (QQmlScript::Object *aliasObject = compileState->aliasingObjects.first(); aliasObject;
+ aliasObject = compileState->aliasingObjects.next(aliasObject))
COMPILE_CHECK(buildDynamicMetaAliases(aliasObject));
const QQmlScript::Parser &parser = unit->parser();
@@ -3708,7 +3677,7 @@ bool QQmlCompiler::completeComponentBuild()
JSCodeGen::ObjectIdMapping idMapping;
if (compileState->ids.count() > 0) {
idMapping.reserve(compileState->ids.count());
- for (Object *o = compileState->ids.first(); o; o = compileState->ids.next(o)) {
+ for (QQmlScript::Object *o = compileState->ids.first(); o; o = compileState->ids.next(o)) {
JSCodeGen::IdMapping m;
m.name = o->id;
m.idIndex = o->idIndex;
@@ -3917,7 +3886,7 @@ QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, b
QHashedStringRef propName = name.mid(0, name.length() - Changed_string.length());
d = property(object, propName, notInRevision);
- if (d)
+ if (d)
return cache->signal(d->notifyIndex);
}
@@ -3925,20 +3894,20 @@ QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, b
}
// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
-int QQmlCompiler::indexOfSignal(QQmlScript::Object *object, const QString &name,
+int QQmlCompiler::indexOfSignal(QQmlScript::Object *object, const QString &name,
bool *notInRevision)
{
QQmlPropertyData *d = signal(object, QStringRef(&name), notInRevision);
return d?d->coreIndex:-1;
}
-int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QString &name,
+int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QString &name,
bool *notInRevision)
{
return indexOfProperty(object, QStringRef(&name), notInRevision);
}
-int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QHashedStringRef &name,
+int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QHashedStringRef &name,
bool *notInRevision)
{
QQmlPropertyData *d = property(object, name, notInRevision);
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 516f6653ca..5a96580f78 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -65,6 +65,7 @@
#include <private/qqmlcodegenerator_p.h>
#include "private/qv4identifier_p.h"
#include <private/qqmljsastfwd_p.h>
+#include "qqmlcustomparser_p.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qset.h>
@@ -84,6 +85,7 @@ class QQmlComponent;
class QQmlContext;
class QQmlContextData;
+// ### Merge with QV4::CompiledData::CompilationUnit
class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
{
public:
@@ -100,7 +102,7 @@ public:
int listMetaTypeId;
bool isRegisteredWithEngine;
- struct TypeReference
+ struct TypeReference
{
TypeReference()
: type(0), typePropertyCache(0), component(0)
@@ -128,7 +130,7 @@ public:
QList<TypeReference> types;
// --- new compiler:
// map from name index
- QHash<int, TypeReference> resolvedTypes;
+ QHash<int, TypeReference*> resolvedTypes;
// ---
struct V8Program {
@@ -144,9 +146,9 @@ public:
QQmlPropertyCache *rootPropertyCache;
QList<QString> primitives;
- QList<QByteArray> datas;
+ QVector<QByteArray> datas;
QByteArray bytecode;
- QList<QQmlPropertyCache *> propertyCaches;
+ QVector<QQmlPropertyCache *> propertyCaches;
QList<QVector<QQmlContextData::ObjectIdMapping> > contextCaches;
QList<QQmlScriptData *> scripts;
QList<QUrl> urls;
@@ -157,7 +159,11 @@ public:
// index in first hash is component index, hash inside maps from object index in that scope to integer id
QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, int> objectIndexToIdForRoot;
+ // hash key is object index
+ QHash<int, QByteArray> customParserData;
QVector<int> customParserBindings; // index is binding identifier, value is compiled function index.
+ int totalBindingsCount; // Number of bindings used in this type
+ int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
bool isCompositeType() const { return !datas.at(qmlUnit->indexOfRootObject).isEmpty(); }
@@ -205,7 +211,7 @@ private:
};
namespace QQmlCompilerTypes {
- struct BindingContext
+ struct BindingContext
{
BindingContext()
: stack(0), owner(0), object(0) {}
@@ -255,7 +261,7 @@ namespace QQmlCompilerTypes {
int n;
};
- struct IdList : public QFieldList<QQmlScript::Object,
+ struct IdList : public QFieldList<QQmlScript::Object,
&QQmlScript::Object::nextIdObject>
{
QQmlScript::Object *value(const QString &id) const {
@@ -289,8 +295,8 @@ namespace QQmlCompilerTypes {
// more than one of these for each compile
struct ComponentCompileState : public QQmlPool::Class
{
- ComponentCompileState()
- : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false),
+ ComponentCompileState()
+ : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false),
root(0) {}
IdList ids;
@@ -330,7 +336,7 @@ namespace QQmlCompilerTypes {
};
class QMetaObjectBuilder;
-class Q_AUTOTEST_EXPORT QQmlCompiler
+class Q_AUTOTEST_EXPORT QQmlCompiler : public QQmlCustomParserCompilerBackend
{
Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
public:
@@ -346,9 +352,9 @@ public:
static bool isAttachedPropertyName(const QHashedStringRef &);
static bool isSignalPropertyName(const QHashedStringRef &);
- int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum
- const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
- int bindingIdentifier(const QString &name, const QQmlScript::Variant& value, const QQmlCompilerTypes::BindingContext &ctxt); // for QQmlCustomParser::bindingIndex
+ virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&value, const QString&name, QQmlCustomParser *customParser);
+
+ virtual const QQmlImports &imports() const { return unit->imports(); }
private:
typedef QQmlCompiledData::Instruction Instruction;
@@ -361,23 +367,23 @@ private:
bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
- bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
+ bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
const QQmlCompilerTypes::BindingContext &);
- bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj,
+ bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj,
const QQmlCompilerTypes::BindingContext &);
bool buildPropertyInNamespace(QQmlImportNamespace *ns,
- QQmlScript::Property *prop,
- QQmlScript::Object *obj,
+ QQmlScript::Property *prop,
+ QQmlScript::Object *obj,
const QQmlCompilerTypes::BindingContext &);
bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
- bool buildAttachedProperty(QQmlScript::Property *prop,
+ bool buildAttachedProperty(QQmlScript::Property *prop,
QQmlScript::Object *obj,
const QQmlCompilerTypes::BindingContext &ctxt);
bool buildGroupedProperty(QQmlScript::Property *prop,
QQmlScript::Object *obj,
const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildValueTypeProperty(QObject *type,
- QQmlScript::Object *obj,
+ bool buildValueTypeProperty(QObject *type,
+ QQmlScript::Object *obj,
QQmlScript::Object *baseObj,
const QQmlCompilerTypes::BindingContext &ctxt);
bool buildListProperty(QQmlScript::Property *prop,
@@ -429,13 +435,13 @@ private:
void genComponent(QQmlScript::Object *obj);
void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
- void genPropertyAssignment(QQmlScript::Property *prop,
+ void genPropertyAssignment(QQmlScript::Property *prop,
QQmlScript::Object *obj,
QQmlScript::Property *valueTypeProperty = 0);
void genLiteralAssignment(QQmlScript::Property *prop,
QQmlScript::Value *value);
- void genBindingAssignment(QQmlScript::Value *binding,
- QQmlScript::Property *prop,
+ void genBindingAssignment(QQmlScript::Value *binding,
+ QQmlScript::Property *prop,
QQmlScript::Object *obj,
QQmlScript::Property *valueTypeProperty = 0);
int genContextCache();
@@ -485,7 +491,7 @@ private:
int cachedComponentTypeRef;
int cachedTranslationContextIndex;
- QScopedPointer<QQmlJS::V4IR::Module> jsModule;
+ QScopedPointer<IR::Module> jsModule;
// Compiler component statistics. Only collected if QML_COMPILER_STATS=1
struct ComponentStat
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 21bcd3569c..084441af01 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -862,7 +862,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
enginePriv->referenceScarceResources();
QObject *rv = 0;
if (enginePriv->useNewCompiler) {
- state.creator = new QmlObjectCreator(context, cc);
+ state.creator = new QQmlObjectCreator(context, cc, creationContext);
rv = state.creator->create(start);
if (!rv)
state.errors = state.creator->errors;
@@ -914,7 +914,8 @@ void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionS
{
if (state->completePending) {
if (enginePriv->useNewCompiler) {
- state->creator->finalize();
+ QQmlInstantiationInterrupt interrupt;
+ state->creator->finalize(interrupt);
} else {
state->vme.complete();
}
@@ -991,7 +992,7 @@ QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
if (p->activeVME) { // XXX should only be allowed during begin
a->add(&p->activeVME->componentAttached);
} else if (p->activeObjectCreator) {
- a->add(&p->activeObjectCreator->componentAttached);
+ a->add(p->activeObjectCreator->componentAttachment());
} else {
QQmlData *d = QQmlData::get(obj);
Q_ASSERT(d);
@@ -1056,7 +1057,11 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
p->compiledData = d->cc;
p->compiledData->addref();
- p->vme.init(contextData, d->cc, d->start, d->creationContext);
+ if (enginePriv->useNewCompiler) {
+ p->creator.reset(new QQmlObjectCreator(contextData, d->cc, d->creationContext));
+ p->subComponentToCreate = d->start;
+ } else
+ p->vme.init(contextData, d->cc, d->start, d->creationContext);
enginePriv->incubate(incubator, forContextData);
}
@@ -1065,7 +1070,7 @@ class QQmlComponentIncubator;
class QmlIncubatorObject : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
public:
QmlIncubatorObject(QV8Engine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
@@ -1081,15 +1086,15 @@ public:
QScopedPointer<QQmlComponentIncubator> incubator;
QV8Engine *v8;
QPointer<QObject> parent;
- QV4::SafeValue valuemap;
- QV4::SafeValue qmlGlobal;
- QV4::SafeValue m_statusChanged;
+ QV4::Value valuemap;
+ QV4::Value qmlGlobal;
+ QV4::Value m_statusChanged;
void statusChanged(QQmlIncubator::Status);
void setInitialState(QObject *);
};
-DEFINE_MANAGED_VTABLE(QmlIncubatorObject);
+DEFINE_OBJECT_VTABLE(QmlIncubatorObject);
class QQmlComponentIncubator : public QQmlIncubator
{
@@ -1463,7 +1468,7 @@ QmlIncubatorObject::QmlIncubatorObject(QV8Engine *engine, QQmlIncubator::Incubat
{
incubator.reset(new QQmlComponentIncubator(this, m));
v8 = engine;
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
valuemap = QV4::Primitive::undefinedValue();
qmlGlobal = QV4::Primitive::undefinedValue();
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index fe376d0e4a..4aa0daf47e 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -129,7 +129,7 @@ private:
Q_DISABLE_COPY(QQmlComponent)
friend class QQmlVME;
friend class QQmlTypeData;
- friend class QmlObjectCreator;
+ friend class QQmlObjectCreator;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 8bf4005dd6..9bccb0be7b 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -81,7 +81,7 @@ class QQmlComponentAttached;
class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public QQmlTypeData::TypeDataCallback
{
Q_DECLARE_PUBLIC(QQmlComponent)
-
+
public:
QQmlComponentPrivate()
: typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), depthIncreased(false) {}
@@ -95,7 +95,7 @@ public:
QQmlTypeData *typeData;
virtual void typeDataReady(QQmlTypeData *);
virtual void typeDataProgress(QQmlTypeData *, qreal);
-
+
void fromTypeData(QQmlTypeData *data);
QUrl url;
@@ -115,7 +115,7 @@ public:
}
// --- new compiler
- QmlObjectCreator *creator;
+ QQmlObjectCreator *creator;
// --- old compiler
QQmlVME vme;
// ---
@@ -124,7 +124,7 @@ public:
};
ConstructionState state;
- static void beginDeferred(QQmlEnginePrivate *enginePriv, QObject *object,
+ static void beginDeferred(QQmlEnginePrivate *enginePriv, QObject *object,
ConstructionState *state);
static void complete(QQmlEnginePrivate *enginePriv, ConstructionState *state);
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 78e6650d02..7b1ba46db2 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -403,7 +403,7 @@ QVariant QQmlContext::contextProperty(const QString &name) const
}
/*!
-Returns the name of \a object in this context, or an empty string if \a object
+Returns the name of \a object in this context, or an empty string if \a object
is not named in the context. Objects are named by setContextProperty(), or by ids in
the case of QML created contexts.
@@ -521,7 +521,7 @@ QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int ind
QQmlContextData::QQmlContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
publicContext(0), activeVMEData(0),
contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
@@ -531,7 +531,7 @@ QQmlContextData::QQmlContextData()
}
QQmlContextData::QQmlContextData(QQmlContext *ctxt)
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
publicContext(ctxt), activeVMEData(0),
contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index 26048b0217..464bee82c0 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -134,7 +134,7 @@ public:
QUrl resolvedUrl(const QUrl &);
- // My containing QQmlContext. If isInternal is true this owns publicContext.
+ // My containing QQmlContext. If isInternal is true this owns publicContext.
// If internal is false publicContext owns this.
QQmlContext *asQQmlContext();
QQmlContextPrivate *asQQmlContextPrivate();
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index b3c2105e68..1ca9c6ac12 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -46,7 +46,7 @@
#include <private/qqmlcontext_p.h>
#include <private/qv4engine_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4function_p.h>
@@ -59,14 +59,14 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_MANAGED_VTABLE(QmlContextWrapper);
+DEFINE_OBJECT_VTABLE(QmlContextWrapper);
QmlContextWrapper::QmlContextWrapper(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
: Object(QV8Engine::getV4(engine)),
v8(engine), readOnly(true), ownsContext(ownsContext), isNullWrapper(false),
context(context), scopeObject(scopeObject), idObjectsWrapper(0)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
QmlContextWrapper::~QmlContextWrapper()
@@ -433,13 +433,13 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(const StringRef &name)
return QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(engine());
}
-DEFINE_MANAGED_VTABLE(QQmlIdObjectsArray);
+DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrapper *contextWrapper)
: Object(engine)
, contextWrapper(contextWrapper)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 89ace7090c..0ecec93652 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -56,7 +56,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4object_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qv4functionobject_p.h>
@@ -73,7 +73,7 @@ struct QQmlIdObjectsArray;
struct Q_QML_EXPORT QmlContextWrapper : Object
{
- Q_MANAGED
+ V4_OBJECT
QmlContextWrapper(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
~QmlContextWrapper();
@@ -112,7 +112,7 @@ private:
struct QQmlIdObjectsArray : public Object
{
- Q_MANAGED
+ V4_OBJECT
QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrapper *contextWrapper);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 19e49009ce..e976000c9e 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -93,7 +93,7 @@ using namespace QQmlScript;
The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE.
*/
-QQmlCustomParserNode
+QQmlCustomParserNode
QQmlCustomParserNodePrivate::fromObject(QQmlScript::Object *root)
{
QQmlCustomParserNode rootNode;
@@ -101,7 +101,7 @@ QQmlCustomParserNodePrivate::fromObject(QQmlScript::Object *root)
rootNode.d->name = root->typeReference->name;
rootNode.d->location = root->location.start;
- for (Property *p = root->properties.first(); p; p = root->properties.next(p)) {
+ for (QQmlScript::Property *p = root->properties.first(); p; p = root->properties.next(p)) {
rootNode.d->properties << fromProperty(p);
}
@@ -111,7 +111,7 @@ QQmlCustomParserNodePrivate::fromObject(QQmlScript::Object *root)
return rootNode;
}
-QQmlCustomParserProperty
+QQmlCustomParserProperty
QQmlCustomParserNodePrivate::fromProperty(QQmlScript::Property *p)
{
QQmlCustomParserProperty prop;
@@ -256,7 +256,6 @@ void QQmlCustomParser::error(const QString& description)
void QQmlCustomParser::error(const QQmlCustomParserProperty& prop, const QString& description)
{
QQmlError error;
- QString exceptionDescription;
error.setLine(prop.location().line);
error.setColumn(prop.location().column);
error.setDescription(description);
@@ -271,7 +270,6 @@ void QQmlCustomParser::error(const QQmlCustomParserProperty& prop, const QString
void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& description)
{
QQmlError error;
- QString exceptionDescription;
error.setLine(node.location().line);
error.setColumn(node.location().column);
error.setDescription(description);
@@ -279,6 +277,34 @@ void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& de
}
/*!
+ Reports an error in parsing \a binding, with the given \a description.
+
+ An error is generated referring to the position of \a node in the source file.
+*/
+void QQmlCustomParser::error(const QV4::CompiledData::Binding *binding, const QString &description)
+{
+ QQmlError error;
+ error.setLine(binding->location.line);
+ error.setColumn(binding->location.column);
+ error.setDescription(description);
+ exceptions << error;
+}
+
+/*!
+ Reports an error in parsing \a object, with the given \a description.
+
+ An error is generated referring to the position of \a object in the source file.
+*/
+void QQmlCustomParser::error(const QV4::CompiledData::Object *object, const QString &description)
+{
+ QQmlError error;
+ error.setLine(object->location.line);
+ error.setColumn(object->location.column);
+ error.setDescription(description);
+ exceptions << error;
+}
+
+/*!
If \a script is a simple enumeration expression (eg. Text.AlignLeft),
returns the integer equivalent (eg. 1), and sets \a ok to true.
@@ -313,7 +339,54 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
*/
QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QQmlScript::Variant &value, const QString& name)
{
- return compiler->bindingIdentifier(name, value, QQmlCompilerTypes::BindingContext(object));
+ return compiler->bindingIdentifier(value, name, this);
+}
+
+QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QV4::CompiledData::Binding *binding)
+{
+ return compiler->bindingIdentifier(binding, this);
+}
+
+QQmlJS::AST::Node *QQmlCustomParser::astForBinding(int scriptIndex) const
+{
+ return compiler->astForBinding(scriptIndex);
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+};
+
+int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
+{
+ Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
+ *ok = false;
+
+ if (scope != QLatin1String("Qt")) {
+ QQmlType *type = 0;
+ imports().resolveType(scope, &type, 0, 0, 0);
+ return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ }
+
+ const QMetaObject *mo = StaticQtMetaObject::get();
+ int i = mo->enumeratorCount();
+ while (i--) {
+ int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+ if (*ok)
+ return v;
+ }
+ return -1;
+}
+
+const QMetaObject *QQmlCustomParserCompilerBackend::resolveType(const QString &name) const
+{
+ QQmlType *qmltype = 0;
+ if (!imports().resolveType(name, &qmltype, 0, 0, 0))
+ return 0;
+ if (!qmltype)
+ return 0;
+ return qmltype->metaObject();
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 27f7e00b31..b406717410 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -79,7 +79,7 @@ public:
QQmlScript::Location location() const;
bool isList() const;
- // Will be one of QQmlScript::Variant, QQmlCustomParserProperty or
+ // Will be one of QQmlScript::Variant, QQmlCustomParserProperty or
// QQmlCustomParserNode
QList<QVariant> assignedValues() const;
@@ -108,6 +108,20 @@ private:
QQmlCustomParserNodePrivate *d;
};
+struct QQmlCustomParserCompilerBackend
+{
+ virtual ~QQmlCustomParserCompilerBackend() {}
+ virtual const QQmlImports &imports() const = 0;
+
+ int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const;
+ const QMetaObject *resolveType(const QString& name) const;
+
+ virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&, QQmlCustomParser *) { return QQmlBinding::Invalid; }
+ virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *, QQmlCustomParser *) { return QQmlBinding::Invalid; }
+
+ virtual QQmlJS::AST::Node *astForBinding(int) const { return 0; }
+};
+
class Q_QML_PRIVATE_EXPORT QQmlCustomParser
{
public:
@@ -126,6 +140,7 @@ public:
Flags flags() const { return m_flags; }
virtual QByteArray compile(const QList<QQmlCustomParserProperty> &)=0;
+ virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) = 0;
virtual void setCustomData(QObject *, const QByteArray &)=0;
QList<QQmlError> errors() const { return exceptions; }
@@ -134,19 +149,25 @@ protected:
void error(const QString& description);
void error(const QQmlCustomParserProperty&, const QString& description);
void error(const QQmlCustomParserNode&, const QString& description);
+ void error(const QV4::CompiledData::Binding *binding, const QString& description);
+ void error(const QV4::CompiledData::Object *object, const QString& description);
int evaluateEnum(const QByteArray&, bool *ok) const;
const QMetaObject *resolveType(const QString&) const;
QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&);
+ QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding);
+
+ QQmlJS::AST::Node *astForBinding(int scriptIndex) const;
private:
QList<QQmlError> exceptions;
- QQmlCompiler *compiler;
+ QQmlCustomParserCompilerBackend *compiler;
QQmlScript::Object *object;
Flags m_flags;
friend class QQmlCompiler;
+ friend class QQmlPropertyValidator;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags)
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 982156ea15..93060e97fb 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -56,7 +56,8 @@
#include <private/qtqmlglobal_p.h>
#include <private/qobject_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
+#include <private/qv4persistent_p.h>
QT_BEGIN_NAMESPACE
@@ -143,7 +144,7 @@ public:
void layout(QQmlNotifierEndpoint*);
};
NotifyList *notifyList;
-
+
inline QQmlNotifierEndpoint *notify(int index);
void addNotify(int index, QQmlNotifierEndpoint *);
int endpointCount(int index);
@@ -151,7 +152,7 @@ public:
void disconnectNotifiers();
// The context that created the C++ object
- QQmlContextData *context;
+ QQmlContextData *context;
// The outermost context in which this object lives
QQmlContextData *outerContext;
@@ -163,7 +164,7 @@ public:
QQmlData**prevContextObject;
int bindingBitsSize;
- quint32 *bindingBits;
+ quint32 *bindingBits;
inline bool hasBindingBit(int) const;
void clearBindingBit(int);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index acc66c8ce5..d373c00574 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -62,12 +62,14 @@
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
+#include <private/qqmldebugserver_p.h>
#include <private/qqmlprofilerservice_p.h>
#include <private/qv4debugservice_p.h>
#include <private/qdebugmessageservice_p.h>
+#include <private/qqmlenginecontrolservice_p.h>
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
-#include <private/qv8profilerservice_p.h>
+#include <private/qv4profilerservice_p.h>
#include <private/qqmlboundsignal_p.h>
#include <QtCore/qstandardpaths.h>
@@ -107,7 +109,7 @@
#include <qlibrary.h>
#include <windows.h>
-#define CSIDL_APPDATA 0x001a // <username>\Application Data
+#define CSIDL_APPDATA 0x001a // <username>\Application Data
#endif
Q_DECLARE_METATYPE(QQmlProperty)
@@ -554,7 +556,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlUseNewCompiler, QML_NEW_COMPILER)
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0), isDebugging(false),
- outputWarningsToStdErr(true),
+ profiler(0), outputWarningsToStdErr(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0), activeVME(0),
activeObjectCreator(0),
@@ -593,6 +595,12 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
(*iter)->release();
for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
iter.value()->isRegisteredWithEngine = false;
+ delete profiler;
+}
+
+void QQmlEnginePrivate::enableProfiler()
+{
+ profiler = new QQmlProfiler();
}
void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
@@ -813,11 +821,13 @@ void QQmlEnginePrivate::init()
if (QCoreApplication::instance()->thread() == q->thread() &&
QQmlEngineDebugService::isDebuggingEnabled()) {
isDebugging = true;
- QQmlEngineDebugService::instance()->addEngine(q);
- QV4DebugService::instance()->addEngine(q);
- QV8ProfilerService::initialize();
- QQmlProfilerService::initialize();
+ QQmlEngineDebugService::instance();
+ QV4DebugService::instance();
+ QV4ProfilerService::instance();
+ QQmlProfilerService::instance();
QDebugMessageService::instance();
+ QQmlEngineControlService::instance();
+ QQmlDebugServer::instance()->addEngine(q);
}
}
@@ -895,10 +905,8 @@ QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
QQmlEngine::~QQmlEngine()
{
Q_D(QQmlEngine);
- if (d->isDebugging) {
- QQmlEngineDebugService::instance()->remEngine(this);
- QV4DebugService::instance()->removeEngine(this);
- }
+ if (d->isDebugging)
+ QQmlDebugServer::instance()->removeEngine(this);
// Emit onDestruction signals for the root context before
// we destroy the contexts, engine, Singleton Types etc. that
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 19eb320fbe..e00e55f157 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -99,9 +99,10 @@ class QQmlCleanup;
class QQmlDelayedError;
class QQuickWorkerScriptEngine;
class QQmlVME;
-class QmlObjectCreator;
+class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
+class QQmlProfiler;
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
@@ -146,6 +147,8 @@ public:
QQmlContext *rootContext;
bool isDebugging;
bool useNewCompiler;
+ QQmlProfiler *profiler;
+ void enableProfiler();
bool outputWarningsToStdErr;
@@ -170,7 +173,7 @@ public:
// --- old compiler:
QQmlVME *activeVME;
// --- new compiler:
- QmlObjectCreator *activeObjectCreator;
+ QQmlObjectCreator *activeObjectCreator;
// ---
QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
@@ -271,16 +274,16 @@ public:
mutable QMutex mutex;
private:
- // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
- // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
+ // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
+ // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
// either idle, or is running with the main thread blocked, no locking is necessary. This way
// we only pay for locking when we have to.
- // Consequently, this class should only be used to protect simple accesses or modifications of the
+ // Consequently, this class should only be used to protect simple accesses or modifications of the
// QQmlEnginePrivate structures or operations that can be guaranteed not to start activity
// on the loader thread.
- // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
+ // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
// QMutex instance and multiple Lockers are recursive in the same thread.
- class Locker
+ class Locker
{
public:
inline Locker(const QQmlEngine *);
@@ -333,7 +336,7 @@ QQmlEnginePrivate::Locker::~Locker()
void QQmlEnginePrivate::Locker::unlock()
{
- if (m_locked) {
+ if (m_locked) {
m_ep->mutex.unlock();
m_locked = false;
}
@@ -373,7 +376,7 @@ thread, \a value will be deleted immediately.
This method should be used for *any* type that has resources that need to
be freed in the engine thread. This is generally types that use V8 handles.
As there is some small overhead in checking the current thread, it is best
-practice to check if any V8 handles actually need to be freed and delete
+practice to check if any V8 handles actually need to be freed and delete
the instance directly if not.
*/
template<typename T>
@@ -384,7 +387,7 @@ void QQmlEnginePrivate::deleteInEngineThread(T *value)
Q_ASSERT(value);
if (isEngineThread()) {
delete value;
- } else {
+ } else {
struct I : public Deletable {
I(T *value) : value(value) {}
~I() { delete value; }
@@ -420,10 +423,10 @@ is returned.
The returned cache is not referenced, so if it is to be stored, call addref().
XXX thread There is a potential future race condition in this and all the cache()
-functions. As the QQmlPropertyCache is returned unreferenced, when called
-from the loader thread, it is possible that the cache will have been dereferenced
+functions. As the QQmlPropertyCache is returned unreferenced, when called
+from the loader thread, it is possible that the cache will have been dereferenced
and deleted before the loader thread has a chance to use or reference it. This
-can't currently happen as the cache holds a reference to the
+can't currently happen as the cache holds a reference to the
QQmlPropertyCache until the QQmlEngine is destroyed.
*/
QQmlPropertyCache *QQmlEnginePrivate::cache(QObject *obj)
@@ -475,8 +478,8 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQ
return rv;
}
-QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e)
-{
+QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e)
+{
Q_ASSERT(e);
return e->d_func()->v8engine();
@@ -489,32 +492,32 @@ QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e)
return e->d_func()->v4engine();
}
-QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlEngine *e)
-{
+QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlEngine *e)
+{
Q_ASSERT(e);
return e->d_func();
}
-const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e)
-{
+const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e)
+{
Q_ASSERT(e);
return e->d_func();
}
-QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c)
-{
- return (c && c->engine()) ? QQmlEnginePrivate::get(c->engine()) : 0;
+QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c)
+{
+ return (c && c->engine()) ? QQmlEnginePrivate::get(c->engine()) : 0;
}
-QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContextData *c)
-{
- return (c && c->engine) ? QQmlEnginePrivate::get(c->engine) : 0;
+QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContextData *c)
+{
+ return (c && c->engine) ? QQmlEnginePrivate::get(c->engine) : 0;
}
-QQmlEngine *QQmlEnginePrivate::get(QQmlEnginePrivate *p)
-{
+QQmlEngine *QQmlEnginePrivate::get(QQmlEnginePrivate *p)
+{
Q_ASSERT(p);
return p->q_func();
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index ad95ecdf06..c583156c43 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -131,7 +131,7 @@ QQmlError &QQmlError::operator=(const QQmlError &other)
}
/*!
- \internal
+ \internal
*/
QQmlError::~QQmlError()
{
@@ -297,7 +297,7 @@ QDebug operator<<(QDebug debug, const QQmlError &error)
if(error.column() > 0) {
int column = qMax(0, error.column() - 1);
- column = qMin(column, line.length());
+ column = qMin(column, line.length());
QByteArray ind;
ind.reserve(column);
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 7b968a7e46..eca13e8fb8 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -193,14 +193,14 @@ struct QQmlGraphics_DerivedObject : public QObject
};
/*!
- Returns true if the case of \a fileName is equivalent to the file case of
+ Returns true if the case of \a fileName is equivalent to the file case of
\a fileName on disk, and false otherwise.
- This is used to ensure that the behavior of QML on a case-insensitive file
- system is the same as on a case-sensitive file system. This function
- performs a "best effort" attempt to determine the real case of the file.
+ This is used to ensure that the behavior of QML on a case-insensitive file
+ system is the same as on a case-sensitive file system. This function
+ performs a "best effort" attempt to determine the real case of the file.
It may have false positives (say the case is correct when it isn't), but it
- should never have a false negative (say the case is incorrect when it is
+ should never have a false negative (say the case is incorrect when it is
correct).
Length specifies specifies the number of characters to be checked from
diff --git a/src/qml/qml/qqmlguard_p.h b/src/qml/qml/qqmlguard_p.h
index 455f5c93a8..b2e0949c74 100644
--- a/src/qml/qml/qqmlguard_p.h
+++ b/src/qml/qml/qqmlguard_p.h
@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
-class QQmlGuardImpl
+class QQmlGuardImpl
{
public:
inline QQmlGuardImpl();
@@ -91,7 +91,7 @@ public:
inline T *object() const;
inline void setObject(T *g);
-
+
inline bool isNull() const
{ return !o; }
@@ -141,7 +141,7 @@ void QQmlGuardImpl::addGuard()
{
Q_ASSERT(!prev);
- if (QObjectPrivate::get(o)->wasDeleted)
+ if (QObjectPrivate::get(o)->wasDeleted)
return;
QQmlData *data = QQmlData::get(o, true);
@@ -198,13 +198,13 @@ QQmlGuard<T> &QQmlGuard<T>::operator=(T *g)
}
template<class T>
-T *QQmlGuard<T>::object() const
-{
- return static_cast<T *>(o);
+T *QQmlGuard<T>::object() const
+{
+ return static_cast<T *>(o);
}
template<class T>
-void QQmlGuard<T>::setObject(T *g)
+void QQmlGuard<T>::setObject(T *g)
{
if (g != o) {
if (prev) remGuard();
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 8645d2116a..97f82a2e8d 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -180,17 +180,22 @@ struct RegisteredPlugin {
QPluginLoader* loader;
};
-typedef QMap<QString, RegisteredPlugin> StringRegisteredPluginMap;
+struct StringRegisteredPluginMap : public QMap<QString, RegisteredPlugin> {
+ QMutex mutex;
+};
+
Q_GLOBAL_STATIC(StringRegisteredPluginMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri and the PluginLoaders
void qmlClearEnginePlugins()
{
- foreach (RegisteredPlugin plugin, qmlEnginePluginsWithRegisteredTypes()->values()) {
+ StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
+ QMutexLocker lock(&plugins->mutex);
+ foreach (RegisteredPlugin plugin, plugins->values()) {
QPluginLoader* loader = plugin.loader;
if (!loader->unload())
qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString()));
delete loader;
}
- qmlEnginePluginsWithRegisteredTypes()->clear();
+ plugins->clear();
}
typedef QPair<QStaticPlugin, QJsonArray> StaticPluginPair;
@@ -303,7 +308,7 @@ public:
\brief The QQmlImports class encapsulates one QML document's import statements.
\internal
*/
-QQmlImports::QQmlImports(const QQmlImports &copy)
+QQmlImports::QQmlImports(const QQmlImports &copy)
: d(copy.d)
{
++d->ref;
@@ -1631,7 +1636,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
}
if (qmlImportTrace())
- qDebug() << "QQmlImportDatabase::resolvePlugin: Could not resolve plugin" << baseName
+ qDebug() << "QQmlImportDatabase::resolvePlugin: Could not resolve plugin" << baseName
<< "in" << qmldirPath;
return QString();
@@ -1909,10 +1914,12 @@ bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &ur
const QString absoluteFilePath = fileInfo.absoluteFilePath();
bool engineInitialized = initializedPlugins.contains(absoluteFilePath);
- bool typesRegistered = qmlEnginePluginsWithRegisteredTypes()->contains(absoluteFilePath);
+ StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
+ QMutexLocker lock(&plugins->mutex);
+ bool typesRegistered = plugins->contains(absoluteFilePath);
if (typesRegistered) {
- Q_ASSERT_X(qmlEnginePluginsWithRegisteredTypes()->value(absoluteFilePath).uri == uri,
+ Q_ASSERT_X(plugins->value(absoluteFilePath).uri == uri,
"QQmlImportDatabase::importPlugin",
"Internal error: Plugin imported previously with different uri");
}
@@ -1942,7 +1949,7 @@ bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &ur
return false;
}
} else {
- loader = qmlEnginePluginsWithRegisteredTypes()->value(absoluteFilePath).loader;
+ loader = plugins->value(absoluteFilePath).loader;
}
QObject *instance = loader->instance();
@@ -1951,7 +1958,7 @@ bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &ur
RegisteredPlugin plugin;
plugin.uri = uri;
plugin.loader = loader;
- qmlEnginePluginsWithRegisteredTypes()->insert(absoluteFilePath, plugin);
+ plugins->insert(absoluteFilePath, plugin);
// Continue with shared code path for dynamic and static plugins:
if (!importPlugin(instance, fileInfo.absolutePath(), uri, typeNamespace, false, errors))
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index ade4634c2d..1cc75387a3 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -46,9 +46,10 @@
#include "qqmlcompiler_p.h"
#include "qqmlexpression_p.h"
#include "qqmlmemoryprofiler_p.h"
+#include "qqmlobjectcreator_p.h"
-// XXX TODO
-// - check that the Component.onCompleted behavior is the same as 4.8 in the synchronous and
+// XXX TODO
+// - check that the Component.onCompleted behavior is the same as 4.8 in the synchronous and
// async if nested cases
void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
{
@@ -90,14 +91,17 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
p->changeStatus(QQmlIncubator::Loading);
if (!watcher.hasRecursed()) {
- QQmlVME::Interrupt i;
+ QQmlInstantiationInterrupt i;
p->incubate(i);
}
} else {
incubatorList.insert(p.data());
incubatorCount++;
- p->vmeGuard.guard(&p->vme);
+ if (useNewCompiler)
+ p->vmeGuard.guard(p->creator.data());
+ else
+ p->vmeGuard.guard(&p->vme);
p->changeStatus(QQmlIncubator::Loading);
if (incubationController)
@@ -106,7 +110,7 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
}
/*!
-Sets the engine's incubation \a controller. The engine can only have one active controller
+Sets the engine's incubation \a controller. The engine can only have one active controller
and it does not take ownership of it.
\sa incubationController()
@@ -180,7 +184,7 @@ the process of creating objects a QQmlIncubators must be driven only during the
application's idle time. QQmlIncubationController allows the application to control
exactly when, how often and for how long this processing occurs.
-A QQmlIncubationController derived instance should be created and set on a
+A QQmlIncubationController derived instance should be created and set on a
QQmlEngine by calling the QQmlEngine::setIncubationController() method.
Processing is then controlled by calling the QQmlIncubationController::incubateFor()
or QQmlIncubationController::incubateWhile() methods as dictated by the application's
@@ -190,12 +194,12 @@ For example, this is an example of a incubation controller that will incubate fo
of 5 milliseconds out of every 16 milliseconds.
\code
-class PeriodicIncubationController : public QObject,
- public QQmlIncubationController
+class PeriodicIncubationController : public QObject,
+ public QQmlIncubationController
{
public:
- PeriodicIncubationController() {
- startTimer(16);
+ PeriodicIncubationController() {
+ startTimer(16);
}
protected:
@@ -207,7 +211,7 @@ protected:
Although the previous example would work, it is not optimal. Real world incubation
controllers should try and maximize the amount of idle time they consume - rather
-than a static amount like 5 milliseconds - while not disturbing the application.
+than a static amount like 5 milliseconds - while not disturbing the application.
*/
/*!
@@ -243,7 +247,7 @@ int QQmlIncubationController::incubatingObjectCount() const
}
/*!
-Called when the number of incubating objects changes. \a incubatingObjectCount is the
+Called when the number of incubating objects changes. \a incubatingObjectCount is the
new number of incubating objects.
The default implementation does nothing.
@@ -253,7 +257,7 @@ void QQmlIncubationController::incubatingObjectCountChanged(int incubatingObject
Q_UNUSED(incubatingObjectCount);
}
-void QQmlIncubatorPrivate::forceCompletion(QQmlVME::Interrupt &i)
+void QQmlIncubatorPrivate::forceCompletion(QQmlInstantiationInterrupt &i)
{
while (QQmlIncubator::Loading == status) {
while (QQmlIncubator::Loading == status && !waitingFor.isEmpty())
@@ -263,7 +267,7 @@ void QQmlIncubatorPrivate::forceCompletion(QQmlVME::Interrupt &i)
}
}
-void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
+void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
{
if (!compiledData)
return;
@@ -292,14 +296,21 @@ void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
if (progress == QQmlIncubatorPrivate::Execute) {
enginePriv->referenceScarceResources();
- QObject *tresult = vme.execute(&errors, i);
+ QObject *tresult = 0;
+ if (enginePriv->useNewCompiler) {
+ tresult = creator->create(subComponentToCreate);
+ if (!tresult)
+ errors = creator->errors;
+ } else {
+ tresult = vme.execute(&errors, i);
+ }
enginePriv->dereferenceScarceResources();
if (watcher.hasRecursed())
return;
result = tresult;
- if (errors.isEmpty() && result == 0)
+ if (errors.isEmpty() && result == 0)
goto finishIncubate;
if (result) {
@@ -335,7 +346,11 @@ void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
if (watcher.hasRecursed())
return;
- QQmlContextData *ctxt = vme.complete(i);
+ QQmlContextData *ctxt = 0;
+ if (enginePriv->useNewCompiler)
+ ctxt = creator->finalize(i);
+ else
+ ctxt = vme.complete(i);
if (ctxt) {
rootContext = ctxt;
progress = QQmlIncubatorPrivate::Completed;
@@ -367,7 +382,10 @@ finishIncubate:
}
}
} else {
- vmeGuard.guard(&vme);
+ if (enginePriv->useNewCompiler)
+ vmeGuard.guard(creator.data());
+ else
+ vmeGuard.guard(&vme);
}
}
@@ -379,7 +397,7 @@ void QQmlIncubationController::incubateFor(int msecs)
if (!d || !d->incubatorCount)
return;
- QQmlVME::Interrupt i(msecs * 1000000);
+ QQmlInstantiationInterrupt i(msecs * 1000000);
i.reset();
do {
static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i);
@@ -398,7 +416,7 @@ void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs)
if (!d || !d->incubatorCount)
return;
- QQmlVME::Interrupt i(flag, msecs * 1000000);
+ QQmlInstantiationInterrupt i(flag, msecs * 1000000);
i.reset();
do {
static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i);
@@ -416,8 +434,8 @@ application uses QQmlComponent::create() directly, the QML object instance is cr
synchronously which, depending on the complexity of the object, can cause noticeable pauses or
stutters in the application.
-The use of QQmlIncubator gives more control over the creation of a QML object,
-including allowing it to be created asynchronously using application idle time. The following
+The use of QQmlIncubator gives more control over the creation of a QML object,
+including allowing it to be created asynchronously using application idle time. The following
example shows a simple use of QQmlIncubator.
\code
@@ -431,25 +449,25 @@ while (incubator.isReady()) {
QObject *object = incubator.object();
\endcode
-Asynchronous incubators are controlled by a QQmlIncubationController that is
+Asynchronous incubators are controlled by a QQmlIncubationController that is
set on the QQmlEngine, which lets the engine know when the application is idle and
incubating objects should be processed. If an incubation controller is not set on the
QQmlEngine, QQmlIncubator creates objects synchronously regardless of the
-specified IncubationMode.
+specified IncubationMode.
QQmlIncubator supports three incubation modes:
\list
\li Synchronous The creation occurs synchronously. That is, once the
QQmlComponent::create() call returns, the incubator will already be in either the
Error or Ready state. A synchronous incubator has no real advantage compared to using
-the synchronous creation methods on QQmlComponent directly, but it may simplify an
-application's implementation to use the same API for both synchronous and asynchronous
+the synchronous creation methods on QQmlComponent directly, but it may simplify an
+application's implementation to use the same API for both synchronous and asynchronous
creations.
\li Asynchronous (default) The creation occurs asynchronously, assuming a
-QQmlIncubatorController is set on the QQmlEngine.
+QQmlIncubatorController is set on the QQmlEngine.
-The incubator will remain in the Loading state until either the creation is complete or an error
+The incubator will remain in the Loading state until either the creation is complete or an error
occurs. The statusChanged() callback can be used to be notified of status changes.
Applications should use the Asynchronous incubation mode to create objects that are not needed
@@ -459,31 +477,31 @@ the object is needed immediately the QQmlIncubator::forceCompletion() method can
to complete the creation process synchronously.
\li AsynchronousIfNested The creation will occur asynchronously if part of a nested asynchronous
-creation, or synchronously if not.
+creation, or synchronously if not.
In most scenarios where a QML component wants the appearance of a synchronous
-instantiation, it should use this mode.
+instantiation, it should use this mode.
This mode is best explained with an example. When the ListView type is first created, it needs
-to populate itself with an initial set of delegates to show. If the ListView was 400 pixels high,
+to populate itself with an initial set of delegates to show. If the ListView was 400 pixels high,
and each delegate was 100 pixels high, it would need to create four initial delegate instances. If
the ListView used the Asynchronous incubation mode, the ListView would always be created empty and
then, sometime later, the four initial items would appear.
-Conversely, if the ListView was to use the Synchronous incubation mode it would behave correctly
-but it may introduce stutters into the application. As QML would have to stop and instantiate the
-ListView's delegates synchronously, if the ListView was part of a QML component that was being
+Conversely, if the ListView was to use the Synchronous incubation mode it would behave correctly
+but it may introduce stutters into the application. As QML would have to stop and instantiate the
+ListView's delegates synchronously, if the ListView was part of a QML component that was being
instantiated asynchronously this would undo much of the benefit of asynchronous instantiation.
The AsynchronousIfNested mode reconciles this problem. By using AsynchronousIfNested, the ListView
delegates are instantiated asynchronously if the ListView itself is already part of an asynchronous
instantiation, and synchronously otherwise. In the case of a nested asynchronous instantiation, the
outer asynchronous instantiation will not complete until after all the nested instantiations have also
-completed. This ensures that by the time the outer asynchronous instantitation completes, inner
+completed. This ensures that by the time the outer asynchronous instantitation completes, inner
items like ListView have already completed loading their initial delegates.
It is almost always incorrect to use the Synchronous incubation mode - elements or components that
-want the appearance of synchronous instantiation, but without the downsides of introducing freezes
+want the appearance of synchronous instantiation, but without the downsides of introducing freezes
or stutters into the application, should use the AsynchronousIfNested incubation mode.
\endlist
*/
@@ -511,14 +529,14 @@ QQmlIncubator::~QQmlIncubator()
/*!
\enum QQmlIncubator::IncubationMode
-Specifies the mode the incubator operates in. Regardless of the incubation mode, a
+Specifies the mode the incubator operates in. Regardless of the incubation mode, a
QQmlIncubator will behave synchronously if the QQmlEngine does not have
a QQmlIncubationController set.
\value Asynchronous The object will be created asynchronously.
\value AsynchronousIfNested If the object is being created in a context that is already part
-of an asynchronous creation, this incubator will join that existing incubation and execute
-asynchronously. The existing incubation will not become Ready until both it and this
+of an asynchronous creation, this incubator will join that existing incubation and execute
+asynchronously. The existing incubation will not become Ready until both it and this
incubation have completed. Otherwise, the incubation will execute synchronously.
\value Synchronous The object will be created synchronously.
*/
@@ -535,7 +553,7 @@ Specifies the status of the QQmlIncubator.
*/
/*!
-Clears the incubator. Any in-progress incubation is aborted. If the incubator is in the
+Clears the incubator. Any in-progress incubation is aborted. If the incubator is in the
Ready state, the created object is \b not deleted.
*/
void QQmlIncubator::clear()
@@ -566,6 +584,7 @@ void QQmlIncubator::clear()
d->vme.reset();
d->vmeGuard.clear();
+ d->creator.reset(0);
Q_ASSERT(d->compiledData == 0);
Q_ASSERT(d->waitingOnMe.data() == 0);
@@ -596,7 +615,7 @@ returns, the incubator will not be in the Loading state.
*/
void QQmlIncubator::forceCompletion()
{
- QQmlVME::Interrupt i;
+ QQmlInstantiationInterrupt i;
d->forceCompletion(i);
}
@@ -693,7 +712,7 @@ void QQmlIncubator::setInitialState(QObject *object)
void QQmlIncubatorPrivate::changeStatus(QQmlIncubator::Status s)
{
- if (s == status)
+ if (s == status)
return;
status = s;
@@ -703,13 +722,13 @@ void QQmlIncubatorPrivate::changeStatus(QQmlIncubator::Status s)
QQmlIncubator::Status QQmlIncubatorPrivate::calculateStatus() const
{
- if (!errors.isEmpty())
+ if (!errors.isEmpty())
return QQmlIncubator::Error;
else if (result && progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty())
return QQmlIncubator::Ready;
else if (compiledData)
return QQmlIncubator::Loading;
- else
+ else
return QQmlIncubator::Null;
}
diff --git a/src/qml/qml/qqmlincubator.h b/src/qml/qml/qqmlincubator.h
index 4d3287a394..2bcaee8a45 100644
--- a/src/qml/qml/qqmlincubator.h
+++ b/src/qml/qml/qqmlincubator.h
@@ -60,11 +60,11 @@ public:
AsynchronousIfNested,
Synchronous
};
- enum Status {
- Null,
- Ready,
- Loading,
- Error
+ enum Status {
+ Null,
+ Ready,
+ Loading,
+ Error
};
QQmlIncubator(IncubationMode = Asynchronous);
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index e7246ce3b2..80da2910c1 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -88,7 +88,12 @@ public:
QPointer<QObject> result;
QQmlGuardedContextData rootContext;
QQmlCompiledData *compiledData;
+ // --- old compiler
QQmlVME vme;
+ // --- new compiler
+ QScopedPointer<QQmlObjectCreator> creator;
+ int subComponentToCreate;
+ // ---
QQmlVMEGuard vmeGuard;
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> waitingOnMe;
@@ -99,8 +104,8 @@ public:
void clear();
- void forceCompletion(QQmlVME::Interrupt &i);
- void incubate(QQmlVME::Interrupt &i);
+ void forceCompletion(QQmlInstantiationInterrupt &i);
+ void incubate(QQmlInstantiationInterrupt &i);
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index 32f0eeef36..63ce2d419c 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -61,13 +61,13 @@ QT_BEGIN_NAMESPACE
When QML types display warning messages, it improves traceability
if they include the QML file and line number on which the
particular instance was instantiated.
-
+
To include the file and line number, an object must be passed. If
the file and line number is not available for that instance
(either it was not instantiated by the QML engine or location
information is disabled), "unknown location" will be used instead.
- For example,
+ For example,
\code
qmlInfo(object) << tr("component property is a write-once property");
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index 8b27cf06dd..314debc8ee 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -131,7 +131,7 @@ QT_BEGIN_NAMESPACE
F(Defer, defer) \
F(PopFetchedObject, common) \
F(FetchValueType, fetchValue) \
- F(PopValueType, fetchValue)
+ F(PopValueType, fetchValue)
#ifndef QT_NO_TRANSLATION
#define F_TRANSLATION(F, I, FMT) F(I, FMT)
@@ -163,7 +163,7 @@ QT_BEGIN_NAMESPACE
class QQmlCompiledData;
union QQmlInstruction
{
- enum Type {
+ enum Type {
FOR_EACH_QML_INSTR(QML_INSTR_ENUM)
};
@@ -195,7 +195,7 @@ union QQmlInstruction
struct instr_completeQml {
QML_INSTR_HEADER
ushort column;
- ushort line;
+ ushort line;
bool isRoot;
};
struct instr_create {
@@ -203,7 +203,7 @@ union QQmlInstruction
int type;
int data;
ushort column;
- ushort line;
+ ushort line;
bool isRoot:1;
bool parentToSuper:1;
};
@@ -213,7 +213,7 @@ union QQmlInstruction
int typeSize;
int type;
ushort column;
- ushort line;
+ ushort line;
bool parentToSuper;
};
struct instr_storeMeta {
@@ -253,6 +253,7 @@ union QQmlInstruction
QML_INSTR_HEADER
int property;
ushort line;
+ ushort column;
};
struct instr_fetchValue {
QML_INSTR_HEADER
@@ -268,7 +269,7 @@ union QQmlInstruction
struct instr_begin {
QML_INSTR_HEADER
int castValue;
- };
+ };
struct instr_storeFloat {
QML_INSTR_HEADER
int propertyIndex;
@@ -324,7 +325,7 @@ union QQmlInstruction
double numberValue;
bool isStringLiteral:1;
bool isNumberLiteral:1;
- };
+ };
struct instr_storeScript {
QML_INSTR_HEADER
int value;
@@ -401,7 +402,7 @@ union QQmlInstruction
struct instr_assignSignalObject {
QML_INSTR_HEADER
int signal;
- ushort line;
+ ushort line;
};
struct instr_createComponent {
QML_INSTR_HEADER
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 9453d455e7..b233b6e98c 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -43,7 +43,7 @@
#include <private/qqmlexpression_p.h>
#include <private/qqmlcontextwrapper_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index d172c9a185..6d0fddf2ad 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -109,7 +109,7 @@ QML list properties are typesafe. Only QObject's that derive from the correct b
the list. The listElementType() method can be used to query the QMetaObject of the QObject type supported.
Attempting to add objects of the incorrect type to a list property will fail.
-Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure
+Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure
that it does not request an out of range element using the count() method before calling at().
The \l {Qt Quick 1} version of this class is named QDeclarativeListReference.
@@ -125,7 +125,7 @@ QQmlListReference::QQmlListReference()
/*!
Constructs a QQmlListReference for \a object's \a property. If \a property is not a list
-property, an invalid QQmlListReference is created. If \a object is destroyed after
+property, an invalid QQmlListReference is created. If \a object is destroyed after
the reference is constructed, it will automatically become invalid. That is, it is safe to hold
QQmlListReference instances even after \a object is deleted.
@@ -243,7 +243,7 @@ bool QQmlListReference::canClear() const
}
/*!
-Returns true if the list property can be queried for its element count, otherwise false.
+Returns true if the list property can be queried for its element count, otherwise false.
Returns false if the reference is invalid.
\sa count()
@@ -336,7 +336,7 @@ int QQmlListReference::count() const
\class QQmlListProperty
\since 5.0
\inmodule QtQml
-\brief The QQmlListProperty class allows applications to expose list-like
+\brief The QQmlListProperty class allows applications to expose list-like
properties to QML.
QML has many list properties, where more than one object value can be assigned.
@@ -344,7 +344,7 @@ The use of a list property from QML looks like this:
\code
FruitBasket {
- fruit: [
+ fruit: [
Apple {},
Orange{},
Banana{}
@@ -354,10 +354,10 @@ FruitBasket {
The QQmlListProperty encapsulates a group of function pointers that represet the
set of actions QML can perform on the list - adding items, retrieving items and
-clearing the list. In the future, additional operations may be supported. All
+clearing the list. In the future, additional operations may be supported. All
list properties must implement the append operation, but the rest are optional.
-To provide a list property, a C++ class must implement the operation callbacks,
+To provide a list property, a C++ class must implement the operation callbacks,
and then return an appropriate QQmlListProperty value from the property getter.
List properties should have no setter. In the example above, the Q_PROPERTY()
declarative will look like this:
@@ -366,7 +366,7 @@ declarative will look like this:
Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit);
\endcode
-QML list properties are typesafe - in this case \c {Fruit} is a QObject type that
+QML list properties are typesafe - in this case \c {Fruit} is a QObject type that
\c {Apple}, \c {Orange} and \c {Banana} all derive from.
The \l {Qt Quick 1} version of this class is named QDeclarativeListProperty.
@@ -375,7 +375,7 @@ The \l {Qt Quick 1} version of this class is named QDeclarativeListProperty.
*/
/*!
-\fn QQmlListProperty::QQmlListProperty()
+\fn QQmlListProperty::QQmlListProperty()
\internal
*/
@@ -386,7 +386,7 @@ Convenience constructor for making a QQmlListProperty value from an existing
QList \a list. The \a list reference must remain valid for as long as \a object
exists. \a object must be provided.
-Generally this constructor should not be used in production code, as a
+Generally this constructor should not be used in production code, as a
writable QList violates QML's memory management rules. However, this constructor
can very useful while prototyping.
*/
@@ -401,12 +401,12 @@ remains valid while \a object exists.
*/
/*!
-\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append,
+\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append,
CountFunction count, AtFunction at,
ClearFunction clear)
Construct a QQmlListProperty from a set of operation functions. An opaque \a data handle
-may be passed which can be accessed from within the operation functions. The list property
+may be passed which can be accessed from within the operation functions. The list property
remains valid while \a object exists.
Null pointers can be passed for any function. If any null pointers are passed in, the list
@@ -431,7 +431,7 @@ Return the number of elements in the list \a property.
*/
/*!
-\fn bool QQmlListProperty::operator==(const QQmlListProperty &other) const
+\fn bool QQmlListProperty::operator==(const QQmlListProperty &other) const
Returns true if this QQmlListProperty is equal to \a other, otherwise false.
*/
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 7b975c2cc8..0d60fee5d0 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -50,14 +50,17 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_MANAGED_VTABLE(QmlListWrapper);
+DEFINE_OBJECT_VTABLE(QmlListWrapper);
QmlListWrapper::QmlListWrapper(QV8Engine *engine)
: Object(QV8Engine::getV4(engine)),
v8(engine)
{
- setVTable(&static_vtbl);
- flags &= ~SimpleArray;
+ setVTable(staticVTable());
+ QV4::Scope scope(QV8Engine::getV4(engine));
+ QV4::ScopedObject protectThis(scope, this);
+ Q_UNUSED(protectThis);
+ setArrayType(ArrayData::Custom);
}
QmlListWrapper::~QmlListWrapper()
@@ -150,21 +153,20 @@ void QmlListWrapper::destroy(Managed *that)
w->~QmlListWrapper();
}
-Property *QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
+void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
{
name = (String *)0;
*index = UINT_MAX;
QmlListWrapper *w = m->as<QmlListWrapper>();
quint32 count = w->property.count ? w->property.count(&w->property) : 0;
if (it->arrayIndex < count) {
- if (attrs)
- *attrs = QV4::Attr_Data;
*index = it->arrayIndex;
++it->arrayIndex;
- it->tmpDynamicProperty.value = QV4::QObjectWrapper::wrap(w->engine(), w->property.at(&w->property, *index));
- return &it->tmpDynamicProperty;
+ *attrs = QV4::Attr_Data;
+ p->value = QV4::QObjectWrapper::wrap(w->engine(), w->property.at(&w->property, *index));
+ return;
}
- return QV4::Object::advanceIterator(m, it, name, index, attrs);
+ return QV4::Object::advanceIterator(m, it, name, index, p, attrs);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 9ece5851ed..a7ce8b30bf 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -58,7 +58,7 @@
#include <QtQml/qqmllist.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -69,7 +69,7 @@ namespace QV4 {
struct Q_QML_EXPORT QmlListWrapper : Object
{
- Q_MANAGED
+ V4_OBJECT
protected:
QmlListWrapper(QV8Engine *engine);
~QmlListWrapper();
@@ -84,7 +84,7 @@ public:
static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, const StringRef name, const ValueRef value);
- static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
static void destroy(Managed *that);
private:
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 14b5471317..fc9e2fc42a 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -54,64 +54,7 @@
QT_BEGIN_NAMESPACE
-class QQmlLocaleData : public QV4::Object
-{
- Q_MANAGED
-public:
- QQmlLocaleData(QV4::ExecutionEngine *engine)
- : QV4::Object(engine)
- {
- setVTable(&static_vtbl);
- type = Type_Object;
- }
-
- QLocale locale;
-
- static QLocale *getThisLocale(QV4::CallContext *ctx) {
- QQmlLocaleData *thisObject = ctx->callData->thisObject.asObject()->as<QQmlLocaleData>();
- if (!thisObject) {
- ctx->throwTypeError();
- return 0;
- }
- return &thisObject->locale;
- }
-
- static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_dateTimeFormat(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_timeFormat(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_dateFormat(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_monthName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_standaloneMonthName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_dayName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_standaloneDayName(QV4::CallContext *ctx);
-
- static QV4::ReturnedValue method_get_firstDayOfWeek(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_measurementSystem(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_textDirection(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_weekDays(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_uiLanguages(QV4::CallContext *ctx);
-
- static QV4::ReturnedValue method_get_name(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_nativeLanguageName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_nativeCountryName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_decimalPoint(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_groupSeparator(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_percent(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_zeroDigit(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_negativeSign(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_positiveSign(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_exponential(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_amText(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx);
-
-private:
- static void destroy(Managed *that)
- {
- static_cast<QQmlLocaleData *>(that)->~QQmlLocaleData();
- }
-};
-
-DEFINE_MANAGED_VTABLE(QQmlLocaleData);
+DEFINE_OBJECT_VTABLE(QQmlLocaleData);
#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
QV4::Scoped<QQmlLocaleData> r(scope, OBJECT.as<QQmlLocaleData>()); \
@@ -555,12 +498,11 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx)
QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject());
result->arrayReserve(days.size());
- result->arrayDataLen = days.size();
for (int i = 0; i < days.size(); ++i) {
int day = days.at(i);
if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
day = 0;
- result->arrayData[i].value = QV4::Primitive::fromInt32(day);
+ result->arrayPut(i, QV4::Primitive::fromInt32(day));
}
result->setArrayLengthUnchecked(days.size());
@@ -577,10 +519,9 @@ QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::CallContext *ctx)
QStringList langs = locale->uiLanguages();
QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject());
result->arrayReserve(langs.size());
- for (int i = 0; i < langs.size(); ++i) {
- result->arrayData[i].value = ctx->engine->newString(langs.at(i));
- result->arrayDataLen = i + 1;
- }
+ QV4::ScopedValue v(scope);
+ for (int i = 0; i < langs.size(); ++i)
+ result->arrayPut(i, (v = ctx->engine->newString(langs.at(i))));
result->setArrayLengthUnchecked(langs.size());
@@ -857,14 +798,21 @@ QQmlLocale::~QQmlLocale()
{
}
-QV4::ReturnedValue QQmlLocale::locale(QV8Engine *v8engine, const QString &locale)
+QV4::ReturnedValue QQmlLocale::locale(QV8Engine *v8engine, const QString &localeName)
+{
+ QLocale qlocale;
+ if (!localeName.isEmpty())
+ qlocale = localeName;
+ return wrap(v8engine, qlocale);
+}
+
+QV4::ReturnedValue QQmlLocale::wrap(QV8Engine *engine, const QLocale &locale)
{
- QV8LocaleDataDeletable *d = localeV8Data(v8engine);
- QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine);
- QV4::Scope scope(engine);
- QV4::Scoped<QQmlLocaleData> wrapper(scope, new (engine->memoryManager) QQmlLocaleData(engine));
- if (!locale.isEmpty())
- wrapper->locale = QLocale(locale);
+ QV8LocaleDataDeletable *d = localeV8Data(engine);
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope scope(v4);
+ QV4::Scoped<QQmlLocaleData> wrapper(scope, new (v4->memoryManager) QQmlLocaleData(v4));
+ wrapper->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
wrapper->setPrototype(p.getPointer());
return wrapper.asReturnedValue();
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 8ca67a8c83..cafe448313 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -118,7 +118,8 @@ public:
Saturday = Qt::Saturday
};
- static QV4::ReturnedValue locale(QV8Engine *v8engine, const QString &lang);
+ static QV4::ReturnedValue locale(QV8Engine *v8engine, const QString &localeName);
+ static QV4::ReturnedValue wrap(QV8Engine *engine, const QLocale &locale);
static void registerStringLocaleCompare(QV4::ExecutionEngine *engine);
@@ -128,6 +129,61 @@ private:
static QV4::ReturnedValue method_localeCompare(QV4::CallContext *ctx);
};
+class QQmlLocaleData : public QV4::Object
+{
+ V4_OBJECT
+public:
+ QQmlLocaleData(QV4::ExecutionEngine *engine)
+ : QV4::Object(engine)
+ {
+ setVTable(staticVTable());
+ }
+
+ QLocale locale;
+
+ static QLocale *getThisLocale(QV4::CallContext *ctx) {
+ QQmlLocaleData *thisObject = ctx->callData->thisObject.asObject()->as<QQmlLocaleData>();
+ if (!thisObject) {
+ ctx->throwTypeError();
+ return 0;
+ }
+ return &thisObject->locale;
+ }
+
+ static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_dateTimeFormat(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_timeFormat(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_dateFormat(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_monthName(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_standaloneMonthName(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_dayName(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_standaloneDayName(QV4::CallContext *ctx);
+
+ static QV4::ReturnedValue method_get_firstDayOfWeek(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_measurementSystem(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_textDirection(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_weekDays(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_uiLanguages(QV4::CallContext *ctx);
+
+ static QV4::ReturnedValue method_get_name(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_nativeLanguageName(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_nativeCountryName(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_decimalPoint(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_groupSeparator(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_percent(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_zeroDigit(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_negativeSign(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_positiveSign(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_exponential(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_amText(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx);
+
+private:
+ static void destroy(Managed *that)
+ {
+ static_cast<QQmlLocaleData *>(that)->~QQmlLocaleData();
+ }
+};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index d1ab50c4af..90d3ca3308 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -116,7 +116,7 @@ struct QQmlMetaTypeData
class QQmlTypeModulePrivate
{
public:
- QQmlTypeModulePrivate()
+ QQmlTypeModulePrivate()
: minMinorVersion(INT_MAX), maxMinorVersion(0), locked(false) {}
static QQmlTypeModulePrivate* get(QQmlTypeModule* q) { return q->d; }
@@ -479,7 +479,7 @@ QQmlType *QQmlType::superType() const
return d->superType;
}
-static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
+static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
{
// Set classname
@@ -491,7 +491,7 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
- // Skip
+ // Skip
} else {
builder.addClassInfo(info.name(), info.value());
}
@@ -504,7 +504,7 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
int otherIndex = ignoreEnd->indexOfProperty(property.name());
if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
- // Skip
+ // Skip
} else {
builder.addProperty(property);
}
@@ -520,7 +520,7 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
bool found = false;
- for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
+ for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
!found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
++ii) {
@@ -540,7 +540,7 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
- // Skip
+ // Skip
} else {
builder.addEnumerator(enumerator);
}
@@ -860,7 +860,7 @@ const QMetaObject *QQmlType::attachedPropertiesType() const
/*
This is the id passed to qmlAttachedPropertiesById(). This is different from the index
-for the case that a single class is registered under two or more names (eg. Item in
+for the case that a single class is registered under two or more names (eg. Item in
Qt 4.7 and QtQuick 1.0).
*/
int QQmlType::attachedPropertiesId() const
@@ -1128,7 +1128,7 @@ int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
int registerInterface(const QQmlPrivate::RegisterInterface &interface)
{
- if (interface.version > 0)
+ if (interface.version > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
QWriteLocker lock(metaTypeDataLock());
@@ -1472,7 +1472,7 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version
QQmlMetaTypeData *data = metaTypeData();
// first, check Types
- QQmlTypeModule *tm =
+ QQmlTypeModule *tm =
data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
return true;
@@ -1755,7 +1755,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri
}
/*!
- Returns the type (if any) that corresponds to the QVariant::Type \a userType.
+ Returns the type (if any) that corresponds to the QVariant::Type \a userType.
Returns null if no type is registered.
*/
QQmlType *QQmlMetaType::qmlType(int userType)
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 64f7702b64..019e6b8821 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -104,7 +104,7 @@ public:
enum TypeCategory { Unknown, Object, List };
static TypeCategory typeCategory(int);
-
+
static bool isInterface(int);
static const char *interfaceIId(int);
static bool isList(int);
@@ -278,7 +278,7 @@ private:
QQmlTypeModulePrivate *d;
};
-class QQmlTypeModuleVersion
+class QQmlTypeModuleVersion
{
public:
QQmlTypeModuleVersion();
diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp
index 3d4b260574..fb058379be 100644
--- a/src/qml/qml/qqmlnotifier.cpp
+++ b/src/qml/qml/qqmlnotifier.cpp
@@ -84,7 +84,7 @@ void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a)
// End of notifying, restore values
endpoint->senderPtr = originalSenderPtr;
}
- }
+ }
}
/*! \internal
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 93f2cd68da..0794f3a911 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -123,7 +123,7 @@ QQmlNotifier::QQmlNotifier()
}
QQmlNotifier::~QQmlNotifier()
-{
+{
QQmlNotifierEndpoint *endpoint = endpoints;
while (endpoint) {
QQmlNotifierEndpoint *n = endpoint;
@@ -221,7 +221,7 @@ bool QQmlNotifierEndpoint::isNotifying() const
/*!
Cancel any notifies that are in progress.
*/
-void QQmlNotifierEndpoint::cancelNotify()
+void QQmlNotifierEndpoint::cancelNotify()
{
if (isNotifying()) {
qintptr sp = *((qintptr *)(senderPtr & ~0x1));
diff --git a/src/qml/qml/qqmlnullablevalue_p_p.h b/src/qml/qml/qqmlnullablevalue_p_p.h
index ed3dfb8780..6c17153181 100644
--- a/src/qml/qml/qqmlnullablevalue_p_p.h
+++ b/src/qml/qml/qqmlnullablevalue_p_p.h
@@ -56,7 +56,7 @@
QT_BEGIN_NAMESPACE
template<typename T>
-struct QQmlNullableValue
+struct QQmlNullableValue
{
QQmlNullableValue()
: isNull(true), value(T()) {}
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 3798129e8b..7085915faa 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -42,7 +42,6 @@
#include "qqmlobjectcreator_p.h"
#include <private/qqmlengine_p.h>
-#include <private/qqmlabstractbinding_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qv4function_p.h>
#include <private/qv4functionobject_p.h>
@@ -52,446 +51,101 @@
#include <private/qqmlboundsignal_p.h>
#include <private/qqmltrace_p.h>
#include <private/qqmlcomponentattached_p.h>
-#include <QQmlComponent>
#include <private/qqmlcomponent_p.h>
-#include <private/qqmlcodegenerator_p.h>
+#include <private/qqmlcustomparser_p.h>
+#include <private/qqmlscriptstring_p.h>
+#include <private/qqmlpropertyvalueinterceptor_p.h>
+#include <private/qqmlvaluetypeproxybinding_p.h>
QT_USE_NAMESPACE
namespace {
struct ActiveOCRestorer
{
- ActiveOCRestorer(QmlObjectCreator *creator, QQmlEnginePrivate *ep)
+ ActiveOCRestorer(QQmlObjectCreator *creator, QQmlEnginePrivate *ep)
: ep(ep), oldCreator(ep->activeObjectCreator) { ep->activeObjectCreator = creator; }
~ActiveOCRestorer() { ep->activeObjectCreator = oldCreator; }
QQmlEnginePrivate *ep;
- QmlObjectCreator *oldCreator;
+ QQmlObjectCreator *oldCreator;
};
}
-QQmlCompilePass::QQmlCompilePass(const QUrl &url, const QV4::CompiledData::QmlUnit *unit)
- : url(url)
- , qmlUnit(unit)
+static void removeBindingOnProperty(QObject *o, int index)
{
-}
+ int coreIndex = index & 0x0000FFFF;
+ int valueTypeIndex = (index & 0xFFFF0000 ? index >> 16 : -1);
-void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description)
-{
- QQmlError error;
- error.setUrl(url);
- error.setLine(location.line);
- error.setColumn(location.column);
- error.setDescription(description);
- errors << error;
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
+ if (binding) binding->destroy();
}
-#define COMPILE_EXCEPTION(token, desc) \
- { \
- recordError((token)->location, desc); \
- return false; \
- }
-
-static QAtomicInt classIndexCounter(0);
-
-QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, const QUrl &url, const QQmlImports *imports,
- QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes)
- : QQmlCompilePass(url, unit)
- , enginePrivate(enginePrivate)
- , imports(imports)
- , resolvedTypes(resolvedTypes)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext)
+ : compiledData(compiledData)
+ , resolvedTypes(compiledData->resolvedTypes)
+ , propertyCaches(compiledData->propertyCaches)
+ , vmeMetaObjectData(compiledData->datas)
{
+ init(parentContext);
+
+ sharedState = new SharedState;
+ sharedState.setFlag(); // We own it, so we must delete it
+ sharedState->componentAttached = 0;
+ sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
+ sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
+ sharedState->creationContext = creationContext;
+ sharedState->rootContext = 0;
}
-bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **resultCache, QByteArray *vmeMetaObjectData)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, SharedState *inheritedSharedState)
+ : compiledData(compiledData)
+ , resolvedTypes(compiledData->resolvedTypes)
+ , propertyCaches(compiledData->propertyCaches)
+ , vmeMetaObjectData(compiledData->datas)
{
- Q_ASSERT(!stringAt(obj->inheritedTypeNameIndex).isEmpty());
-
- QQmlCompiledData::TypeReference typeRef = resolvedTypes->value(obj->inheritedTypeNameIndex);
- QQmlPropertyCache *baseTypeCache = typeRef.createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
- Q_ASSERT(baseTypeCache);
- if (obj->nProperties == 0 && obj->nSignals == 0 && obj->nFunctions == 0) {
- *resultCache = baseTypeCache;
- vmeMetaObjectData->clear();
- return true;
- }
-
- QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate),
- obj->nProperties,
- obj->nFunctions + obj->nProperties + obj->nSignals,
- obj->nSignals + obj->nProperties);
- *resultCache = cache;
-
- vmeMetaObjectData->clear();
-
- struct TypeData {
- QV4::CompiledData::Property::Type dtype;
- int metaType;
- } builtinTypes[] = {
- { QV4::CompiledData::Property::Var, QMetaType::QVariant },
- { QV4::CompiledData::Property::Variant, QMetaType::QVariant },
- { QV4::CompiledData::Property::Int, QMetaType::Int },
- { QV4::CompiledData::Property::Bool, QMetaType::Bool },
- { QV4::CompiledData::Property::Real, QMetaType::Double },
- { QV4::CompiledData::Property::String, QMetaType::QString },
- { QV4::CompiledData::Property::Url, QMetaType::QUrl },
- { QV4::CompiledData::Property::Color, QMetaType::QColor },
- { QV4::CompiledData::Property::Font, QMetaType::QFont },
- { QV4::CompiledData::Property::Time, QMetaType::QTime },
- { QV4::CompiledData::Property::Date, QMetaType::QDate },
- { QV4::CompiledData::Property::DateTime, QMetaType::QDateTime },
- { QV4::CompiledData::Property::Rect, QMetaType::QRectF },
- { QV4::CompiledData::Property::Point, QMetaType::QPointF },
- { QV4::CompiledData::Property::Size, QMetaType::QSizeF },
- { QV4::CompiledData::Property::Vector2D, QMetaType::QVector2D },
- { QV4::CompiledData::Property::Vector3D, QMetaType::QVector3D },
- { QV4::CompiledData::Property::Vector4D, QMetaType::QVector4D },
- { QV4::CompiledData::Property::Matrix4x4, QMetaType::QMatrix4x4 },
- { QV4::CompiledData::Property::Quaternion, QMetaType::QQuaternion }
- };
- static const uint builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
-
- QByteArray newClassName;
-
- if (false /* ### compileState->root == obj && !compileState->nested*/) {
-#if 0 // ###
- QString path = output->url.path();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- if (lastSlash > -1) {
- QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
- if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
- newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
- QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
- }
-#endif
- }
- if (newClassName.isEmpty()) {
- newClassName = QQmlMetaObject(baseTypeCache).className();
- newClassName.append("_QML_");
- newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
- }
-
- cache->_dynamicClassName = newClassName;
-
- int aliasCount = 0;
- int varPropCount = 0;
-
- const QV4::CompiledData::Property *p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
-
- if (p->type == QV4::CompiledData::Property::Alias)
- aliasCount++;
- else if (p->type == QV4::CompiledData::Property::Var)
- varPropCount++;
-
-#if 0 // ### Do this elsewhere
- // No point doing this for both the alias and non alias cases
- QQmlPropertyData *d = property(obj, p->name);
- if (d && d->isFinal())
- COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
-#endif
- }
-
- typedef QQmlVMEMetaData VMD;
-
- QByteArray &dynamicData = *vmeMetaObjectData = QByteArray(sizeof(QQmlVMEMetaData)
- + obj->nProperties * sizeof(VMD::PropertyData)
- + obj->nFunctions * sizeof(VMD::MethodData)
- + aliasCount * sizeof(VMD::AliasData), 0);
-
- int effectivePropertyIndex = cache->propertyIndexCacheStart;
- int effectiveMethodIndex = cache->methodIndexCacheStart;
-
- // For property change signal override detection.
- // We prepopulate a set of signal names which already exist in the object,
- // and throw an error if there is a signal/method defined as an override.
- QSet<QString> seenSignals;
- seenSignals << QStringLiteral("destroyed") << QStringLiteral("parentChanged") << QStringLiteral("objectNameChanged");
- QQmlPropertyCache *parentCache = cache;
- while ((parentCache = parentCache->parent())) {
- if (int pSigCount = parentCache->signalCount()) {
- int pSigOffset = parentCache->signalOffset();
- for (int i = pSigOffset; i < pSigCount; ++i) {
- QQmlPropertyData *currPSig = parentCache->signal(i);
- // XXX TODO: find a better way to get signal name from the property data :-/
- for (QQmlPropertyCache::StringCache::ConstIterator iter = parentCache->stringCache.begin();
- iter != parentCache->stringCache.end(); ++iter) {
- if (currPSig == (*iter).second) {
- seenSignals.insert(iter.key());
- break;
- }
- }
- }
- }
- }
-
- // First set up notify signals for properties - first normal, then var, then alias
- enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
- for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
-
- if (ii == NSS_Var && varPropCount == 0) continue;
- else if (ii == NSS_Alias && aliasCount == 0) continue;
-
- const QV4::CompiledData::Property *p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
- if ((ii == NSS_Normal && (p->type == QV4::CompiledData::Property::Alias ||
- p->type == QV4::CompiledData::Property::Var)) ||
- ((ii == NSS_Var) && (p->type != QV4::CompiledData::Property::Var)) ||
- ((ii == NSS_Alias) && (p->type != QV4::CompiledData::Property::Alias)))
- continue;
-
- quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
- QQmlPropertyData::IsVMESignal;
-
- QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
- seenSignals.insert(changedSigName);
-
- cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
- }
- }
-
- // Dynamic signals
- for (uint i = 0; i < obj->nSignals; ++i) {
- const QV4::CompiledData::Signal *s = obj->signalAt(i);
- const int paramCount = s->nParameters;
-
- QList<QByteArray> names;
- QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
-
- if (paramCount) {
- paramTypes[0] = paramCount;
-
- for (int i = 0; i < paramCount; ++i) {
- const QV4::CompiledData::Parameter *param = s->parameterAt(i);
- names.append(stringAt(param->nameIndex).toUtf8());
- if (param->type < builtinTypeCount) {
- // built-in type
- paramTypes[i + 1] = builtinTypes[param->type].metaType;
- } else {
- // lazily resolved type
- Q_ASSERT(param->type == QV4::CompiledData::Property::Custom);
- const QString customTypeName = stringAt(param->customTypeNameIndex);
- QQmlType *qmltype = 0;
- if (!imports->resolveType(customTypeName, &qmltype, 0, 0, 0))
- COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(customTypeName));
-
- if (qmltype->isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
-
- QQmlCompiledData *data = tdata->compiledData();
-
- paramTypes[i + 1] = data->metaTypeId;
-
- tdata->release();
- } else {
- paramTypes[i + 1] = qmltype->typeId();
- }
- }
- }
- }
-
- ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
-
- quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
- QQmlPropertyData::IsVMESignal;
- if (paramCount)
- flags |= QQmlPropertyData::HasArguments;
-
- QString signalName = stringAt(s->nameIndex);
- if (seenSignals.contains(signalName))
- COMPILE_EXCEPTION(s, tr("Duplicate signal name: invalid override of property change signal or superclass signal"));
- seenSignals.insert(signalName);
-
- cache->appendSignal(signalName, flags, effectiveMethodIndex++,
- paramCount?paramTypes.constData():0, names);
- }
-
-
- // Dynamic slots
- const quint32 *functionIndex = obj->functionOffsetTable();
- for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
- const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
- int paramCount = s->nFormals;
+ init(parentContext);
- quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
-
- if (paramCount)
- flags |= QQmlPropertyData::HasArguments;
-
- QString slotName = stringAt(s->nameIndex);
- if (seenSignals.contains(slotName))
- COMPILE_EXCEPTION(s, tr("Duplicate method name: invalid override of property change signal or superclass signal"));
- // Note: we don't append slotName to the seenSignals list, since we don't
- // protect against overriding change signals or methods with properties.
-
- const quint32 *formalsIndices = s->formalsTable();
- QList<QByteArray> parameterNames;
- parameterNames.reserve(paramCount);
- for (int i = 0; i < paramCount; ++i)
- parameterNames << stringAt(formalsIndices[i]).toUtf8();
-
- cache->appendMethod(slotName, flags, effectiveMethodIndex++, parameterNames);
- }
-
-
- // Dynamic properties (except var and aliases)
- int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
- /* const QV4::CompiledData::Property* */ p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
-
- if (p->type == QV4::CompiledData::Property::Alias ||
- p->type == QV4::CompiledData::Property::Var)
- continue;
-
- int propertyType = 0;
- int vmePropertyType = 0;
- quint32 propertyFlags = 0;
-
- if (p->type < builtinTypeCount) {
- propertyType = builtinTypes[p->type].metaType;
- vmePropertyType = propertyType;
-
- if (p->type == QV4::CompiledData::Property::Variant)
- propertyFlags |= QQmlPropertyData::IsQVariant;
- } else {
- Q_ASSERT(p->type == QV4::CompiledData::Property::CustomList ||
- p->type == QV4::CompiledData::Property::Custom);
-
- QQmlType *qmltype = 0;
- if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) {
- COMPILE_EXCEPTION(p, tr("Invalid property type"));
- }
-
- Q_ASSERT(qmltype);
- if (qmltype->isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
-
- QQmlCompiledData *data = tdata->compiledData();
-
- if (p->type == QV4::CompiledData::Property::Custom) {
- propertyType = data->metaTypeId;
- vmePropertyType = QMetaType::QObjectStar;
- } else {
- propertyType = data->listMetaTypeId;
- vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
- }
-
- tdata->release();
- } else {
- if (p->type == QV4::CompiledData::Property::Custom) {
- propertyType = qmltype->typeId();
- vmePropertyType = QMetaType::QObjectStar;
- } else {
- propertyType = qmltype->qListTypeId();
- vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
- }
- }
-
- if (p->type == QV4::CompiledData::Property::Custom)
- propertyFlags |= QQmlPropertyData::IsQObjectDerived;
- else
- propertyFlags |= QQmlPropertyData::IsQList;
- }
-
- if ((!p->flags & QV4::CompiledData::Property::IsReadOnly) && p->type != QV4::CompiledData::Property::CustomList)
- propertyFlags |= QQmlPropertyData::IsWritable;
-
-
- QString propertyName = stringAt(p->nameIndex);
- if (i == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- propertyType, effectiveSignalIndex);
-
- effectiveSignalIndex++;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
- vmd->propertyCount++;
- }
-
- // Now do var properties
- /* const QV4::CompiledData::Property* */ p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
-
- if (p->type != QV4::CompiledData::Property::Var)
- continue;
-
- quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
- if (!p->flags & QV4::CompiledData::Property::IsReadOnly)
- propertyFlags |= QQmlPropertyData::IsWritable;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
- vmd->propertyCount++;
- ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
-
- QString propertyName = stringAt(p->nameIndex);
- if (i == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- QMetaType::QVariant, effectiveSignalIndex);
-
- effectiveSignalIndex++;
- }
-
- // Alias property count. Actual data is setup in buildDynamicMetaAliases
- ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
-
- // Dynamic slot data - comes after the property data
- /*const quint32* */functionIndex = obj->functionOffsetTable();
- for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
- const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
-
- VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
- int(s->nFormals),
- /* s->location.start.line */0 }; // ###
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
- vmd->methodCount++;
- md = methodData;
- }
-
- return true;
+ sharedState = inheritedSharedState;
}
-static void removeBindingOnProperty(QObject *o, int index)
+void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
{
- int coreIndex = index & 0x0000FFFF;
- int valueTypeIndex = (index & 0xFFFF0000 ? index >> 16 : -1);
+ parentContext = providedParentContext;
+ engine = parentContext->engine;
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
- if (binding) binding->destroy();
+ if (!compiledData->isInitialized())
+ compiledData->initialize(engine);
+
+ qmlUnit = compiledData->qmlUnit;
+ context = 0;
+ _qobject = 0;
+ _scopeObject = 0;
+ _valueTypeProperty = 0;
+ _compiledObject = 0;
+ _ddata = 0;
+ _propertyCache = 0;
+ _vmeMetaObject = 0;
+ _qmlContext = 0;
}
-QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData)
- : QQmlCompilePass(compiledData->url, compiledData->qmlUnit)
- , componentAttached(0)
- , engine(parentContext->engine)
- , jsUnit(compiledData->compilationUnit)
- , parentContext(parentContext)
- , context(0)
- , resolvedTypes(compiledData->resolvedTypes)
- , propertyCaches(compiledData->propertyCaches)
- , vmeMetaObjectData(compiledData->datas)
- , compiledData(compiledData)
- , _qobject(0)
- , _qobjectForBindings(0)
- , _valueTypeProperty(0)
- , _compiledObject(0)
- , _ddata(0)
- , _propertyCache(0)
- , _vmeMetaObject(0)
- , _qmlContext(0)
+QQmlObjectCreator::~QQmlObjectCreator()
{
- if (!compiledData->isInitialized())
- compiledData->initialize(engine);
+ if (sharedState.flag()) {
+ for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) {
+ QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i);
+ if (b)
+ b->m_mePtr = 0;
+ }
+ for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
+ QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(i);
+ if (ps)
+ ps->d = 0;
+ }
+ delete sharedState.data();
+ }
}
-QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent)
+QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent)
{
int objectToCreate;
@@ -512,6 +166,11 @@ QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent)
context->imports->addref();
context->setParent(parentContext);
+ if (!sharedState->rootContext) {
+ sharedState->rootContext = context;
+ sharedState->rootContext->isRootObjectInCreation = true;
+ }
+
QVector<QQmlContextData::ObjectIdMapping> mapping(objectIndexToId.count());
for (QHash<int, int>::ConstIterator it = objectIndexToId.constBegin(), end = objectIndexToId.constEnd();
it != end; ++it) {
@@ -528,13 +187,13 @@ QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent)
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
+ context->importedScripts = scripts;
for (int i = 0; i < compiledData->scripts.count(); ++i) {
QQmlScriptData *s = compiledData->scripts.at(i);
scripts->putIndexed(i, s->scriptValueForContext(context));
}
- context->importedScripts = scripts;
- } else if (parentContext) {
- context->importedScripts = parentContext->importedScripts;
+ } else if (sharedState->creationContext) {
+ context->importedScripts = sharedState->creationContext->importedScripts;
}
QObject *instance = createInstance(objectToCreate, parent);
@@ -546,10 +205,11 @@ QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent)
context->contextObject = instance;
}
+
return instance;
}
-void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
@@ -558,7 +218,15 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
- // ### enums
+
+ // ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
+ if (property->isEnum() && !(binding->flags & QV4::CompiledData::Binding::IsResolvedEnum)) {
+ QVariant value = binding->valueAsString(&qmlUnit->header);
+ bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ return;
+ }
switch (property->propType) {
case QMetaType::QVariant: {
@@ -604,109 +272,79 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
}
break;
case QVariant::String: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QString value = binding->valueAsString(&qmlUnit->header);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: string expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QString value = binding->valueAsString(&qmlUnit->header);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::StringList: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QStringList value(binding->valueAsString(&qmlUnit->header));
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: string or string list expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QStringList value(binding->valueAsString(&qmlUnit->header));
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::ByteArray: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QByteArray value(binding->valueAsString(&qmlUnit->header).toUtf8());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: byte array expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QByteArray value(binding->valueAsString(&qmlUnit->header).toUtf8());
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Url: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QString string = binding->valueAsString(&qmlUnit->header);
- // Encoded dir-separators defeat QUrl processing - decode them first
- string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl value = string.isEmpty() ? QUrl() : this->url.resolved(QUrl(string));
- // Apply URL interceptor
- if (engine->urlInterceptor())
- value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: url expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QString string = binding->valueAsString(&qmlUnit->header);
+ // Encoded dir-separators defeat QUrl processing - decode them first
+ string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
+ QUrl value = string.isEmpty() ? QUrl() : compiledData->url.resolved(QUrl(string));
+ // Apply URL interceptor
+ if (engine->urlInterceptor())
+ value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::UInt: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber();
- if (double(uint(d)) == d) {
- uint value = uint(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- break;
- }
- }
- recordError(binding->location, tr("Invalid property assignment: unsigned int expected"));
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double d = binding->valueAsNumber();
+ uint value = uint(d);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ break;
}
break;
case QVariant::Int: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber();
- if (double(int(d)) == d) {
- int value = int(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- break;
- }
- }
- recordError(binding->location, tr("Invalid property assignment: int expected"));
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double d = binding->valueAsNumber();
+ int value = int(d);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ break;
}
break;
case QMetaType::Float: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- float value = float(binding->valueAsNumber());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: number expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ float value = float(binding->valueAsNumber());
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Double: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double value = binding->valueAsNumber();
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: number expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double value = binding->valueAsNumber();
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Color: {
bool ok = false;
uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(&qmlUnit->header), &ok);
-
- if (ok) {
- struct { void *data[4]; } buffer;
- if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
- argv[0] = reinterpret_cast<void *>(&buffer);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
- } else {
- recordError(binding->location, tr("Invalid property assignment: color expected"));
+ Q_ASSERT(ok);
+ struct { void *data[4]; } buffer;
+ if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
+ argv[0] = reinterpret_cast<void *>(&buffer);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
}
break;
@@ -714,111 +352,87 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
case QVariant::Date: {
bool ok = false;
QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: date expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Time: {
bool ok = false;
QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: time expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::DateTime: {
bool ok = false;
QDateTime value = QQmlStringConverters::dateTimeFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: datetime expected"));
+ // ### VME compatibility :(
+ {
+ const qint64 date = value.date().toJulianDay();
+ const int msecsSinceStartOfDay = value.time().msecsSinceStartOfDay();
+ value = QDateTime(QDate::fromJulianDay(date), QTime::fromMSecsSinceStartOfDay(msecsSinceStartOfDay));
}
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
#endif // QT_NO_DATESTRING
case QVariant::Point: {
bool ok = false;
QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::PointF: {
bool ok = false;
QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Size: {
bool ok = false;
QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: size expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::SizeF: {
bool ok = false;
QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: size expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Rect: {
bool ok = false;
QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::RectF: {
bool ok = false;
QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Bool: {
- if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- bool value = binding->valueAsBoolean();
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: boolean expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
+ bool value = binding->valueAsBoolean();
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Vector3D: {
@@ -827,12 +441,11 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
float yp;
float zy;
} vec;
- if (QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: 3D vector expected"));
- }
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ argv[0] = reinterpret_cast<void *>(&vec);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Vector4D: {
@@ -842,74 +455,55 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
float zy;
float wp;
} vec;
- if (QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: 4D vector expected"));
- }
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ argv[0] = reinterpret_cast<void *>(&vec);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::RegExp:
- recordError(binding->location, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
+ Q_ASSERT(!"not possible");
break;
default: {
// generate single literal value assignment to a list property if required
if (property->propType == qMetaTypeId<QList<qreal> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- QList<qreal> value;
- value.append(binding->valueAsNumber());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: real or array of reals expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ QList<qreal> value;
+ value.append(binding->valueAsNumber());
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<int> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double n = binding->valueAsNumber();
- if (double(int(n)) == n) {
- QList<int> value;
- value.append(int(n));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- break;
- } else {
- recordError(binding->location, tr("Invalid property assignment: int or array of ints expected"));
- }
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double n = binding->valueAsNumber();
+ QList<int> value;
+ value.append(int(n));
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<bool> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- QList<bool> value;
- value.append(binding->valueAsBoolean());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: bool or array of bools expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
+ QList<bool> value;
+ value.append(binding->valueAsBoolean());
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QString urlString = binding->valueAsString(&qmlUnit->header);
- QUrl u = urlString.isEmpty() ? QUrl() : this->url.resolved(QUrl(urlString));
- QList<QUrl> value;
- value.append(u);
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: url or array of urls expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QString urlString = binding->valueAsString(&qmlUnit->header);
+ QUrl u = urlString.isEmpty() ? QUrl() : compiledData->url.resolved(QUrl(urlString));
+ QList<QUrl> value;
+ value.append(u);
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<QString> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QList<QString> value;
- value.append(binding->valueAsString(&qmlUnit->header));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: string or array of strings expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QList<QString> value;
+ value.append(binding->valueAsString(&qmlUnit->header));
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QJSValue>()) {
QJSValue value;
@@ -932,38 +526,45 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
// otherwise, try a custom type assignment
QString stringValue = binding->valueAsString(&qmlUnit->header);
QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
- if (converter) {
- QVariant value = (*converter)(stringValue);
-
- QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
- if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
- recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
- break;
- }
+ Q_ASSERT(converter);
+ QVariant value = (*converter)(stringValue);
- argv[0] = value.data();
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType))));
+ QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
+ if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
+ recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
+ break;
}
+
+ argv[0] = value.data();
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
}
}
-void QmlObjectCreator::setupBindings()
+static QQmlType *qmlTypeForObject(QObject *object)
+{
+ QQmlType *type = 0;
+ const QMetaObject *mo = object->metaObject();
+ while (mo && !type) {
+ type = QQmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ return type;
+}
+
+void QQmlObjectCreator::setupBindings()
{
QQmlListProperty<void> savedList;
qSwap(_currentList, savedList);
QQmlPropertyData *property = 0;
- bool defaultPropertyQueried = false;
- QQmlPropertyData *defaultProperty = 0;
+ QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
QString id = stringAt(_compiledObject->idIndex);
if (!id.isEmpty()) {
QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context);
- if (idProperty) {
+ if (idProperty && idProperty->isWritable()) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
@@ -974,6 +575,36 @@ void QmlObjectCreator::setupBindings()
}
}
+ // ### this is best done through type-compile-time binding skip lists.
+ if (_valueTypeProperty) {
+ QQmlAbstractBinding *binding =
+ QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1);
+
+ if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
+ QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0);
+ binding->destroy();
+ } else if (binding) {
+ QQmlValueTypeProxyBinding *proxy =
+ static_cast<QQmlValueTypeProxyBinding *>(binding);
+
+ if (qmlTypeForObject(_bindingTarget)) {
+ quint32 bindingSkipList = 0;
+
+ const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
+ for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Script)
+ continue;
+ property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
+ if (property)
+ bindingSkipList |= (1 << property->coreIndex);
+ }
+ property = 0;
+
+ proxy->removeBindings(bindingSkipList);
+ }
+ }
+ }
+
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
@@ -981,16 +612,18 @@ void QmlObjectCreator::setupBindings()
if (name.isEmpty())
property = 0;
- if (!property || (i > 0 && (binding - 1)->propertyNameIndex != binding->propertyNameIndex)) {
- if (!name.isEmpty())
- property = _propertyCache->property(name, _qobject, context);
- else {
- if (!defaultPropertyQueried) {
- defaultProperty = _propertyCache->defaultProperty();
- defaultPropertyQueried = true;
- }
+ if (!property
+ || (i > 0 && ((binding - 1)->propertyNameIndex != binding->propertyNameIndex
+ || (binding - 1)->flags != binding->flags))
+ ) {
+ if (!name.isEmpty()) {
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ property = PropertyResolver(_propertyCache).signal(name, /*notInRevision*/0, _qobject, context);
+ else
+ property = _propertyCache->property(name, _qobject, context);
+ } else
property = defaultProperty;
- }
if (property && property->isQList()) {
void *argv[1] = { (void*)&_currentList };
@@ -1000,29 +633,50 @@ void QmlObjectCreator::setupBindings()
}
- if (!setPropertyValue(property, i, binding))
+ if (!setPropertyBinding(property, binding))
return;
}
qSwap(_currentList, savedList);
}
-bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingIndex, const QV4::CompiledData::Binding *binding)
+bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
- QQmlType *attachedType = resolvedTypes.value(binding->propertyNameIndex).type;
+ QQmlCompiledData::TypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
+ Q_ASSERT(tr);
+ QQmlType *attachedType = tr->type;
const int id = attachedType->attachedPropertiesId();
QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject);
QQmlRefPointer<QQmlPropertyCache> cache = QQmlEnginePrivate::get(engine)->cache(qmlObject);
- if (!populateInstance(binding->value.objectIndex, qmlObject, cache, _qobject, /*value type property*/0))
+ if (!populateInstance(binding->value.objectIndex, qmlObject, cache, qmlObject, /*value type property*/0))
return false;
return true;
}
+ // ### resolve this at compile time
+ if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
+ QQmlScriptString ss(binding->valueAsScriptString(&qmlUnit->header), context->asQQmlContext(), _scopeObject);
+ ss.d.data()->bindingId = 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();
+
+ QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
+ QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ int propertyWriteStatus = -1;
+ void *argv[] = { &ss, 0, &propertyWriteStatus, &propertyWriteFlags };
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ return true;
+ }
+
QObject *createdSubObject = 0;
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
- createdSubObject = createInstance(binding->value.objectIndex, _qobject);
+ Q_ASSERT(!_valueTypeProperty);
+ createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
if (!createdSubObject)
return false;
}
@@ -1035,11 +689,11 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
- QQmlRefPointer<QQmlPropertyCache> groupedObjCache;
- QObject *groupedObjInstance = 0;
- QObject *objForBindings = _qobjectForBindings;
+ QQmlRefPointer<QQmlPropertyCache> groupObjectPropertyCache;
+ QObject *groupObject = 0;
QQmlValueType *valueType = 0;
QQmlPropertyData *valueTypeProperty = 0;
+ QObject *bindingTarget = _bindingTarget;
if (QQmlValueTypeFactory::isValueType(property->propType)) {
valueType = QQmlValueTypeFactory::valueType(property->propType);
@@ -1050,27 +704,27 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
valueType->read(_qobject, property->coreIndex);
- groupedObjCache = enginePrivate->cache(valueType);
- groupedObjInstance = valueType;
+ groupObjectPropertyCache = enginePrivate->cache(valueType);
+ groupObject = valueType;
valueTypeProperty = property;
} else {
- groupedObjCache = enginePrivate->propertyCacheForType(property->propType);
- if (!groupedObjCache) {
+ groupObjectPropertyCache = enginePrivate->propertyCacheForType(property->propType);
+ if (!groupObjectPropertyCache) {
recordError(binding->location, tr("Invalid grouped property access"));
return false;
}
- void *argv[1] = { &groupedObjInstance };
+ void *argv[1] = { &groupObject };
QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
- if (!groupedObjInstance) {
+ if (!groupObject) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
return false;
}
- objForBindings = groupedObjInstance;
+ bindingTarget = groupObject;
}
- if (!populateInstance(binding->value.objectIndex, groupedObjInstance, groupedObjCache, objForBindings, valueTypeProperty))
+ if (!populateInstance(binding->value.objectIndex, groupObject, groupObjectPropertyCache, bindingTarget, valueTypeProperty))
return false;
if (valueType)
@@ -1080,25 +734,27 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
}
}
- if (_ddata->hasBindingBit(property->coreIndex))
- removeBindingOnProperty(_qobject, property->coreIndex);
+ if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
+ && !_valueTypeProperty)
+ removeBindingOnProperty(_bindingTarget, property->coreIndex);
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
QV4::Scope scope(_qmlContext);
QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction));
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
- QQmlBoundSignal *bs = new QQmlBoundSignal(_qobject, signalIndex, _qobject, engine);
- QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_qobject, signalIndex,
- context, _qobject, function);
+ QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
+ QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
+ context, _scopeObject, function);
bs->takeExpression(expr);
} else {
- QQmlBinding *qmlBinding = new QQmlBinding(function, _qobject, context,
- QString(), 0, 0); // ###
+ QQmlBinding *qmlBinding = new QQmlBinding(function, _scopeObject, context,
+ context->urlString, binding->location.line, binding->location.column);
// When writing bindings to grouped properties implemented as value types,
// such as point.x: { someExpression; }, then the binding is installed on
@@ -1109,16 +765,82 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
if (_valueTypeProperty)
targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
- qmlBinding->setTarget(_qobjectForBindings, targetCorePropertyData, context);
- qmlBinding->addToObject();
+ qmlBinding->setTarget(_bindingTarget, targetCorePropertyData, context);
+
+ if (targetCorePropertyData.isAlias()) {
+ QQmlAbstractBinding *old =
+ QQmlPropertyPrivate::setBindingNoEnable(_bindingTarget,
+ targetCorePropertyData.coreIndex,
+ targetCorePropertyData.getValueTypeCoreIndex(),
+ qmlBinding);
+ if (old) { old->destroy(); }
+ } else {
+ qmlBinding->addToObject();
+ }
- _createdBindings[bindingIndex] = qmlBinding;
- qmlBinding->m_mePtr = &_createdBindings[bindingIndex];
+ sharedState->allCreatedBindings.push(qmlBinding);
+ qmlBinding->m_mePtr = &sharedState->allCreatedBindings.top();
}
return true;
}
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
+ // ### determine value source and interceptor casts ahead of time.
+ QQmlType *type = qmlTypeForObject(createdSubObject);
+ Q_ASSERT(type);
+
+ QQmlPropertyData targetCorePropertyData = *property;
+ if (_valueTypeProperty)
+ targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
+
+ int valueSourceCast = type->propertyValueSourceCast();
+ if (valueSourceCast != -1) {
+ QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
+ QObject *target = createdSubObject->parent();
+ vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
+ return true;
+ }
+ int valueInterceptorCast = type->propertyValueInterceptorCast();
+ if (valueInterceptorCast != -1) {
+ QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
+ QObject *target = createdSubObject->parent();
+
+ QQmlProperty prop =
+ QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
+ vi->setTarget(prop);
+ QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
+ Q_ASSERT(mo);
+ mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi);
+ return true;
+ }
+ return false;
+ }
+
+ // Assigning object to signal property?
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
+ if (!property->isFunction()) {
+ recordError(binding->valueLocation, tr("Cannot assign an object to signal property %1").arg(property->name(_qobject)));
+ return false;
+ }
+ QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
+ if (!method.isValid()) {
+ recordError(binding->valueLocation, tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(createdSubObject->metaObject()->className())));
+ return false;
+ }
+
+ QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex);
+ if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
+ recordError(binding->valueLocation, tr("Cannot connect mismatched signal/slot %1 %vs. %2")
+ .arg(QString::fromLatin1(method.methodSignature().constData()))
+ .arg(QString::fromLatin1(signalMethod.methodSignature().constData())));
+ return false;
+ }
+
+ QQmlPropertyPrivate::connect(_qobject, property->coreIndex, createdSubObject, method.methodIndex());
+ return true;
+ }
+
QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
@@ -1159,33 +881,9 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
if (_currentList.append)
_currentList.append(&_currentList, itemToAdd);
} else {
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
-
- // We want to raw metaObject here as the raw metaobject is the
- // actual property type before we applied any extensions that might
- // effect the properties on the type, but don't effect assignability
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
-
- // Will be true if the assgned type inherits propertyMetaObject
- bool isAssignable = false;
- // Determine isAssignable value
- if (propertyMetaObject) {
- QQmlPropertyCache *c = propertyCaches.value(binding->value.objectIndex);
- if (!c)
- c = enginePrivate->cache(createdSubObject);
- while (c && !isAssignable) {
- isAssignable |= c == propertyMetaObject;
- c = c->parent();
- }
- }
-
- if (isAssignable) {
- argv[0] = &createdSubObject;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Cannot assign object to property"));
- return false;
- }
+ // pointer compatibility was tested in QQmlPropertyValidator at type compile time
+ argv[0] = &createdSubObject;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
return true;
}
@@ -1199,15 +897,14 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
return true;
}
-void QmlObjectCreator::setupFunctions()
+void QQmlObjectCreator::setupFunctions()
{
QV4::Scope scope(_qmlContext);
QV4::ScopedValue function(scope);
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(_qobject);
const quint32 *functionIdx = _compiledObject->functionOffsetTable();
for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
- QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[*functionIdx];
+ QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[*functionIdx];
const QString name = runtimeFunction->name->toQString();
QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
@@ -1215,16 +912,28 @@ void QmlObjectCreator::setupFunctions()
continue;
function = QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction);
- vme->setVmeMethod(property->coreIndex, function);
+ _vmeMetaObject->setVmeMethod(property->coreIndex, function);
}
}
-QObject *QmlObjectCreator::createInstance(int index, QObject *parent)
+void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
+{
+ QQmlError error;
+ error.setUrl(compiledData->url);
+ error.setLine(location.line);
+ error.setColumn(location.column);
+ error.setDescription(description);
+ errors << error;
+}
+
+QObject *QQmlObjectCreator::createInstance(int index, QObject *parent)
{
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
bool isComponent = false;
QObject *instance = 0;
+ QQmlCustomParser *customParser = 0;
+ QQmlParserStatus *parserStatus = 0;
if (compiledData->isComponent(index)) {
isComponent = true;
@@ -1234,30 +943,40 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent)
} else {
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
- QQmlCompiledData::TypeReference typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
- QQmlType *type = typeRef.type;
+ QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+ QQmlType *type = typeRef->type;
if (type) {
instance = type->create();
if (!instance) {
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
return 0;
}
+
+ const int parserStatusCast = type->parserStatusCast();
+ if (parserStatusCast != -1)
+ parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast);
+
+ customParser = type->customParser();
+
+ if (sharedState->rootContext->isRootObjectInCreation) {
+ QQmlData *ddata = QQmlData::get(instance, /*create*/true);
+ ddata->rootObjectInCreation = true;
+ sharedState->rootContext->isRootObjectInCreation = false;
+ }
} else {
- Q_ASSERT(typeRef.component);
- if (typeRef.component->qmlUnit->isSingleton())
+ Q_ASSERT(typeRef->component);
+ if (typeRef->component->qmlUnit->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
return 0;
}
- QmlObjectCreator subCreator(context, typeRef.component);
+ QQmlObjectCreator subCreator(context, typeRef->component, sharedState.data());
instance = subCreator.create();
if (!instance) {
errors += subCreator.errors;
return 0;
}
- if (subCreator.componentAttached)
- subCreator.componentAttached->add(&componentAttached);
- allCreatedBindings << subCreator.allCreatedBindings;
}
// ### use no-event variant
if (parent)
@@ -1265,7 +984,8 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent)
}
QQmlData *ddata = QQmlData::get(instance, /*create*/true);
- if (static_cast<quint32>(index) == qmlUnit->indexOfRootObject) {
+ ddata->setImplicitDestructible();
+ if (static_cast<quint32>(index) == qmlUnit->indexOfRootObject || ddata->rootObjectInCreation) {
if (ddata->context) {
Q_ASSERT(ddata->context != context);
Q_ASSERT(ddata->outerContext);
@@ -1281,50 +1001,103 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent)
ddata->outerContext = context;
+ if (parserStatus) {
+ parserStatus->classBegin();
+ sharedState->allParserStatusCallbacks.push(parserStatus);
+ parserStatus->d = &sharedState->allParserStatusCallbacks.top();
+ }
+
QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(index);
if (idEntry != objectIndexToId.constEnd())
context->setIdProperty(idEntry.value(), instance);
- if (!isComponent) {
- QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.value(index);
- Q_ASSERT(!cache.isNull());
-
- if (!populateInstance(index, instance, cache, instance, /*value type property*/0))
- return 0;
+ if (customParser) {
+ QHash<int, QByteArray>::ConstIterator entry = compiledData->customParserData.find(index);
+ if (entry != compiledData->customParserData.constEnd())
+ customParser->setCustomData(instance, *entry);
}
- return instance;
+ if (isComponent)
+ return instance;
+
+ QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.value(index);
+ Q_ASSERT(!cache.isNull());
+
+ QObject *scopeObject = instance;
+ qSwap(_scopeObject, scopeObject);
+
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope valueScope(v4);
+ QV4::ScopedValue scopeObjectProtector(valueScope, ddata ? ddata->jsWrapper.value() : 0);
+ Q_UNUSED(scopeObjectProtector);
+ QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
+ QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
+ QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
+
+ qSwap(_qmlContext, qmlContext);
+
+ bool result = populateInstance(index, instance, cache, /*binding target*/instance, /*value type property*/0);
+
+ qSwap(_qmlContext, qmlContext);
+ qSwap(_scopeObject, scopeObject);
+
+ return result ? instance : 0;
}
-void QmlObjectCreator::finalize()
+QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
{
{
QQmlTrace trace("VME Binding Enable");
trace.event("begin binding eval");
- Q_ASSERT(allCreatedBindings.isEmpty() || allCreatedBindings.isDetached());
+ while (!sharedState->allCreatedBindings.isEmpty()) {
+ if (interrupt.shouldInterrupt())
+ return 0;
- for (QLinkedList<QVector<QQmlAbstractBinding*> >::Iterator it = allCreatedBindings.begin(), end = allCreatedBindings.end();
- it != end; ++it) {
- const QVector<QQmlAbstractBinding *> &bindings = *it;
- for (int i = 0; i < bindings.count(); ++i) {
- QQmlAbstractBinding *b = bindings.at(i);
- if (!b)
- continue;
- b->m_mePtr = 0;
- QQmlData *data = QQmlData::get(b->object());
- Q_ASSERT(data);
- data->clearPendingBindingBit(b->propertyIndex());
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlAbstractBinding *b = sharedState->allCreatedBindings.pop();
+ if (!b)
+ continue;
+ b->m_mePtr = 0;
+ QQmlData *data = QQmlData::get(b->object());
+ Q_ASSERT(data);
+ data->clearPendingBindingBit(b->propertyIndex());
+ b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+ QQmlPropertyPrivate::DontRemoveBinding);
+ }
+ }
+
+ if (true /* ### componentCompleteEnabled()*/) { // the qml designer does the component complete later
+ QQmlTrace trace("VME Component Complete");
+ while (!sharedState->allParserStatusCallbacks.isEmpty()) {
+ QQmlParserStatus *status = sharedState->allParserStatusCallbacks.pop();
+
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
+
+ if (interrupt.shouldInterrupt())
+ return 0;
}
}
+
+ {
+ QQmlTrace trace("VME Finalize Callbacks");
+ for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
+ QQmlEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
+ QObject *obj = callback.first;
+ if (obj) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
+ }
+ }
+ finalizeCallbacks.clear();
}
{
QQmlTrace trace("VME Component.onCompleted Callbacks");
- while (componentAttached) {
- QQmlComponentAttached *a = componentAttached;
+ while (sharedState->componentAttached) {
+ QQmlComponentAttached *a = sharedState->componentAttached;
a->rem();
QQmlData *d = QQmlData::get(a->parent());
Q_ASSERT(d);
@@ -1333,42 +1106,44 @@ void QmlObjectCreator::finalize()
// ### designer if (componentCompleteEnabled())
emit a->completed();
-#if 0 // ###
- if (watcher.hasRecursed() || interrupt.shouldInterrupt())
+ if (interrupt.shouldInterrupt())
return 0;
-#endif
}
}
+
+ return sharedState->rootContext;
}
-bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache,
- QObject *scopeObjectForBindings, QQmlPropertyData *valueTypeProperty)
+bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty)
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
- Q_ASSERT(scopeObjectForBindings);
-
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
qSwap(_propertyCache, cache);
qSwap(_qobject, instance);
- qSwap(_qobjectForBindings, scopeObjectForBindings);
qSwap(_valueTypeProperty, valueTypeProperty);
qSwap(_compiledObject, obj);
qSwap(_ddata, declarativeData);
+ qSwap(_bindingTarget, bindingTarget);
+
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope valueScope(v4);
+ QV4::ScopedValue scopeObjectProtector(valueScope);
QQmlVMEMetaObject *vmeMetaObject = 0;
const QByteArray data = vmeMetaObjectData.value(index);
if (!data.isEmpty()) {
// install on _object
- vmeMetaObject = new QQmlVMEMetaObject(_qobjectForBindings, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
+ vmeMetaObject = new QQmlVMEMetaObject(_qobject, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
if (_ddata->propertyCache)
_ddata->propertyCache->release();
- _ddata->propertyCache = _propertyCache;
- _ddata->propertyCache->addref();
+ scopeObjectProtector = _ddata->jsWrapper.value();
} else {
- vmeMetaObject = QQmlVMEMetaObject::get(_qobjectForBindings);
+ vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
}
+ _ddata->propertyCache = _propertyCache;
+ _ddata->propertyCache->addref();
_ddata->lineNumber = _compiledObject->location.line;
_ddata->columnNumber = _compiledObject->location.column;
@@ -1376,389 +1151,19 @@ bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPoi
qSwap(_vmeMetaObject, vmeMetaObject);
QVector<QQmlAbstractBinding*> createdBindings(_compiledObject->nBindings, 0);
- qSwap(_createdBindings, createdBindings);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- QV4::Scope valueScope(v4);
- QV4::ScopedObject scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _qobjectForBindings));
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, scopeObject));
- QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
-
- qSwap(_qmlContext, qmlContext);
-
- setupBindings();
setupFunctions();
+ setupBindings();
- allCreatedBindings.append(_createdBindings);
-
- qSwap(_qmlContext, qmlContext);
-
- qSwap(_createdBindings, createdBindings);
qSwap(_vmeMetaObject, vmeMetaObject);
- qSwap(_propertyCache, cache);
+ qSwap(_bindingTarget, bindingTarget);
qSwap(_ddata, declarativeData);
qSwap(_compiledObject, obj);
qSwap(_valueTypeProperty, valueTypeProperty);
- qSwap(_qobjectForBindings, scopeObjectForBindings);
qSwap(_qobject, instance);
+ qSwap(_propertyCache, cache);
return errors.isEmpty();
}
-QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
- const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
- const QList<QQmlPropertyCache *> &propertyCaches, QList<QByteArray> *vmeMetaObjectData,
- QHash<int, int> *objectIndexToIdForRoot,
- QHash<int, QHash<int, int> > *objectIndexToIdPerComponent)
- : QQmlCompilePass(url, qmlUnit)
- , _componentIndex(-1)
- , _objectIndexToIdInScope(0)
- , resolvedTypes(resolvedTypes)
- , propertyCaches(propertyCaches)
- , vmeMetaObjectData(vmeMetaObjectData)
- , objectIndexToIdForRoot(objectIndexToIdForRoot)
- , objectIndexToIdPerComponent(objectIndexToIdPerComponent)
-{
-}
-
-bool QQmlComponentAndAliasResolver::resolve()
-{
- Q_ASSERT(componentRoots.isEmpty());
-
- // Find objects that are Components. This is missing an extra pass
- // that finds implicitly defined components, i.e.
- // someProperty: Item { ... }
- // when someProperty _is_ a QQmlComponent. In that case the Item {}
- // should be implicitly surrounded by Component {}
-
- for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
- if (stringAt(obj->inheritedTypeNameIndex).isEmpty())
- continue;
-
- QQmlCompiledData::TypeReference tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
- if (!tref.type)
- continue;
- if (tref.type->metaObject() != &QQmlComponent::staticMetaObject)
- continue;
-
- componentRoots.append(i);
- // Sanity checks: There can be only an (optional) id property and
- // a default property, that defines the component tree.
- }
-
- std::sort(componentRoots.begin(), componentRoots.end());
-
- // For each component's tree, remember to which component the children
- // belong to
- for (int i = 0; i < componentRoots.count(); ++i) {
- const QV4::CompiledData::Object *component = qmlUnit->objectAt(componentRoots.at(i));
-
- if (component->nFunctions > 0)
- COMPILE_EXCEPTION(component, tr("Component objects cannot declare new functions."));
- if (component->nProperties > 0)
- COMPILE_EXCEPTION(component, tr("Component objects cannot declare new properties."));
- if (component->nSignals > 0)
- COMPILE_EXCEPTION(component, tr("Component objects cannot declare new signals."));
-
- if (component->nBindings == 0)
- COMPILE_EXCEPTION(component, tr("Cannot create empty component specification"));
-
- const QV4::CompiledData::Binding *rootBinding = component->bindingTable();
- if (component->nBindings > 1 || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
- COMPILE_EXCEPTION(rootBinding, tr("Component elements may not contain properties other than id"));
-
- _componentIndex = i;
- _idToObjectIndex.clear();
-
- _objectIndexToIdInScope = &(*objectIndexToIdPerComponent)[componentRoots.at(i)];
-
- _objectsWithAliases.clear();
-
- if (!collectIdsAndAliases(rootBinding->value.objectIndex))
- return false;
-
- if (!resolveAliases())
- return false;
- }
-
- // Collect ids and aliases for root
- _componentIndex = -1;
- _idToObjectIndex.clear();
- _objectIndexToIdInScope = objectIndexToIdForRoot;
- _objectsWithAliases.clear();
-
- collectIdsAndAliases(qmlUnit->indexOfRootObject);
-
- resolveAliases();
-
- return errors.isEmpty();
-}
-
-bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
-{
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
-
- // Only include creatable types. Everything else is synthetic, such as group property
- // objects.
- if (_componentIndex != -1 && !stringAt(obj->inheritedTypeNameIndex).isEmpty())
- objectIndexToComponentIndex.insert(objectIndex, _componentIndex);
-
- QString id = stringAt(obj->idIndex);
- if (!id.isEmpty()) {
- if (_idToObjectIndex.contains(obj->idIndex)) {
- recordError(obj->locationOfIdProperty, tr("id is not unique"));
- return false;
- }
- _idToObjectIndex.insert(obj->idIndex, objectIndex);
- _objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
- }
-
- const QV4::CompiledData::Property *property = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++property)
- if (property->type == QV4::CompiledData::Property::Alias) {
- _objectsWithAliases.append(objectIndex);
- break;
- }
-
- const QV4::CompiledData::Binding *binding = obj->bindingTable();
- for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
- if (binding->type != QV4::CompiledData::Binding::Type_Object
- && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
- && binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
- continue;
-
- // Stop at Component boundary
- if (std::binary_search(componentRoots.constBegin(), componentRoots.constEnd(), binding->value.objectIndex))
- continue;
-
- if (!collectIdsAndAliases(binding->value.objectIndex))
- return false;
- }
-
- return true;
-}
-
-bool QQmlComponentAndAliasResolver::resolveAliases()
-{
- foreach (int objectIndex, _objectsWithAliases) {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
-
- QQmlPropertyCache *propertyCache = propertyCaches.value(objectIndex);
- Q_ASSERT(propertyCache);
-
- int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.count();
- int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
- int effectiveAliasIndex = 0;
-
- const QV4::CompiledData::Property *p = obj->propertyTable();
- for (quint32 propertyIndex = 0; propertyIndex < obj->nProperties; ++propertyIndex, ++p) {
- if (p->type != QV4::CompiledData::Property::Alias)
- continue;
-
- const int idIndex = p->aliasIdValueIndex;
- const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
- if (targetObjectIndex == -1) {
- recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
- return false;
- }
- const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
- Q_ASSERT(targetId != -1);
-
- const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex);
-
- QStringRef property;
- QStringRef subProperty;
-
- const int propertySeparator = aliasPropertyValue.indexOf(QLatin1Char('.'));
- if (propertySeparator != -1) {
- property = aliasPropertyValue.leftRef(propertySeparator);
- subProperty = aliasPropertyValue.midRef(propertySeparator + 1);
- } else
- property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length());
-
- int propIdx = -1;
- int propType = 0;
- int notifySignal = -1;
- int flags = 0;
- int type = 0;
- bool writable = false;
- bool resettable = false;
-
- quint32 propertyFlags = QQmlPropertyData::IsAlias;
-
- if (property.isEmpty()) {
- const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(targetObjectIndex);
- QQmlCompiledData::TypeReference typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex);
-
- if (typeRef.type)
- type = typeRef.type->typeId();
- else
- type = typeRef.component->metaTypeId;
-
- flags |= QML_ALIAS_FLAG_PTR;
- propertyFlags |= QQmlPropertyData::IsQObjectDerived;
- } else {
- QQmlPropertyCache *targetCache = propertyCaches.value(targetObjectIndex);
- Q_ASSERT(targetCache);
- QtQml::PropertyResolver resolver(targetCache);
-
- QQmlPropertyData *targetProperty = resolver.property(property.toString());
- if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
- recordError(p->aliasLocation, tr("Invalid alias location"));
- return false;
- }
-
- propIdx = targetProperty->coreIndex;
- type = targetProperty->propType;
-
- writable = targetProperty->isWritable();
- resettable = targetProperty->isResettable();
- notifySignal = targetProperty->notifyIndex;
-
- if (!subProperty.isEmpty()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
- if (!valueType) {
- recordError(p->aliasLocation, tr("Invalid alias location"));
- return false;
- }
-
- propType = type;
-
- int valueTypeIndex =
- valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData());
- if (valueTypeIndex == -1) {
- recordError(p->aliasLocation, tr("Invalid alias location"));
- return false;
- }
- Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
-
- propIdx |= (valueTypeIndex << 16);
- if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
- type = QVariant::Int;
- else
- type = valueType->metaObject()->property(valueTypeIndex).userType();
-
- } else {
- if (targetProperty->isEnum()) {
- type = QVariant::Int;
- } else {
- // Copy type flags
- propertyFlags |= targetProperty->getFlags() & QQmlPropertyData::PropTypeFlagMask;
-
- if (targetProperty->isVarProperty())
- propertyFlags |= QQmlPropertyData::IsQVariant;
-
- if (targetProperty->isQObject())
- flags |= QML_ALIAS_FLAG_PTR;
- }
- }
- }
-
- QQmlVMEMetaData::AliasData aliasData = { targetId, propIdx, propType, flags, notifySignal };
-
- typedef QQmlVMEMetaData VMD;
- QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex];
- Q_ASSERT(!dynamicData.isEmpty());
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- *(vmd->aliasData() + effectiveAliasIndex++) = aliasData;
-
- Q_ASSERT(dynamicData.isDetached());
-
- if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
- propertyFlags |= QQmlPropertyData::IsWritable;
- else
- propertyFlags &= ~QQmlPropertyData::IsWritable;
-
- if (resettable)
- propertyFlags |= QQmlPropertyData::IsResettable;
- else
- propertyFlags &= ~QQmlPropertyData::IsResettable;
-
- QString propertyName = stringAt(p->nameIndex);
- if (propertyIndex == obj->indexOfDefaultProperty) propertyCache->_defaultPropertyName = propertyName;
- propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- type, effectiveSignalIndex++);
-
- }
- }
- return true;
-}
-
-
-QQmlPropertyValidator::QQmlPropertyValidator(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
- const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
- const QList<QQmlPropertyCache *> &propertyCaches, const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent)
- : QQmlCompilePass(url, qmlUnit)
- , resolvedTypes(resolvedTypes)
- , propertyCaches(propertyCaches)
- , objectIndexToIdPerComponent(objectIndexToIdPerComponent)
-{
-}
-
-bool QQmlPropertyValidator::validate()
-{
- for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
- if (stringAt(obj->inheritedTypeNameIndex).isEmpty())
- continue;
-
- if (isComponent(i))
- continue;
-
- QQmlPropertyCache *propertyCache = propertyCaches.value(i);
- Q_ASSERT(propertyCache);
-
- if (!validateObject(obj, i, propertyCache))
- return false;
- }
- return true;
-}
-
-bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache)
-{
- PropertyResolver propertyResolver(propertyCache);
-
- QQmlPropertyData *defaultProperty = propertyCache->defaultProperty();
-
- const QV4::CompiledData::Binding *binding = obj->bindingTable();
- for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
- if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty
- || binding->type == QV4::CompiledData::Binding::Type_GroupProperty)
- continue;
-
- const QString name = stringAt(binding->propertyNameIndex);
-
- bool bindingToDefaultProperty = false;
-
- bool notInRevision = false;
- QQmlPropertyData *pd = 0;
- if (!name.isEmpty()) {
- pd = propertyResolver.property(name, &notInRevision);
-
- if (notInRevision) {
- QString typeName = stringAt(obj->inheritedTypeNameIndex);
- QQmlCompiledData::TypeReference type = resolvedTypes.value(objectIndex);
- if (type.type) {
- COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
- } else {
- COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
- }
- }
- } else {
- pd = defaultProperty;
- bindingToDefaultProperty = true;
- }
-
- if (!pd) {
- if (bindingToDefaultProperty) {
- COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent default property"));
- } else {
- COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent property \"%1\"").arg(name));
- }
- }
- }
-
- return true;
-}
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index ec4b362491..c48d7d3c05 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -45,139 +45,79 @@
#include <private/qqmltypenamecache_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmlcompiler_p.h>
-#include <QLinkedList>
+#include <private/qqmltypecompiler_p.h>
+#include <private/qfinitestack_p.h>
QT_BEGIN_NAMESPACE
class QQmlAbstractBinding;
+struct QQmlTypeCompiler;
+class QQmlInstantiationInterrupt;
-struct QQmlCompilePass
+class QQmlObjectCreator
{
- QQmlCompilePass(const QUrl &url, const QV4::CompiledData::QmlUnit *unit);
- QList<QQmlError> errors;
-
-protected:
- QString stringAt(int idx) const { return qmlUnit->header.stringAt(idx); }
- void recordError(const QV4::CompiledData::Location &location, const QString &description);
-
- const QUrl url;
- const QV4::CompiledData::QmlUnit *qmlUnit;
-};
-
-class QQmlPropertyCacheCreator : public QQmlCompilePass
-{
- Q_DECLARE_TR_FUNCTIONS(QQmlPropertyCacheCreator)
+ Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
+ struct SharedState;
public:
- QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *qmlUnit,
- const QUrl &url, const QQmlImports *imports,
- QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes);
+ QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext);
+ ~QQmlObjectCreator();
- bool create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **cache, QByteArray *vmeMetaObjectData);
+ QObject *create(int subComponentIndex = -1, QObject *parent = 0);
+ QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
-protected:
- QQmlEnginePrivate *enginePrivate;
- const QQmlImports *imports;
- QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes;
-};
+ QQmlComponentAttached **componentAttachment() { return &sharedState->componentAttached; }
-class QQmlComponentAndAliasResolver : public QQmlCompilePass
-{
- Q_DECLARE_TR_FUNCTIONS(QQmlAnonymousComponentResolver)
-public:
- QQmlComponentAndAliasResolver(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
- const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
- const QList<QQmlPropertyCache *> &propertyCaches,
- QList<QByteArray> *vmeMetaObjectData,
- QHash<int, int> *objectIndexToIdForRoot,
- QHash<int, QHash<int, int> > *objectIndexToIdPerComponent);
-
- bool resolve();
-
- QVector<int> componentRoots;
- QHash<int, int> objectIndexToComponentIndex;
-
-protected:
- bool collectIdsAndAliases(int objectIndex);
- bool resolveAliases();
-
- bool isComponentType(int typeNameIndex) const
- { return resolvedTypes.value(typeNameIndex).type == 0; }
-
- int _componentIndex;
- QHash<int, int> _idToObjectIndex;
- QHash<int, int> *_objectIndexToIdInScope;
- QList<int> _objectsWithAliases;
-
- const QHash<int, QQmlCompiledData::TypeReference> resolvedTypes;
- const QList<QQmlPropertyCache *> propertyCaches;
- QList<QByteArray> *vmeMetaObjectData;
- QHash<int, int> *objectIndexToIdForRoot;
- QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
-};
+ QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
-class QQmlPropertyValidator : public QQmlCompilePass
-{
- Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
-public:
- QQmlPropertyValidator(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
- const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
- const QList<QQmlPropertyCache *> &propertyCaches,
- const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent);
+ QList<QQmlError> errors;
- bool validate();
+ QQmlContextData *parentContextData() const { return parentContext; }
private:
- bool validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache);
+ QQmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData, SharedState *inheritedSharedState);
- bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
+ void init(QQmlContextData *parentContext);
- const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes;
- const QList<QQmlPropertyCache *> &propertyCaches;
- const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
-};
-
-class QmlObjectCreator : public QQmlCompilePass
-{
- Q_DECLARE_TR_FUNCTIONS(QmlObjectCreator)
-public:
- QmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData);
-
- QObject *create(int subComponentIndex = -1, QObject *parent = 0);
- void finalize();
-
- QQmlComponentAttached *componentAttached;
- QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
-
-private:
QObject *createInstance(int index, QObject *parent = 0);
- bool populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache,
- QObject *scopeObjectForJavaScript, QQmlPropertyData *valueTypeProperty);
+ bool populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty);
void setupBindings();
- bool setPropertyValue(QQmlPropertyData *property, int index, const QV4::CompiledData::Binding *binding);
+ bool setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
void setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
void setupFunctions();
+ QString stringAt(int idx) const { return qmlUnit->header.stringAt(idx); }
+ void recordError(const QV4::CompiledData::Location &location, const QString &description);
+
+ struct SharedState {
+ QQmlContextData *rootContext;
+ QQmlContextData *creationContext;
+ QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
+ QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
+ QQmlComponentAttached *componentAttached;
+ };
+
QQmlEngine *engine;
- const QV4::CompiledData::CompilationUnit *jsUnit;
+ QQmlCompiledData *compiledData;
+ const QV4::CompiledData::QmlUnit *qmlUnit;
QQmlContextData *parentContext;
QQmlContextData *context;
- const QHash<int, QQmlCompiledData::TypeReference> resolvedTypes;
- const QList<QQmlPropertyCache *> propertyCaches;
- const QList<QByteArray> vmeMetaObjectData;
+ const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
+ const QVector<QQmlPropertyCache *> &propertyCaches;
+ const QVector<QByteArray> &vmeMetaObjectData;
QHash<int, int> objectIndexToId;
- QLinkedList<QVector<QQmlAbstractBinding*> > allCreatedBindings;
- QQmlCompiledData *compiledData;
+ QFlagPointer<SharedState> sharedState;
QObject *_qobject;
- QObject *_qobjectForBindings;
+ QObject *_scopeObject;
+ QObject *_bindingTarget;
+
QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache
const QV4::CompiledData::Object *_compiledObject;
QQmlData *_ddata;
QQmlRefPointer<QQmlPropertyCache> _propertyCache;
QQmlVMEMetaObject *_vmeMetaObject;
- QVector<QQmlAbstractBinding*> _createdBindings;
QQmlListProperty<void> _currentList;
QV4::ExecutionContext *_qmlContext;
};
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 5745f35498..4d2c3d0332 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -254,7 +254,7 @@ int QQmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
propertyWritten(propId);
activate(d->object, d->type->d->signalOffset + propId, 0);
}
- }
+ }
return -1;
} else {
if (d->parent)
diff --git a/src/qml/qml/qqmlparserstatus.cpp b/src/qml/qml/qqmlparserstatus.cpp
index 41b7d962ce..0da22fb668 100644
--- a/src/qml/qml/qqmlparserstatus.cpp
+++ b/src/qml/qml/qqmlparserstatus.cpp
@@ -109,7 +109,7 @@ QQmlParserStatus::~QQmlParserStatus()
/*!
\fn void QQmlParserStatus::componentComplete()
- Invoked after the root component that caused this instantiation has
+ Invoked after the root component that caused this instantiation has
completed construction. At this point all static values and binding values
have been assigned to the class.
*/
diff --git a/src/qml/qml/qqmlparserstatus.h b/src/qml/qml/qqmlparserstatus.h
index d3447e7752..4e611f82b1 100644
--- a/src/qml/qml/qqmlparserstatus.h
+++ b/src/qml/qml/qqmlparserstatus.h
@@ -62,6 +62,7 @@ private:
friend class QQmlComponent;
friend class QQmlComponentPrivate;
friend class QQmlEnginePrivate;
+ friend class QQmlObjectCreator;
QQmlParserStatus **d;
};
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index 15306cb131..90e7961e6b 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -85,8 +85,8 @@ namespace QQmlPrivate
class QQmlElement : public T
{
public:
- virtual ~QQmlElement() {
- QQmlPrivate::qdeclarativeelement_destructor(this);
+ virtual ~QQmlElement() {
+ QQmlPrivate::qdeclarativeelement_destructor(this);
}
};
@@ -130,7 +130,7 @@ namespace QQmlPrivate
};
template <typename T, bool hasMember>
- class has_attachedPropertiesMethod
+ class has_attachedPropertiesMethod
{
public:
typedef int yes_type;
@@ -141,7 +141,7 @@ namespace QQmlPrivate
static no_type check(...);
static bool const value = sizeof(check(&T::qmlAttachedProperties)) == sizeof(yes_type);
- };
+ };
template <typename T>
class has_attachedPropertiesMethod<T, false>
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 3975b88bb0..0bbcafda54 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1250,7 +1250,7 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
return rv;
}
-bool QQmlPropertyPrivate::write(QObject *object,
+bool QQmlPropertyPrivate::write(QObject *object,
const QQmlPropertyData &property,
const QVariant &value, QQmlContextData *context,
WriteFlags flags)
diff --git a/src/qml/qml/qqmlproperty.h b/src/qml/qml/qqmlproperty.h
index c3322c0048..992d579aed 100644
--- a/src/qml/qml/qqmlproperty.h
+++ b/src/qml/qml/qqmlproperty.h
@@ -64,7 +64,7 @@ public:
Normal
};
- enum Type {
+ enum Type {
Invalid,
Property,
SignalProperty
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index ce15061ba0..28e9dca515 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -101,11 +101,11 @@ public:
bool writeValueProperty(const QVariant &, WriteFlags);
static QQmlMetaObject rawMetaObjectForType(QQmlEnginePrivate *, int);
- static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
+ static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,
const QQmlPropertyData &,
- const QVariant &, QQmlContextData *,
+ const QVariant &, QQmlContextData *,
WriteFlags flags = 0);
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
QQmlContextData *, WriteFlags flags = 0);
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 6c40557886..a0af0e94ef 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -50,7 +50,7 @@
#include <private/qqmlaccessors_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <QtCore/qdebug.h>
@@ -1140,7 +1140,7 @@ QString QQmlPropertyCache::signalParameterStringForJS(QQmlEngine *engine, const
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
bool unnamedParameter = false;
- const QV4::IdentifierHash<bool> &illegalNames = ep->v8engine()->illegalNames();
+ const QSet<QString> &illegalNames = ep->v8engine()->illegalNames();
QString error;
QString parameters;
@@ -1195,7 +1195,7 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
int argc = m.parameterCount();
if (!rv->arguments) {
- A *args = c->createArgumentsObject(argc);
+ A *args = c->createArgumentsObject(argc, m.parameterNames());
rv->arguments = args;
}
A *args = static_cast<A *>(rv->arguments);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index bc0cef9f4c..fe7f204e87 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -62,7 +62,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
QT_BEGIN_NAMESPACE
@@ -351,7 +351,7 @@ private:
QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
QQmlPropertyCacheMethodArguments *createArgumentsObject(int count,
- const QList<QByteArray> &names = QList<QByteArray>());
+ const QList<QByteArray> &names);
QQmlPropertyData *signal(int, QQmlPropertyCache **) const;
typedef QVector<QQmlPropertyData> IndexCache;
diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp
index 8a6af7cb05..282cbb7a21 100644
--- a/src/qml/qml/qqmlproxymetaobject.cpp
+++ b/src/qml/qml/qqmlproxymetaobject.cpp
@@ -78,7 +78,7 @@ int QQmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
if (id >= data.propertyOffset) {
if (!proxies) {
proxies = new QObject*[metaObjects->count()];
- ::memset(proxies, 0,
+ ::memset(proxies, 0,
sizeof(QObject *) * metaObjects->count());
}
@@ -93,7 +93,7 @@ int QQmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
// ### - Can this be done more optimally?
for (int jj = 0; jj < methods; ++jj) {
- QMetaMethod method =
+ QMetaMethod method =
metaObject->method(jj + methodOffset);
if (method.methodType() == QMetaMethod::Signal)
QQmlPropertyPrivate::connect(proxy, methodOffset + jj, object, localOffset + jj);
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index 6cb23ec07c..0618c90fa5 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
using namespace QQmlJS;
using namespace QQmlScript;
-//
+//
// Parser IR classes
//
QQmlScript::Object::Object()
@@ -68,8 +68,8 @@ QQmlScript::Object::Object()
{
}
-QQmlScript::Object::~Object()
-{
+QQmlScript::Object::~Object()
+{
if (synthCache) synthCache->release();
}
@@ -215,7 +215,7 @@ int QQmlScript::Object::DynamicSlot::parameterNamesLength() const
}
QQmlScript::Property::Property()
-: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false),
+: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false),
isValueTypeSubProperty(false), isAlias(false), isReadOnlyDeclaration(false),
scriptStringScope(-1), nextMainProperty(0), nextProperty(0)
{
@@ -354,7 +354,7 @@ QString escapedString(const QString &string)
QString QQmlScript::Variant::asScript() const
{
- switch(type()) {
+ switch (type()) {
default:
case Invalid:
return QString();
@@ -363,7 +363,7 @@ QString QQmlScript::Variant::asScript() const
case Number:
if (asWritten.isEmpty())
return QString::number(d);
- else
+ else
return asWritten.toString();
case String:
return escapedString(asString());
@@ -727,7 +727,7 @@ ProcessAST::defineObjectBinding(AST::Node *node,
} else {
// Class
- QQmlScript::Object *obj = _parser->_pool.New<QQmlScript::Object>();
+ QQmlScript::Object *obj = _parser->_pool.New<QQmlScript::Object>();
obj->type = _parser->findOrCreateTypeId(objectType, obj);
obj->typeReference = _parser->_refTypes.at(obj->type);
@@ -1034,11 +1034,11 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
bool typeFound = false;
Object::DynamicProperty::Type type;
- if ((unsigned)memberType.length() == strlen("alias") &&
+ if ((unsigned)memberType.length() == strlen("alias") &&
QHashedString::compare(memberType.constData(), "alias", int(strlen("alias")))) {
type = Object::DynamicProperty::Alias;
typeFound = true;
- }
+ }
for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
const TypeNameToType *t = propTypeNameToTypes + ii;
@@ -1054,7 +1054,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
if (typeModifier.isEmpty()) {
type = Object::DynamicProperty::Custom;
- } else if((unsigned)typeModifier.length() == strlen("list") &&
+ } else if ((unsigned)typeModifier.length() == strlen("list") &&
QHashedString::compare(typeModifier.constData(), "list", int(strlen("list")))) {
type = Object::DynamicProperty::CustomList;
} else {
@@ -1411,7 +1411,7 @@ QList<QQmlError> QQmlScript::Parser::errors() const
return _errors;
}
-static void replaceWithSpace(QString &str, int idx, int n)
+static void replaceWithSpace(QString &str, int idx, int n)
{
QChar *data = str.data() + idx;
const QChar space(QLatin1Char(' '));
@@ -1490,42 +1490,42 @@ QQmlScript::Object::ScriptBlock::Pragmas QQmlScript::Parser::extractPragmas(QStr
#define CHECK_TOKEN(t) if (token != QQmlJSGrammar:: t) return rv;
static const int uriTokens[] = {
- QQmlJSGrammar::T_IDENTIFIER,
- QQmlJSGrammar::T_PROPERTY,
- QQmlJSGrammar::T_SIGNAL,
- QQmlJSGrammar::T_READONLY,
- QQmlJSGrammar::T_ON,
- QQmlJSGrammar::T_BREAK,
- QQmlJSGrammar::T_CASE,
- QQmlJSGrammar::T_CATCH,
- QQmlJSGrammar::T_CONTINUE,
- QQmlJSGrammar::T_DEFAULT,
- QQmlJSGrammar::T_DELETE,
- QQmlJSGrammar::T_DO,
- QQmlJSGrammar::T_ELSE,
- QQmlJSGrammar::T_FALSE,
- QQmlJSGrammar::T_FINALLY,
- QQmlJSGrammar::T_FOR,
- QQmlJSGrammar::T_FUNCTION,
- QQmlJSGrammar::T_IF,
- QQmlJSGrammar::T_IN,
- QQmlJSGrammar::T_INSTANCEOF,
- QQmlJSGrammar::T_NEW,
- QQmlJSGrammar::T_NULL,
- QQmlJSGrammar::T_RETURN,
- QQmlJSGrammar::T_SWITCH,
- QQmlJSGrammar::T_THIS,
- QQmlJSGrammar::T_THROW,
- QQmlJSGrammar::T_TRUE,
- QQmlJSGrammar::T_TRY,
- QQmlJSGrammar::T_TYPEOF,
- QQmlJSGrammar::T_VAR,
- QQmlJSGrammar::T_VOID,
- QQmlJSGrammar::T_WHILE,
- QQmlJSGrammar::T_CONST,
- QQmlJSGrammar::T_DEBUGGER,
- QQmlJSGrammar::T_RESERVED_WORD,
- QQmlJSGrammar::T_WITH,
+ QQmlJSGrammar::T_IDENTIFIER,
+ QQmlJSGrammar::T_PROPERTY,
+ QQmlJSGrammar::T_SIGNAL,
+ QQmlJSGrammar::T_READONLY,
+ QQmlJSGrammar::T_ON,
+ QQmlJSGrammar::T_BREAK,
+ QQmlJSGrammar::T_CASE,
+ QQmlJSGrammar::T_CATCH,
+ QQmlJSGrammar::T_CONTINUE,
+ QQmlJSGrammar::T_DEFAULT,
+ QQmlJSGrammar::T_DELETE,
+ QQmlJSGrammar::T_DO,
+ QQmlJSGrammar::T_ELSE,
+ QQmlJSGrammar::T_FALSE,
+ QQmlJSGrammar::T_FINALLY,
+ QQmlJSGrammar::T_FOR,
+ QQmlJSGrammar::T_FUNCTION,
+ QQmlJSGrammar::T_IF,
+ QQmlJSGrammar::T_IN,
+ QQmlJSGrammar::T_INSTANCEOF,
+ QQmlJSGrammar::T_NEW,
+ QQmlJSGrammar::T_NULL,
+ QQmlJSGrammar::T_RETURN,
+ QQmlJSGrammar::T_SWITCH,
+ QQmlJSGrammar::T_THIS,
+ QQmlJSGrammar::T_THROW,
+ QQmlJSGrammar::T_TRUE,
+ QQmlJSGrammar::T_TRY,
+ QQmlJSGrammar::T_TYPEOF,
+ QQmlJSGrammar::T_VAR,
+ QQmlJSGrammar::T_VOID,
+ QQmlJSGrammar::T_WHILE,
+ QQmlJSGrammar::T_CONST,
+ QQmlJSGrammar::T_DEBUGGER,
+ QQmlJSGrammar::T_RESERVED_WORD,
+ QQmlJSGrammar::T_WITH,
QQmlJSGrammar::EOF_SYMBOL
};
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index fac31add5c..29da97fe83 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -72,14 +72,14 @@ namespace QQmlCompilerTypes { struct BindingReference; struct ComponentCompileSt
namespace QQmlScript {
-struct Location
+struct Location
{
Location() : line(0), column(0) {}
quint16 line;
quint16 column;
inline bool operator<(const Location &other) {
- return line < other.line ||
+ return line < other.line ||
(line == other.line && column < other.column);
}
};
@@ -253,12 +253,12 @@ public:
void addValue(Value *v);
void addOnValue(Value *v);
- // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
+ // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
// unknown.
int type;
// The metaobject index of this property, or -1 if unknown.
int index;
- // The core data in the case of a regular property.
+ // The core data in the case of a regular property.
// XXX This has to be a value now as the synthCache may change during
// compilation which invalidates pointers. We should fix this.
QQmlPropertyData core;
@@ -280,14 +280,14 @@ public:
const QHashedStringRef &name() const { return _name; }
void setName(const QString &n) { _name = QHashedStringRef(pool()->NewString(n)); }
void setName(const QHashedStringRef &n) { _name = n; }
- // True if this property was accessed as the default property.
+ // True if this property was accessed as the default property.
bool isDefault;
// True if the setting of this property will be deferred. Set by the
// QQmlCompiler
bool isDeferred;
// True if this property is a value-type pseudo-property
bool isValueTypeSubProperty;
- // True if this property is a property alias. Set by the
+ // True if this property is a property alias. Set by the
// QQmlCompiler
bool isAlias;
// True if this is a readonly property declaration
@@ -314,9 +314,9 @@ class Object : public QQmlPool::Class
{
public:
Object();
- virtual ~Object();
+ virtual ~Object();
- // Type of the object. The integer is an index into the
+ // Type of the object. The integer is an index into the
// QQmlCompiledData::types array, or -1 if the object is a property
// group.
int type;
@@ -331,7 +331,7 @@ public:
// Custom parsed data
QByteArray custom;
// Bit mask of the properties assigned bindings
- QByteArray bindingBitmask;
+ QByteArray bindingBitmask;
void setBindingBit(int);
QQmlPropertyCache *metatype;
@@ -374,7 +374,7 @@ public:
// Script blocks that were nested under this object
struct ScriptBlock {
- enum Pragma {
+ enum Pragma {
None = 0x00000000,
Shared = 0x00000001
};
@@ -385,14 +385,14 @@ public:
Pragmas pragmas;
};
- // The bytes to cast instances by to get to the QQmlParserStatus
+ // The bytes to cast instances by to get to the QQmlParserStatus
// interface. -1 indicates the type doesn't support this interface.
// Set by the QQmlCompiler.
int parserStatusCast;
LocationSpan location;
- struct DynamicProperty : public QQmlPool::POD
+ struct DynamicProperty : public QQmlPool::POD
{
DynamicProperty();
@@ -500,7 +500,7 @@ public:
class JavaScriptMetaData {
public:
- JavaScriptMetaData()
+ JavaScriptMetaData()
: pragmas(QQmlScript::Object::ScriptBlock::None) {}
QQmlScript::Object::ScriptBlock::Pragmas pragmas;
diff --git a/src/qml/qml/qqmlscriptstring.h b/src/qml/qml/qqmlscriptstring.h
index 5421ef95fc..9817fdc92c 100644
--- a/src/qml/qml/qqmlscriptstring.h
+++ b/src/qml/qml/qqmlscriptstring.h
@@ -53,7 +53,8 @@ QT_BEGIN_NAMESPACE
class QObject;
class QQmlContext;
class QQmlScriptStringPrivate;
-class Q_QML_EXPORT QQmlScriptString
+class QQmlObjectCreator;
+class Q_QML_EXPORT QQmlScriptString
{
public:
QQmlScriptString();
@@ -74,6 +75,7 @@ private:
QQmlScriptString(const QString &script, QQmlContext *context, QObject *scope);
QSharedDataPointer<QQmlScriptStringPrivate> d;
+ friend class QQmlObjectCreator;
friend class QQmlScriptStringPrivate;
friend class QQmlVME;
friend class QQmlExpression;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 6eda55e35b..1b947c421a 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -49,9 +49,10 @@
#include <private/qqmlthread_p.h>
#include <private/qqmlcompiler_p.h>
#include <private/qqmlcomponent_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qqmlcodegenerator_p.h>
+#include <private/qqmltypecompiler_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
@@ -93,7 +94,7 @@
#else
-#define ASSERT_MAINTHREAD()
+#define ASSERT_MAINTHREAD()
#define ASSERT_LOADTHREAD()
#define ASSERT_CALLBACK()
@@ -115,9 +116,9 @@ namespace {
}
// This is a lame object that we need to ensure that slots connected to
-// QNetworkReply get called in the correct thread (the loader thread).
+// QNetworkReply get called in the correct thread (the loader thread).
// As QQmlDataLoader lives in the main thread, and we can't use
-// Qt::DirectConnection connections from a QNetworkReply (because then
+// Qt::DirectConnection connections from a QNetworkReply (because then
// sender() wont work), we need to insert this object in the middle.
class QQmlDataLoaderNetworkReplyProxy : public QObject
{
@@ -167,8 +168,8 @@ private:
};
-QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l)
-: l(l)
+QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l)
+: l(l)
{
}
@@ -240,7 +241,7 @@ This enum describes the type of the data blob.
Create a new QQmlDataBlob for \a url and of the provided \a type.
*/
QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type)
-: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0),
+: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0),
m_inCallback(false), m_isDone(false)
{
}
@@ -395,7 +396,7 @@ QList<QQmlError> QQmlDataBlob::errors() const
/*!
Mark this blob as having \a errors.
-All outstanding dependencies will be cancelled. Requests to add new dependencies
+All outstanding dependencies will be cancelled. Requests to add new dependencies
will be ignored. Entry into the Error state is irreversable.
The setError() method may only be called from within a QQmlDataBlob callback.
@@ -433,8 +434,8 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors)
tryDone();
}
-/*!
-Wait for \a blob to become complete or to error. If \a blob is already
+/*!
+Wait for \a blob to become complete or to error. If \a blob is already
complete or in error, or this blob is already complete, this has no effect.
The setError() method may only be called from within a QQmlDataBlob callback.
@@ -447,7 +448,7 @@ void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
if (!blob ||
blob->status() == Error || blob->status() == Complete ||
- status() == Error || status() == Complete || m_isDone ||
+ status() == Error || status() == Complete || m_isDone ||
m_waitingFor.contains(blob))
return;
@@ -468,7 +469,7 @@ or addDependency().
*/
/*!
-Invoked once data has either been received or a network error occurred, and all
+Invoked once data has either been received or a network error occurred, and all
dependencies are complete.
You can set an error in this method, but you cannot add new dependencies. Implementors
@@ -536,7 +537,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
setError(error);
}
-/*!
+/*!
Called if \a blob, which was previously waited for, has an error.
The default implementation does nothing.
@@ -556,9 +557,9 @@ void QQmlDataBlob::dependencyComplete(QQmlDataBlob *blob)
Q_UNUSED(blob);
}
-/*!
-Called when all blobs waited for have completed. This occurs regardless of
-whether they are in error, or complete state.
+/*!
+Called when all blobs waited for have completed. This occurs regardless of
+whether they are in error, or complete state.
The default implementation does nothing.
*/
@@ -570,9 +571,9 @@ void QQmlDataBlob::allDependenciesDone()
Called when the download progress of this blob changes. \a progress goes
from 0 to 1.
-This callback is only invoked if an asynchronous load for this blob is
+This callback is only invoked if an asynchronous load for this blob is
made. An asynchronous load is one in which the Asynchronous mode is
-specified explicitly, or one that is implicitly delayed due to a network
+specified explicitly, or one that is implicitly delayed due to a network
operation.
The default implementation does nothing.
@@ -586,12 +587,12 @@ void QQmlDataBlob::downloadProgressChanged(qreal progress)
Invoked on the main thread sometime after done() was called on the load thread.
You cannot modify the blobs state at all in this callback and cannot depend on the
-order or timeliness of these callbacks. Implementors should use this callback to notify
+order or timeliness of these callbacks. Implementors should use this callback to notify
dependencies on the main thread that the blob is done and not a lot else.
-This callback is only invoked if an asynchronous load for this blob is
+This callback is only invoked if an asynchronous load for this blob is
made. An asynchronous load is one in which the Asynchronous mode is
-specified explicitly, or one that is implicitly delayed due to a network
+specified explicitly, or one that is implicitly delayed due to a network
operation.
The default implementation does nothing.
@@ -669,7 +670,7 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
blob->release();
- if (!isError() && m_waitingFor.isEmpty())
+ if (!isError() && m_waitingFor.isEmpty())
allDependenciesDone();
m_inCallback = false;
@@ -753,10 +754,10 @@ QQmlDataLoaderNetworkReplyProxy *QQmlDataLoaderThread::networkReplyProxy() const
return m_networkReplyProxy;
}
-void QQmlDataLoaderThread::load(QQmlDataBlob *b)
-{
+void QQmlDataLoaderThread::load(QQmlDataBlob *b)
+{
b->addref();
- callMethodInThread(&This::loadThread, b);
+ callMethodInThread(&This::loadThread, b);
}
void QQmlDataLoaderThread::loadAsync(QQmlDataBlob *b)
@@ -777,19 +778,19 @@ void QQmlDataLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteA
postMethodToThread(&This::loadWithStaticDataThread, b, d);
}
-void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
-{
- b->addref();
- postMethodToMain(&This::callCompletedMain, b);
+void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
+{
+ b->addref();
+ postMethodToMain(&This::callCompletedMain, b);
}
-void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
-{
- b->addref();
- postMethodToMain(&This::callDownloadProgressChangedMain, b, p);
+void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
+{
+ b->addref();
+ postMethodToMain(&This::callDownloadProgressChangedMain, b, p);
}
-void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
+void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
const char *uri)
{
callMethodInMain(&This::initializeEngineMain, iface, uri);
@@ -803,9 +804,9 @@ void QQmlDataLoaderThread::shutdownThread()
m_networkReplyProxy = 0;
}
-void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b)
-{
- m_loader->loadThread(b);
+void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b)
+{
+ m_loader->loadThread(b);
b->release();
}
@@ -815,27 +816,27 @@ void QQmlDataLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByte
b->release();
}
-void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b)
-{
+void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b)
+{
QML_MEMORY_SCOPE_URL(b->url());
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString()));
+ qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString()));
#endif
- b->completed();
- b->release();
+ b->completed();
+ b->release();
}
-void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p)
-{
+void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p)
+{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback",
- qPrintable(b->url().toString()), p);
+ qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback",
+ qPrintable(b->url().toString()), p);
#endif
- b->downloadProgressChanged(p);
- b->release();
+ b->downloadProgressChanged(p);
+ b->release();
}
-void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
+void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
const char *uri)
{
Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
@@ -855,7 +856,7 @@ The loader then fetches the data over the network or from the local file system
QQmlDataBlob is an abstract class, so should always be specialized.
Once data is received, the QQmlDataBlob::dataReceived() method is invoked on the blob. The
-derived class should use this callback to process the received data. Processing of the data can
+derived class should use this callback to process the received data. Processing of the data can
result in an error being set (QQmlDataBlob::setError()), or one or more dependencies being
created (QQmlDataBlob::addDependency()). Dependencies are other QQmlDataBlob's that
are required before processing can fully complete.
@@ -883,7 +884,7 @@ QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine)
/*! \internal */
QQmlDataLoader::~QQmlDataLoader()
{
- for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
+ for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
(*iter)->release();
shutdownThread();
@@ -908,7 +909,7 @@ The loader must be locked.
void QQmlDataLoader::load(QQmlDataBlob *blob, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
blob->startLoading(this);
@@ -940,7 +941,7 @@ The loader must be locked.
void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
@@ -1117,7 +1118,7 @@ QQmlEngine *QQmlDataLoader::engine() const
Call the initializeEngine() method on \a iface. Used by QQmlImportDatabase to ensure it
gets called in the correct thread.
*/
-void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface,
+void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface,
const char *uri)
{
Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread());
@@ -1157,7 +1158,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
if (!blob->isError() && !blob->isWaiting())
blob->allDependenciesDone();
- if (blob->status() != QQmlDataBlob::Error)
+ if (blob->status() != QQmlDataBlob::Error)
blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
blob->m_inCallback = false;
@@ -1524,12 +1525,12 @@ Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached
*/
QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
{
- Q_ASSERT(!url.isRelative() &&
+ Q_ASSERT(!url.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
!QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
LockHolder<QQmlTypeLoader> holder(this);
-
+
QQmlTypeData *typeData = m_typeCache.value(url);
if (!typeData) {
@@ -1545,7 +1546,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
}
/*!
-Returns a QQmlTypeData for the given \a data with the provided base \a url. The
+Returns a QQmlTypeData for the given \a data with the provided base \a url. The
QQmlTypeData will not be cached.
*/
QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url)
@@ -1563,7 +1564,7 @@ Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached.
*/
QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url)
{
- Q_ASSERT(!url.isRelative() &&
+ Q_ASSERT(!url.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
!QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
@@ -1587,7 +1588,7 @@ Returns a QQmlQmldirData for \a url. The QQmlQmldirData may be cached.
*/
QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
{
- Q_ASSERT(!url.isRelative() &&
+ Q_ASSERT(!url.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
!QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
@@ -1904,7 +1905,7 @@ void QQmlTypeLoader::clearCache()
{
for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter)
(*iter)->release();
- for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter)
+ for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter)
(*iter)->release();
for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter)
(*iter)->release();
@@ -1970,9 +1971,9 @@ QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager)
QQmlTypeData::~QQmlTypeData()
{
- for (int ii = 0; ii < m_scripts.count(); ++ii)
+ for (int ii = 0; ii < m_scripts.count(); ++ii)
m_scripts.at(ii).script->release();
- for (int ii = 0; ii < m_types.count(); ++ii)
+ for (int ii = 0; ii < m_types.count(); ++ii)
if (m_types.at(ii).typeData) m_types.at(ii).typeData->release();
if (m_compiledData)
m_compiledData->release();
@@ -2109,7 +2110,7 @@ void QQmlTypeData::done()
}
// Compile component
- if (!isError())
+ if (!isError())
compile();
scriptParser.clear();
@@ -2154,8 +2155,9 @@ void QQmlTypeData::dataReceived(const Data &data)
if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse"));
if (m_useNewCompiler) {
- parsedQML.reset(new QtQml::ParsedQML(QV8Engine::getV4(typeLoader()->engine())->debugger != 0));
- QQmlCodeGenerator compiler;
+ QQmlEngine *qmlEngine = typeLoader()->engine();
+ parsedQML.reset(new QtQml::ParsedQML(QV8Engine::getV4(qmlEngine)->debugger != 0));
+ QQmlCodeGenerator compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrl(), finalUrlString(), parsedQML.data())) {
setError(compiler.errors);
return;
@@ -2302,176 +2304,12 @@ void QQmlTypeData::compile()
m_compiledData->url = finalUrl();
m_compiledData->name = finalUrlString();
- QQmlCompilingProfiler prof(m_compiledData->name);
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, m_compiledData->name);
if (m_useNewCompiler) {
- m_compiledData->importCache = new QQmlTypeNameCache;
-
- foreach (const QString &ns, m_namespaces)
- m_compiledData->importCache->add(ns);
-
- // Add any Composite Singletons that were used to the import cache
- for (int i = 0; i < compositeSingletons().count(); ++i) {
- m_compiledData->importCache->add(compositeSingletons().at(i).type->qmlTypeName(),
- compositeSingletons().at(i).type->sourceUrl(), compositeSingletons().at(i).prefix);
- }
-
- m_imports.populateCache(m_compiledData->importCache);
- m_compiledData->importCache->addref();
-
- QQmlEngine *engine = typeLoader()->engine();
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
-
- for (QHash<int, TypeReference>::ConstIterator resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
- resolvedType != end; ++resolvedType) {
- QQmlCompiledData::TypeReference ref;
- if (resolvedType->typeData) {
- ref.component = resolvedType->typeData->compiledData();
- ref.component->addref();
- } else {
- ref.type = resolvedType->type;
- Q_ASSERT(ref.type);
- }
- ref.majorVersion = resolvedType->majorVersion;
- ref.minorVersion = resolvedType->minorVersion;
- m_compiledData->resolvedTypes.insert(resolvedType.key(), ref);
- }
-
- {
- SignalHandlerConverter converter(QQmlEnginePrivate::get(engine),
- parsedQML.data(),
- m_compiledData);
- if (!converter.convertSignalHandlerExpressionsToFunctionDeclarations()) {
- setError(converter.errors);
- m_compiledData->release();
- m_compiledData = 0;
- return;
- }
- }
-
- // Collect imported scripts
- m_compiledData->scripts.reserve(m_scripts.count());
- for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
- const ScriptReference &script = m_scripts.at(scriptIndex);
-
- QString qualifier = script.qualifier;
- QString enclosingNamespace;
-
- const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
- if (lastDotIndex != -1) {
- enclosingNamespace = qualifier.left(lastDotIndex);
- qualifier = qualifier.mid(lastDotIndex+1);
- }
-
- m_compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace);
- QQmlScriptData *scriptData = script.script->scriptData();
- scriptData->addref();
- m_compiledData->scripts << scriptData;
- }
-
- // Compile JS binding expressions and signal handlers
-
- JSCodeGen jsCodeGen(finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, m_compiledData->importCache);
- const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions);
-
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
-
- QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(enginePrivate, v4->executableAllocator, &parsedQML->jsModule, &parsedQML->jsGenerator));
- isel->setUseFastLookups(false);
- QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/false);
-
- // Generate QML compiled type data structures
-
- QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML.data(), runtimeFunctionIndices);
-
- if (jsUnit) {
- Q_ASSERT(!jsUnit->data);
- jsUnit->ownsData = false;
- jsUnit->data = &qmlUnit->header;
- }
-
- m_compiledData->compilationUnit = jsUnit;
- if (m_compiledData->compilationUnit)
- m_compiledData->compilationUnit->ref();
- m_compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData
-
- QList<QQmlError> errors;
-
- // Build property caches and VME meta object data
-
- m_compiledData->datas.reserve(qmlUnit->nObjects);
- m_compiledData->propertyCaches.reserve(qmlUnit->nObjects);
-
- QQmlPropertyCacheCreator propertyCacheBuilder(enginePrivate,
- qmlUnit, m_compiledData->url,
- &m_imports, &m_compiledData->resolvedTypes);
-
- for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
-
- QByteArray vmeMetaObjectData;
- QQmlPropertyCache *propertyCache = 0;
-
- // If the object has no type, then it's probably a nested object definition as part
- // of a group property.
- const bool objectHasType = !parsedQML->jsGenerator.strings.at(obj->inheritedTypeNameIndex).isEmpty();
- if (objectHasType) {
- if (!propertyCacheBuilder.create(obj, &propertyCache, &vmeMetaObjectData)) {
- errors << propertyCacheBuilder.errors;
- break;
- }
- }
-
- m_compiledData->datas << vmeMetaObjectData;
- if (propertyCache)
- propertyCache->addref();
- m_compiledData->propertyCaches << propertyCache;
-
- if (i == qmlUnit->indexOfRootObject) {
- Q_ASSERT(propertyCache);
- m_compiledData->rootPropertyCache = propertyCache;
- propertyCache->addref();
- }
- }
-
- // Resolve component boundaries and aliases
-
- if (errors.isEmpty()) {
- // Scan for components, determine their scopes and resolve aliases within the scope.
- QQmlComponentAndAliasResolver resolver(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes, m_compiledData->propertyCaches,
- &m_compiledData->datas, &m_compiledData->objectIndexToIdForRoot, &m_compiledData->objectIndexToIdPerComponent);
- if (!resolver.resolve())
- errors << resolver.errors;
- }
-
- if (errors.isEmpty()) {
- // Add to type registry of composites
- if (m_compiledData->isCompositeType())
- QQmlEnginePrivate::get(engine)->registerInternalCompositeType(m_compiledData);
- else {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
- QQmlCompiledData::TypeReference typeRef = m_compiledData->resolvedTypes.value(obj->inheritedTypeNameIndex);
- if (typeRef.component) {
- m_compiledData->metaTypeId = typeRef.component->metaTypeId;
- m_compiledData->listMetaTypeId = typeRef.component->listMetaTypeId;
- } else {
- m_compiledData->metaTypeId = typeRef.type->typeId();
- m_compiledData->listMetaTypeId = typeRef.type->qListTypeId();
- }
- }
- }
-
- // Sanity check property bindings
- if (errors.isEmpty()) {
- QQmlPropertyValidator validator(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes,
- m_compiledData->propertyCaches, m_compiledData->objectIndexToIdPerComponent);
- if (!validator.validate())
- errors << validator.errors;
- }
-
- if (!errors.isEmpty()) {
- setError(errors);
+ QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, parsedQML.data());
+ if (!compiler.compile()) {
+ setError(compiler.compilationErrors());
m_compiledData->release();
m_compiledData = 0;
}
@@ -2615,8 +2453,8 @@ void QQmlTypeData::resolveTypes()
error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(name).arg(error.description()));
}
- error.setLine(unresolvedRef->line);
- error.setColumn(unresolvedRef->column);
+ error.setLine(unresolvedRef->location.line);
+ error.setColumn(unresolvedRef->location.column);
errors.prepend(error);
setError(errors);
@@ -2630,8 +2468,10 @@ void QQmlTypeData::resolveTypes()
ref.majorVersion = majorVersion;
ref.minorVersion = minorVersion;
- ref.location.line = unresolvedRef->line;
- ref.location.column = unresolvedRef->column;
+ ref.location.line = unresolvedRef->location.line;
+ ref.location.column = unresolvedRef->location.column;
+
+ ref.needsCreation = unresolvedRef->needsCreation;
m_resolvedTypes.insert(unresolvedRef.key(), ref);
}
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index b93cf2942d..ab6f47e8de 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -69,7 +69,7 @@
#include <private/qqmlbundle_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4script_p.h>
QT_BEGIN_NAMESPACE
@@ -189,7 +189,7 @@ private:
// m_errors should *always* be written before the status is set to Error.
// We use the status change as a memory fence around m_errors so that locking
- // isn't required. Once the status is set to Error (or Complete), m_errors
+ // isn't required. Once the status is set to Error (or Complete), m_errors
// cannot be changed.
QList<QQmlError> m_errors;
@@ -244,7 +244,7 @@ private:
void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
void networkReplyFinished(QNetworkReply *);
void networkReplyProgress(QNetworkReply *, qint64, qint64);
-
+
typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies;
void setData(QQmlDataBlob *, const QByteArray &);
@@ -396,7 +396,7 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
public:
struct TypeReference
{
- TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0) {}
+ TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0), needsCreation(true) {}
QQmlScript::Location location;
QQmlType *type;
@@ -404,6 +404,7 @@ public:
int minorVersion;
QQmlTypeData *typeData;
QString prefix; // used by CompositeSingleton types
+ bool needsCreation;
};
struct ScriptReference
@@ -425,7 +426,12 @@ public:
const QQmlScript::Parser &parser() const;
+ // old compiler:
const QList<TypeReference> &resolvedTypes() const;
+ // new compiler:
+ const QHash<int, TypeReference> &resolvedTypeRefs() const { return m_resolvedTypes; }
+ // ---
+
const QList<ScriptReference> &resolvedScripts() const;
const QSet<QString> &namespaces() const;
const QList<TypeReference> &compositeSingletons() const;
@@ -486,10 +492,10 @@ private:
bool loadImplicitImport();
};
-// QQmlScriptData instances are created, uninitialized, by the loader in the
+// QQmlScriptData instances are created, uninitialized, by the loader in the
// load thread. The first time they are used by the VME, they are initialized which
// creates their v8 objects and they are referenced and added to the engine's cleanup
-// list. During QQmlCleanup::clear() all v8 resources are destroyed, and the
+// list. During QQmlCleanup::clear() all v8 resources are destroyed, and the
// reference that was created is released but final deletion only occurs once all the
// references as released. This is all intended to ensure that the v8 resources are
// only created and destroyed in the main thread :)
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index a880bbdd58..f388972559 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -99,7 +99,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name)
return result;
}
-QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
+QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
const void *importNamespace)
{
Q_ASSERT(importNamespace);
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 9c350a54a5..573779acab 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -54,13 +54,13 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_MANAGED_VTABLE(QmlTypeWrapper);
+DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
QmlTypeWrapper::QmlTypeWrapper(QV8Engine *engine)
: Object(QV8Engine::getV4(engine)),
v8(engine), mode(IncludeEnums), type(0), typeNamespace(0), importNamespace(0)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
QmlTypeWrapper::~QmlTypeWrapper()
@@ -248,7 +248,7 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
if (type && !type->isSingleton() && w->object) {
QObject *object = w->object;
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
- if (ao)
+ if (ao)
QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, ao, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value);
} else if (type && type->isSingleton()) {
QQmlEngine *e = v8engine->engine();
@@ -277,7 +277,7 @@ PropertyAttributes QmlTypeWrapper::query(const Managed *m, StringRef name)
Scope scope(m->engine());
ScopedString n(scope, name);
bool hasProperty = false;
- const_cast<Managed*>(m)->get(n, &hasProperty);
+ static_cast<Object *>(const_cast<Managed*>(m))->get(n, &hasProperty);
return hasProperty ? Attr_Data : Attr_Invalid;
}
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index ee462d6479..355a6751a9 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -56,7 +56,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qpointer.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -68,7 +68,7 @@ namespace QV4 {
struct Q_QML_EXPORT QmlTypeWrapper : Object
{
- Q_MANAGED
+ V4_OBJECT
private:
QmlTypeWrapper(QV8Engine *engine);
~QmlTypeWrapper();
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index bd44dfb0cf..953ea2154d 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -247,7 +247,7 @@ public:
qreal y() const;
void setX(qreal);
void setY(qreal);
-
+
qreal width() const;
qreal height() const;
void setWidth(qreal);
@@ -270,7 +270,7 @@ public:
int y() const;
void setX(int);
void setY(int);
-
+
int width() const;
int height() const;
void setWidth(int);
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 50d7cbcc5e..56da6819fe 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_MANAGED_VTABLE(QmlValueTypeWrapper);
+DEFINE_OBJECT_VTABLE(QmlValueTypeWrapper);
class QmlValueTypeReference : public QmlValueTypeWrapper
{
@@ -79,7 +79,7 @@ QmlValueTypeWrapper::QmlValueTypeWrapper(QV8Engine *engine, ObjectType objectTyp
: Object(QV8Engine::getV4(engine)), objectType(objectType)
{
v8 = engine;
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
QmlValueTypeWrapper::~QmlValueTypeWrapper()
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 9dd3e8dcbe..d66dbbba0c 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -56,7 +56,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -68,7 +68,7 @@ namespace QV4 {
struct Q_QML_EXPORT QmlValueTypeWrapper : Object
{
- Q_MANAGED
+ V4_OBJECT
protected:
enum ObjectType { Reference, Copy };
QmlValueTypeWrapper(QV8Engine *engine, ObjectType type);
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index dfc184b9f7..ce4997fef9 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -92,6 +92,17 @@ using namespace QQmlVMETypes;
goto exceptionExit; \
}
+#define VME_EXCEPTION_WITH_COLUMN(desc, line, column) \
+ { \
+ QQmlError error; \
+ error.setDescription(desc.trimmed()); \
+ error.setLine(line); \
+ error.setColumn(column); \
+ error.setUrl(COMP->url); \
+ *errors << error; \
+ goto exceptionExit; \
+ }
+
bool QQmlVME::s_enableComponentComplete = true;
void QQmlVME::init(QQmlContextData *ctxt, QQmlCompiledData *comp, int start,
@@ -129,6 +140,7 @@ void QQmlVME::init(QQmlContextData *ctxt, QQmlCompiledData *comp, int start,
rootContext = 0;
engine = ctxt->engine;
+ profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
}
bool QQmlVME::initDeferred(QObject *object)
@@ -168,14 +180,15 @@ bool QQmlVME::initDeferred(QObject *object)
rootContext = 0;
engine = ctxt->engine;
+ profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
return true;
}
namespace {
-struct ActiveVMERestorer
+struct ActiveVMERestorer
{
- ActiveVMERestorer(QQmlVME *me, QQmlEnginePrivate *ep)
+ ActiveVMERestorer(QQmlVME *me, QQmlEnginePrivate *ep)
: ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
~ActiveVMERestorer() { ep->activeVME = oldVME; }
@@ -184,7 +197,7 @@ struct ActiveVMERestorer
};
}
-QObject *QQmlVME::execute(QList<QQmlError> *errors, const Interrupt &interrupt)
+QObject *QQmlVME::execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt &interrupt)
{
Q_ASSERT(states.count() >= 1);
@@ -202,7 +215,7 @@ QObject *QQmlVME::execute(QList<QQmlError> *errors, const Interrupt &interrupt)
return rv;
}
-inline bool fastHasBinding(QObject *o, int index)
+inline bool fastHasBinding(QObject *o, int index)
{
if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(o)->declarativeData)) {
int coreIndex = index & 0x0000FFFF;
@@ -226,7 +239,7 @@ static QVariant variantFromString(const QString &string)
return QQmlStringConverters::variantFromString(string);
}
-static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::ExecutionEngine *v4, QV4::SafeValue *qmlBindingWrappers, QQmlContextData *context, QObject *scope, int objIdx)
+static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::ExecutionEngine *v4, QV4::Value *qmlBindingWrappers, QQmlContextData *context, QObject *scope, int objIdx)
{
QV4::Scope valueScope(v4);
QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, qmlBindingWrappers[objIdx]);
@@ -238,7 +251,7 @@ static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::Executi
return wrapper->context();
}
-// XXX we probably need some form of "work count" here to prevent us checking this
+// XXX we probably need some form of "work count" here to prevent us checking this
// for every instruction.
#define QML_BEGIN_INSTR_COMMON(I) { \
const QQmlInstructionMeta<(int)QQmlInstruction::I>::DataType &instr = QQmlInstructionMeta<(int)QQmlInstruction::I>::data(*genericInstr); \
@@ -330,7 +343,7 @@ static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::Executi
removeBindingOnProperty(o, index)
QObject *QQmlVME::run(QList<QQmlError> *errors,
- const Interrupt &interrupt
+ const QQmlInstantiationInterrupt &interrupt
#ifdef QML_THREADED_VME_INTERPRETER
, void * const **storeJumpTable
#endif
@@ -355,7 +368,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QV4::ExecutionEngine *v4 = ep->v4engine();
QV4::Scope valueScope(v4);
QV4::ScopedValue tmpValue(valueScope);
- QV4::SafeValue *qmlBindingWrappers = valueScope.alloc(objects.capacity());
+ QV4::Value *qmlBindingWrappers = valueScope.alloc(objects.capacity());
std::fill(qmlBindingWrappers, qmlBindingWrappers + objects.capacity(), QV4::Primitive::undefinedValue());
int status = -1; // needed for dbus
@@ -461,7 +474,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
CTXT->imports = COMP->importCache;
CTXT->imports->addref();
CTXT->setParent(parentCtxt);
- if (instr.contextCache != -1)
+ if (instr.contextCache != -1)
CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
if (states.count() == 1) {
rootContext = CTXT;
@@ -469,7 +482,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
rootContext->isRootObjectInCreation = true;
}
if (states.count() == 1 && !creationContext.isNull()) {
- // A component that is logically created within another component instance shares the
+ // A component that is logically created within another component instance shares the
// same instances of script imports. For example:
//
// import QtQuick 2.0
@@ -482,7 +495,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
// }
//
// Has the same "Test" instance. To implement this, we simply copy the v8 handles into
- // the inner context. We have to create a fresh persistent handle for each to prevent
+ // the inner context. We have to create a fresh persistent handle for each to prevent
// double dispose. It is possible we could do this more efficiently using some form of
// referencing instead.
CTXT->importedScripts = creationContext->importedScripts;
@@ -503,10 +516,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.component);
- if (profiler.start()) {
- profiler.updateTypeName(type.component->name);
- profiler.background();
- }
+ Q_QML_VME_PROFILE(profiler, startBackground(type.component->name));
states.push(State());
@@ -529,8 +539,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(CreateQMLObject)
QML_BEGIN_INSTR(CompleteQMLObject)
- if (profiler.foreground())
- profiler.updateLocation(CTXT->url, instr.line, instr.column);
+ Q_QML_VME_PROFILE(profiler, foreground(CTXT->url, instr.line, instr.column));
QObject *o = objects.top();
Q_ASSERT(o);
@@ -574,10 +583,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateCppObject)
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.type);
- if (profiler.start()) {
- profiler.updateLocation(CTXT->url, instr.line, instr.column);
- profiler.updateTypeName(type.type->qmlTypeName());
- }
+ Q_QML_VME_PROFILE(profiler, start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
QObject *o = 0;
void *memory = 0;
@@ -637,9 +643,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
if (!objects.isEmpty()) {
QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
#if 0 // ### refactor
- if (o->isWidgetType() && parent->isWidgetType())
+ if (o->isWidgetType() && parent->isWidgetType())
static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
- else
+ else
#endif
QQml_setParent_noEvent(o, parent);
ddata->parentFrozen = true;
@@ -650,11 +656,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateSimpleObject)
const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type);
- if (profiler.start()) {
- profiler.updateLocation(CTXT->url, instr.line, instr.column);
- profiler.updateTypeName(ref.type->qmlTypeName());
- }
- QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
+ Q_QML_VME_PROFILE(profiler, start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
+ QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
::memset(static_cast<void *>(o), 0, instr.typeSize + sizeof(QQmlData));
instr.create(o);
@@ -666,16 +669,16 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
ddata->lineNumber = instr.line;
ddata->columnNumber = instr.column;
- QObjectPrivate::get(o)->declarativeData = ddata;
+ QObjectPrivate::get(o)->declarativeData = ddata;
ddata->context = ddata->outerContext = CTXT;
- ddata->nextContextObject = CTXT->contextObjects;
- if (ddata->nextContextObject)
- ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
- ddata->prevContextObject = &CTXT->contextObjects;
- CTXT->contextObjects = ddata;
+ ddata->nextContextObject = CTXT->contextObjects;
+ if (ddata->nextContextObject)
+ ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
+ ddata->prevContextObject = &CTXT->contextObjects;
+ CTXT->contextObjects = ddata;
QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
- QQml_setParent_noEvent(o, parent);
+ QQml_setParent_noEvent(o, parent);
ddata->parentFrozen = true;
objects.push(o);
@@ -692,7 +695,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(SetDefault)
QML_BEGIN_INSTR(CreateComponent)
- QQmlComponent *qcomp =
+ QQmlComponent *qcomp =
new QQmlComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
objects.isEmpty() ? 0 : objects.top());
@@ -727,7 +730,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QQmlPropertyCache *propertyCache = PROPERTYCACHES.at(instr.propertyCache);
- const QQmlVMEMetaData *data =
+ const QQmlVMEMetaData *data =
(const QQmlVMEMetaData *)DATAS.at(instr.aliasData).constData();
QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, target, objects.count() - 1);
@@ -749,13 +752,13 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type);
QVariant v = (*converter)(primitive);
- QMetaProperty prop =
+ QMetaProperty prop =
target->metaObject()->property(instr.propertyIndex);
- if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
+ if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
void *a[] = { (void *)v.data(), 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.propertyIndex, a);
QML_END_INSTR(AssignCustomType)
@@ -828,12 +831,12 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
ss.d.data()->numberValue = instr.numberValue;
void *a[] = { &ss, 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.propertyIndex, a);
QML_END_INSTR(StoreScriptString)
QML_BEGIN_INSTR(BeginObject)
- profiler.push();
+ Q_QML_VME_PROFILE(profiler, push());
QObject *target = objects.top();
QQmlParserStatus *status = reinterpret_cast<QQmlParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
parserStatus.push(status);
@@ -847,9 +850,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(BeginObject)
QML_BEGIN_INSTR(StoreBinding)
- QObject *target =
+ QObject *target =
objects.at(objects.count() - 1 - instr.owner);
- QObject *context =
+ QObject *context =
objects.at(objects.count() - 1 - instr.context);
if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
@@ -901,7 +904,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QObject *obj = objects.pop();
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
QObject *target = obj->parent();
- QQmlProperty prop =
+ QQmlProperty prop =
QQmlPropertyPrivate::restore(target, instr.property, CTXT);
vi->setTarget(prop);
QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
@@ -929,9 +932,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
void *ptr = 0;
const char *iid = QQmlMetaType::interfaceIId(type);
- if (iid)
+ if (iid)
ptr = assign->qt_metacast(iid);
- if (!ptr)
+ if (!ptr)
VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
if (list.qListProperty.append)
@@ -954,17 +957,17 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
void *ptr = assign->qt_metacast(iid);
if (ptr) {
void *a[] = { &ptr, 0, &status, &flags };
- QMetaObject::metacall(target,
+ QMetaObject::metacall(target,
QMetaObject::WriteProperty,
coreIdx, a);
ok = true;
}
- }
+ }
- if (!ok)
+ if (!ok)
VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
QML_END_INSTR(StoreInterface)
-
+
QML_BEGIN_INSTR(FetchAttached)
QObject *target = objects.top();
@@ -984,7 +987,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
void *a[1];
a[0] = (void *)&(lists.top().qListProperty);
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
instr.property, a);
QML_END_INSTR(FetchQList)
@@ -992,15 +995,15 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QObject *target = objects.top();
QObject *obj = 0;
- // NOTE: This assumes a cast to QObject does not alter the
+ // NOTE: This assumes a cast to QObject does not alter the
// object pointer
void *a[1];
a[0] = &obj;
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
instr.property, a);
if (!obj)
- VME_EXCEPTION(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line);
+ VME_EXCEPTION_WITH_COLUMN(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line, instr.column);
objects.push(obj);
qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
@@ -1042,14 +1045,14 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
// Possibly need to clear bindings
QQmlData *targetData = QQmlData::get(target);
if (targetData) {
- QQmlAbstractBinding *binding =
+ QQmlAbstractBinding *binding =
QQmlPropertyPrivate::binding(target, instr.property, -1);
if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
QQmlPropertyPrivate::setBinding(target, instr.property, -1, 0);
binding->destroy();
} else if (binding) {
- QQmlValueTypeProxyBinding *proxy =
+ QQmlValueTypeProxyBinding *proxy =
static_cast<QQmlValueTypeProxyBinding *>(binding);
proxy->removeBindings(instr.bindingSkipList);
}
@@ -1064,7 +1067,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(FetchValueType)
QML_BEGIN_INSTR(PopValueType)
- QQmlValueType *valueHandler =
+ QQmlValueType *valueHandler =
static_cast<QQmlValueType *>(objects.pop());
QObject *target = objects.top();
valueHandler->write(target, instr.property, QQmlPropertyPrivate::BypassInterceptor);
@@ -1097,7 +1100,7 @@ normalExit:
objects.deallocate();
lists.deallocate();
states.clear();
- profiler.stop();
+ Q_QML_VME_PROFILE(profiler, stop());
return rv;
}
@@ -1109,9 +1112,9 @@ void QQmlVME::reset()
QRecursionWatcher<QQmlVME, &QQmlVME::recursion> watcher(this);
if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
- delete objects.at(0);
-
- if (!rootContext.isNull())
+ delete objects.at(0);
+
+ if (!rootContext.isNull())
rootContext->activeVMEData = 0;
// Remove the QQmlParserStatus and QQmlAbstractBinding back pointers
@@ -1122,7 +1125,7 @@ void QQmlVME::reset()
QQmlComponentAttached *a = componentAttached;
a->rem();
}
-
+
engine = 0;
objects.deallocate();
lists.deallocate();
@@ -1135,7 +1138,13 @@ void QQmlVME::reset()
states.clear();
rootContext = 0;
creationContext = 0;
- profiler.clear();
+
+ // If profiling is switched off during a VME run and then switched back on
+ // before or during the next run background ranges from the first run will
+ // be reported in the second run because we don't clear() here. We accept
+ // that as the collected data will be incomplete anyway and because not
+ // calling clear() here is benefitial for the non-profiling case.
+ Q_QML_VME_PROFILE(profiler, clear(true));
}
#ifdef QML_THREADED_VME_INTERPRETER
@@ -1144,14 +1153,14 @@ void *const *QQmlVME::instructionJumpTable()
static void * const *jumpTable = 0;
if (!jumpTable) {
QQmlVME dummy;
- QQmlVME::Interrupt i;
+ QQmlInstantiationInterrupt i;
dummy.run(0, i, &jumpTable);
}
return jumpTable;
}
#endif
-QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
+QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt)
{
Q_ASSERT(engine ||
(bindValues.isEmpty() &&
@@ -1195,7 +1204,7 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
if (componentCompleteEnabled()) { // the qml designer does the component complete later
QQmlTrace trace("VME Component Complete");
while (!parserStatus.isEmpty()) {
- profiler.pop();
+ Q_QML_VME_PROFILE(profiler, pop());
QQmlParserStatus *status = parserStatus.pop();
#ifdef QML_ENABLE_TRACE
QQmlData *data = parserStatusData.pop();
@@ -1215,7 +1224,7 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
return 0;
}
parserStatus.deallocate();
- profiler.clear();
+ Q_QML_VME_PROFILE(profiler, clear());
}
{
@@ -1303,7 +1312,7 @@ QQmlVMEGuard::~QQmlVMEGuard()
void QQmlVMEGuard::guard(QQmlVME *vme)
{
clear();
-
+
m_objectCount = vme->objects.count();
m_objects = new QPointer<QObject>[m_objectCount];
for (int ii = 0; ii < m_objectCount; ++ii)
@@ -1311,12 +1320,20 @@ void QQmlVMEGuard::guard(QQmlVME *vme)
m_contextCount = (vme->rootContext.isNull()?0:1) + vme->states.count();
m_contexts = new QQmlGuardedContextData[m_contextCount];
- for (int ii = 0; ii < vme->states.count(); ++ii)
+ for (int ii = 0; ii < vme->states.count(); ++ii)
m_contexts[ii] = vme->states.at(ii).context;
if (!vme->rootContext.isNull())
m_contexts[m_contextCount - 1] = vme->rootContext.contextData();
}
+void QQmlVMEGuard::guard(QQmlObjectCreator *creator)
+{
+ clear();
+ m_contextCount = 1;
+ m_contexts = new QQmlGuardedContextData[m_contextCount];
+ m_contexts[0] = creator->parentContextData();
+}
+
void QQmlVMEGuard::clear()
{
delete [] m_objects;
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index d5afd4c67a..cde8c0c6c4 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -68,7 +68,7 @@
#include <private/qfinitestack_p.h>
#include <private/qqmltrace_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
QT_BEGIN_NAMESPACE
@@ -102,28 +102,28 @@ Q_DECLARE_TYPEINFO(QQmlVMETypes::List, Q_PRIMITIVE_TYPE | Q_MOVABLE_TYPE);
template<>
class QTypeInfo<QQmlVMETypes::State> : public QTypeInfoMerger<QQmlVMETypes::State, QBitField> {}; //Q_DECLARE_TYPEINFO
+class QQmlInstantiationInterrupt {
+public:
+ inline QQmlInstantiationInterrupt();
+ inline QQmlInstantiationInterrupt(volatile bool *runWhile, int nsecs=0);
+ inline QQmlInstantiationInterrupt(int nsecs);
+
+ inline void reset();
+ inline bool shouldInterrupt() const;
+private:
+ enum Mode { None, Time, Flag };
+ Mode mode;
+ struct {
+ QElapsedTimer timer;
+ int nsecs;
+ };
+ volatile bool *runWhile;
+};
+
class Q_QML_PRIVATE_EXPORT QQmlVME
{
Q_DECLARE_TR_FUNCTIONS(QQmlVME)
public:
- class Interrupt {
- public:
- inline Interrupt();
- inline Interrupt(volatile bool *runWhile, int nsecs=0);
- inline Interrupt(int nsecs);
-
- inline void reset();
- inline bool shouldInterrupt() const;
- private:
- enum Mode { None, Time, Flag };
- Mode mode;
- struct {
- QElapsedTimer timer;
- int nsecs;
- };
- volatile bool *runWhile;
- };
-
QQmlVME() : data(0), componentAttached(0) {}
QQmlVME(void *data) : data(data), componentAttached(0) {}
@@ -136,8 +136,8 @@ public:
bool initDeferred(QObject *);
void reset();
- QObject *execute(QList<QQmlError> *errors, const Interrupt & = Interrupt());
- QQmlContextData *complete(const Interrupt & = Interrupt());
+ QObject *execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt & = QQmlInstantiationInterrupt());
+ QQmlContextData *complete(const QQmlInstantiationInterrupt & = QQmlInstantiationInterrupt());
static void enableComponentComplete();
static void disableComponentComplete();
@@ -146,7 +146,7 @@ public:
private:
friend class QQmlVMEGuard;
- QObject *run(QList<QQmlError> *errors, const Interrupt &
+ QObject *run(QList<QQmlError> *errors, const QQmlInstantiationInterrupt &
#ifdef QML_THREADED_VME_INTERPRETER
, void *const**storeJumpTable = 0
#endif
@@ -187,7 +187,7 @@ private:
};
// Used to check that a QQmlVME that is interrupted mid-execution
-// is still valid. Checks all the objects and contexts have not been
+// is still valid. Checks all the objects and contexts have not been
// deleted.
class QQmlVMEGuard
{
@@ -196,6 +196,7 @@ public:
~QQmlVMEGuard();
void guard(QQmlVME *);
+ void guard(QQmlObjectCreator *);
void clear();
bool isOK() const;
@@ -207,28 +208,28 @@ private:
QQmlGuardedContextData *m_contexts;
};
-QQmlVME::Interrupt::Interrupt()
+QQmlInstantiationInterrupt::QQmlInstantiationInterrupt()
: mode(None), nsecs(0), runWhile(0)
{
}
-QQmlVME::Interrupt::Interrupt(volatile bool *runWhile, int nsecs)
+QQmlInstantiationInterrupt::QQmlInstantiationInterrupt(volatile bool *runWhile, int nsecs)
: mode(Flag), nsecs(nsecs), runWhile(runWhile)
{
}
-QQmlVME::Interrupt::Interrupt(int nsecs)
+QQmlInstantiationInterrupt::QQmlInstantiationInterrupt(int nsecs)
: mode(Time), nsecs(nsecs), runWhile(0)
{
}
-void QQmlVME::Interrupt::reset()
+void QQmlInstantiationInterrupt::reset()
{
if (mode == Time || nsecs)
timer.start();
}
-bool QQmlVME::Interrupt::shouldInterrupt() const
+bool QQmlInstantiationInterrupt::shouldInterrupt() const
{
if (mode == None) {
return false;
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index ebe72b2ff6..f9cb9565b3 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -224,7 +224,7 @@ const void *QQmlVMEVariant::dataPtr() const
return &data;
}
-void *QQmlVMEVariant::dataPtr()
+void *QQmlVMEVariant::dataPtr()
{
return &data;
}
@@ -234,7 +234,7 @@ size_t QQmlVMEVariant::dataSize() const
return sizeof(data);
}
-QObject *QQmlVMEVariant::asQObject()
+QObject *QQmlVMEVariant::asQObject()
{
if (type != QMetaType::QObjectStar)
setValue((QObject *)0, 0, -1);
@@ -242,7 +242,7 @@ QObject *QQmlVMEVariant::asQObject()
return *(QQmlGuard<QObject> *)(dataPtr());
}
-const QVariant &QQmlVMEVariant::asQVariant()
+const QVariant &QQmlVMEVariant::asQVariant()
{
if (type != QMetaType::QVariant)
setValue(QVariant());
@@ -250,7 +250,7 @@ const QVariant &QQmlVMEVariant::asQVariant()
return *(QVariant *)(dataPtr());
}
-int QQmlVMEVariant::asInt()
+int QQmlVMEVariant::asInt()
{
if (type != QMetaType::Int)
setValue(int(0));
@@ -258,7 +258,7 @@ int QQmlVMEVariant::asInt()
return *(int *)(dataPtr());
}
-bool QQmlVMEVariant::asBool()
+bool QQmlVMEVariant::asBool()
{
if (type != QMetaType::Bool)
setValue(bool(false));
@@ -266,7 +266,7 @@ bool QQmlVMEVariant::asBool()
return *(bool *)(dataPtr());
}
-double QQmlVMEVariant::asDouble()
+double QQmlVMEVariant::asDouble()
{
if (type != QMetaType::Double)
setValue(double(0));
@@ -274,7 +274,7 @@ double QQmlVMEVariant::asDouble()
return *(double *)(dataPtr());
}
-const QString &QQmlVMEVariant::asQString()
+const QString &QQmlVMEVariant::asQString()
{
if (type != QMetaType::QString)
setValue(QString());
@@ -282,7 +282,7 @@ const QString &QQmlVMEVariant::asQString()
return *(QString *)(dataPtr());
}
-const QUrl &QQmlVMEVariant::asQUrl()
+const QUrl &QQmlVMEVariant::asQUrl()
{
if (type != QMetaType::QUrl)
setValue(QUrl());
@@ -290,7 +290,7 @@ const QUrl &QQmlVMEVariant::asQUrl()
return *(QUrl *)(dataPtr());
}
-const QTime &QQmlVMEVariant::asQTime()
+const QTime &QQmlVMEVariant::asQTime()
{
if (type != QMetaType::QTime)
setValue(QTime());
@@ -298,7 +298,7 @@ const QTime &QQmlVMEVariant::asQTime()
return *(QTime *)(dataPtr());
}
-const QDate &QQmlVMEVariant::asQDate()
+const QDate &QQmlVMEVariant::asQDate()
{
if (type != QMetaType::QDate)
setValue(QDate());
@@ -306,7 +306,7 @@ const QDate &QQmlVMEVariant::asQDate()
return *(QDate *)(dataPtr());
}
-const QDateTime &QQmlVMEVariant::asQDateTime()
+const QDateTime &QQmlVMEVariant::asQDateTime()
{
if (type != QMetaType::QDateTime)
setValue(QDateTime());
@@ -779,9 +779,9 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
int listIndex = data[id].asInt();
const List *list = &listProperties.at(listIndex);
- *reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) =
+ *reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) =
QQmlListProperty<QObject>(object, (void *)list,
- list_append, list_count, list_at,
+ list_append, list_count, list_at,
list_clear);
}
@@ -858,7 +858,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QQmlVMEMetaData::AliasData *d = metaData->aliasData() + id;
- if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty)
+ if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty)
*reinterpret_cast<void **>(a[0]) = 0;
if (!ctxt) return -1;
@@ -867,7 +867,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
- if (!target)
+ if (!target)
return -1;
connectAlias(id);
@@ -875,8 +875,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (d->isObjectAlias()) {
*reinterpret_cast<QObject **>(a[0]) = target;
return -1;
- }
-
+ }
+
// Remove binding (if any) on write
if(c == QMetaObject::WriteProperty) {
int flags = *reinterpret_cast<int*>(a[3]);
@@ -888,7 +888,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
}
}
}
-
+
if (d->isValueTypeAlias()) {
// Value type property
QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->valueType());
@@ -896,7 +896,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
valueType->read(target, d->propertyIndex());
int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a);
-
+
if (c == QMetaObject::WriteProperty)
valueType->write(target, d->propertyIndex(), 0x00);
@@ -987,7 +987,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
return QV4::Primitive::undefinedValue().asReturnedValue();
}
- if (!v8methods)
+ if (!v8methods)
v8methods = new QV4::PersistentValue[metaData->methodCount];
return v8methods[index].value();
@@ -1086,7 +1086,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
QV4::ScopedValue newv(scope, QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value));
- if (QV4::Referenced<QV4::VariantObject> v = newv->asRef<QV4::VariantObject>())
+ QV4::VariantObjectRef v = newv;
+ if (!!v)
v->addVmePropertyReference();
// Write the value and emit change signal as appropriate.
@@ -1186,7 +1187,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, QV4::ValueRef function)
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
- if (!v8methods)
+ if (!v8methods)
v8methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index a9a0308ded..778559d0c4 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -71,7 +71,7 @@
#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
QT_BEGIN_NAMESPACE
@@ -113,7 +113,7 @@ struct QQmlVMEMetaData
return (propertyIdx & 0xFFFF0000) ? propType : 0;
}
};
-
+
struct PropertyData {
int propertyType;
};
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index ad231d0769..e2cdac16c0 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -122,11 +122,11 @@ QQmlXMLHttpRequestData::~QQmlXMLHttpRequestData()
namespace {
class DocumentImpl;
-class NodeImpl
+class NodeImpl
{
public:
NodeImpl() : type(Element), document(0), parent(0) {}
- virtual ~NodeImpl() {
+ virtual ~NodeImpl() {
for (int ii = 0; ii < children.count(); ++ii)
delete children.at(ii);
for (int ii = 0; ii < attributes.count(); ++ii)
@@ -134,18 +134,18 @@ public:
}
// These numbers are copied from the Node IDL definition
- enum Type {
- Attr = 2,
- CDATA = 4,
- Comment = 8,
- Document = 9,
- DocumentFragment = 11,
+ enum Type {
+ Attr = 2,
+ CDATA = 4,
+ Comment = 8,
+ Document = 9,
+ DocumentFragment = 11,
DocumentType = 10,
- Element = 1,
- Entity = 6,
+ Element = 1,
+ Entity = 6,
EntityReference = 5,
- Notation = 12,
- ProcessingInstruction = 7,
+ Notation = 12,
+ ProcessingInstruction = 7,
Text = 3
};
Type type;
@@ -185,14 +185,14 @@ public:
class NamedNodeMap : public Object
{
- Q_MANAGED
+ V4_OBJECT
public:
NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
: Object(engine)
, list(list)
, d(data)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
if (d)
d->addref();
@@ -216,17 +216,17 @@ public:
NodeImpl *d;
};
-DEFINE_MANAGED_VTABLE(NamedNodeMap);
+DEFINE_OBJECT_VTABLE(NamedNodeMap);
class NodeList : public Object
{
- Q_MANAGED
+ V4_OBJECT
public:
NodeList(ExecutionEngine *engine, NodeImpl *data)
: Object(engine)
, d(data)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
if (d)
d->addref();
@@ -249,16 +249,16 @@ public:
NodeImpl *d;
};
-DEFINE_MANAGED_VTABLE(NodeList);
+DEFINE_OBJECT_VTABLE(NodeList);
class NodePrototype : public Object
{
- Q_MANAGED
+ V4_OBJECT
public:
NodePrototype(ExecutionEngine *engine)
: Object(engine)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
Scope scope(engine);
ScopedObject protectThis(scope, this);
@@ -302,17 +302,17 @@ public:
};
-DEFINE_MANAGED_VTABLE(NodePrototype);
+DEFINE_OBJECT_VTABLE(NodePrototype);
class Node : public Object
{
- Q_MANAGED
+ V4_OBJECT
Node(ExecutionEngine *engine, NodeImpl *data)
: Object(engine)
, d(data)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
if (d)
d->addref();
@@ -339,7 +339,7 @@ private:
Node &operator=(const Node &);
};
-DEFINE_MANAGED_VTABLE(Node);
+DEFINE_OBJECT_VTABLE(Node);
class Element : public Node
{
@@ -407,7 +407,7 @@ public:
}
-void NodeImpl::addref()
+void NodeImpl::addref()
{
document->addref();
}
@@ -826,7 +826,7 @@ ReturnedValue Document::load(QV8Engine *engine, const QByteArray &data)
break;
case QXmlStreamReader::EndDocument:
break;
- case QXmlStreamReader::StartElement:
+ case QXmlStreamReader::StartElement:
{
Q_ASSERT(document);
NodeImpl *node = new NodeImpl;
@@ -851,7 +851,7 @@ ReturnedValue Document::load(QV8Engine *engine, const QByteArray &data)
attr->parent = node;
node->attributes.append(attr);
}
- }
+ }
break;
case QXmlStreamReader::EndElement:
nodeStack.pop();
@@ -1045,7 +1045,7 @@ class QQmlXMLHttpRequest : public QObject
{
Q_OBJECT
public:
- enum State { Unsent = 0,
+ enum State { Unsent = 0,
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
@@ -1250,7 +1250,7 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
request.setHeader(QNetworkRequest::ContentTypeHeader, str);
} else {
- request.setHeader(QNetworkRequest::ContentTypeHeader,
+ request.setHeader(QNetworkRequest::ContentTypeHeader,
QLatin1String("text/plain;charset=UTF-8"));
}
}
@@ -1258,7 +1258,7 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
if (xhrDump()) {
qWarning().nospace() << "XMLHttpRequest: " << qPrintable(m_method) << ' ' << qPrintable(url.toString());
if (!m_data.isEmpty()) {
- qWarning().nospace() << " "
+ qWarning().nospace() << " "
<< qPrintable(QString::fromUtf8(m_data));
}
}
@@ -1303,7 +1303,7 @@ ReturnedValue QQmlXMLHttpRequest::abort(const ValueRef me)
m_errorFlag = true;
m_request = QNetworkRequest();
- if (!(m_state == Unsent ||
+ if (!(m_state == Unsent ||
(m_state == Opened && !m_sendFlag) ||
m_state == Done)) {
@@ -1329,7 +1329,7 @@ void QQmlXMLHttpRequest::setMe(const ValueRef me)
void QQmlXMLHttpRequest::readyRead()
{
- m_status =
+ m_status =
m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
m_statusText =
QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
@@ -1394,7 +1394,7 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
} else {
m_errorFlag = true;
m_responseEntityBody = QByteArray();
- }
+ }
m_state = Done;
@@ -1438,7 +1438,7 @@ void QQmlXMLHttpRequest::finished()
if (xhrDump()) {
qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
if (!m_responseEntityBody.isEmpty()) {
- qWarning().nospace() << " "
+ qWarning().nospace() << " "
<< qPrintable(QString::fromUtf8(m_responseEntityBody));
}
}
@@ -1479,7 +1479,7 @@ void QQmlXMLHttpRequest::readEncoding()
}
}
- if (m_mime.isEmpty() || m_mime == "text/xml" || m_mime == "application/xml" || m_mime.endsWith("+xml"))
+ if (m_mime.isEmpty() || m_mime == "text/xml" || m_mime == "application/xml" || m_mime.endsWith("+xml"))
m_gotXml = true;
}
@@ -1494,7 +1494,7 @@ QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
{
QTextCodec *codec = 0;
- if (!m_charset.isEmpty())
+ if (!m_charset.isEmpty())
codec = QTextCodec::codecForName(m_charset);
if (!codec && m_gotXml) {
@@ -1503,7 +1503,7 @@ QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8());
}
- if (!codec && m_mime == "text/html")
+ if (!codec && m_mime == "text/html")
codec = QTextCodec::codecForHtml(m_responseEntityBody, 0);
if (!codec)
@@ -1600,12 +1600,12 @@ void QQmlXMLHttpRequest::destroyNetwork()
struct QQmlXMLHttpRequestWrapper : public Object
{
- Q_MANAGED
+ V4_OBJECT
QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
: Object(engine)
, request(request)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
~QQmlXMLHttpRequestWrapper() {
delete request;
@@ -1618,15 +1618,15 @@ struct QQmlXMLHttpRequestWrapper : public Object
QQmlXMLHttpRequest *request;
};
-DEFINE_MANAGED_VTABLE(QQmlXMLHttpRequestWrapper);
+DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper);
struct QQmlXMLHttpRequestCtor : public FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
: FunctionObject(engine->rootContext, QStringLiteral("XMLHttpRequest"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
Scope scope(engine);
ScopedValue protectThis(scope, this);
@@ -1688,7 +1688,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
Object *proto;
};
-DEFINE_MANAGED_VTABLE(QQmlXMLHttpRequestCtor);
+DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestCtor);
void QQmlXMLHttpRequestCtor::setupProto()
{
@@ -1737,7 +1737,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
// Argument 0 - Method
QString method = ctx->callData->args[0].toQStringNoThrow().toUpper();
- if (method != QLatin1String("GET") &&
+ if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
method != QLatin1String("POST") &&
@@ -1747,7 +1747,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
// Argument 1 - URL
QUrl url = QUrl(ctx->callData->args[1].toQStringNoThrow());
- if (url.isRelative())
+ if (url.isRelative())
url = engine->callingContext()->resolvedUrl(url);
// Argument 2 - async (optional)
@@ -1811,7 +1811,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
nameUpper == QLatin1String("USER-AGENT") ||
nameUpper == QLatin1String("VIA") ||
nameUpper.startsWith(QLatin1String("PROXY-")) ||
- nameUpper.startsWith(QLatin1String("SEC-")))
+ nameUpper.startsWith(QLatin1String("SEC-")))
return Encode::undefined();
r->addHeader(name, value);
@@ -1958,7 +1958,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx)
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)
return engine->toString(QString());
- else
+ else
return engine->toString(r->responseBody());
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 67b7e789bd..fbc41201fb 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -48,7 +48,7 @@
#include <private/qqmllocale_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv8profilerservice_p.h>
+#include <private/qv4profilerservice_p.h>
#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlglobal_p.h>
@@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-DEFINE_MANAGED_VTABLE(QtObject);
+DEFINE_OBJECT_VTABLE(QtObject);
struct StaticQtMetaObject : public QObject
{
@@ -90,7 +90,7 @@ QV4::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
, m_platform(0)
, m_application(0)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
Scope scope(v4);
ScopedObject protectThis(scope, this);
@@ -1178,12 +1178,12 @@ namespace {
struct BindingFunction : public QV4::FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
BindingFunction(FunctionObject *originalFunction)
: QV4::FunctionObject(originalFunction->scope, originalFunction->name)
, originalFunction(originalFunction)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
bindingKeyFlag = true;
}
@@ -1203,7 +1203,7 @@ struct BindingFunction : public QV4::FunctionObject
QV4::FunctionObject *originalFunction;
};
-DEFINE_MANAGED_VTABLE(BindingFunction);
+DEFINE_OBJECT_VTABLE(BindingFunction);
}
@@ -1422,10 +1422,6 @@ QV4::ReturnedValue ConsoleObject::method_log(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
{
- //DeclarativeDebugTrace cannot handle nested profiling
- //although v8 can handle several profiling at once,
- //we do not allow that. Hence, we pass an empty(default) title
- QString title;
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::StackFrame frame = v4->currentStackFrame();
@@ -1434,12 +1430,9 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
if (!QQmlDebugService::isDebuggingEnabled()) {
logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
- } else if (QQmlProfilerService::startProfiling()) {
- QV8ProfilerService::instance()->startProfiling(title);
-
- logger.debug("Profiling started.");
} else {
- logger.warning("Profiling is already in progress. First, end current profiling session.");
+ QQmlProfilerService::instance()->startProfiling(v4->v8Engine->engine());
+ logger.debug("Profiling started.");
}
return QV4::Encode::undefined();
@@ -1447,11 +1440,6 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
{
- //DeclarativeDebugTrace cannot handle nested profiling
- //although v8 can handle several profiling at once,
- //we do not allow that. Hence, we pass an empty(default) title
- QString title;
-
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::StackFrame frame = v4->currentStackFrame();
@@ -1459,15 +1447,11 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (QQmlProfilerService::stopProfiling()) {
- QV8ProfilerService *profiler = QV8ProfilerService::instance();
- profiler->stopProfiling(title);
- QQmlProfilerService::sendProfilingData();
- profiler->sendProfilingData();
-
- logger.debug("Profiling ended.");
+ if (!QQmlDebugService::isDebuggingEnabled()) {
+ logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
} else {
- logger.warning("Profiling was not started.");
+ QQmlProfilerService::instance()->stopProfiling(v4->v8Engine->engine());
+ logger.debug("Profiling ended.");
}
return QV4::Encode::undefined();
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 90536c09dd..b0c63f1ad4 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -65,7 +65,7 @@ namespace QV4 {
struct QtObject : Object
{
- Q_MANAGED
+ V4_OBJECT
QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine);
static ReturnedValue method_isQtObject(CallContext *ctx);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 33f5a00a6c..f448cca439 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -68,7 +68,7 @@
#include <QtCore/qdatetime.h>
#include <private/qsimd_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4mm_p.h>
@@ -164,7 +164,7 @@ QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint)
QV4::ScopedArrayObject a(scope, value);
if (typeHint == qMetaTypeId<QList<QObject *> >()) {
QList<QObject *> list;
- uint32_t length = a->arrayLength();
+ uint32_t length = a->getLength();
QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
for (uint32_t ii = 0; ii < length; ++ii) {
qobjectWrapper = a->getIndexed(ii);
@@ -196,10 +196,10 @@ static QV4::ReturnedValue arrayFromStringList(QV8Engine *engine, const QStringLi
QV4::Scoped<QV4::ArrayObject> a(scope, e->newArrayObject());
int len = list.count();
a->arrayReserve(len);
- for (int ii = 0; ii < len; ++ii) {
- a->arrayData[ii].value = QV4::Encode(e->newString(list.at(ii)));
- a->arrayDataLen = ii + 1;
- }
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < len; ++ii)
+ a->arrayPut(ii, (v = QV4::Encode(e->newString(list.at(ii)))));
+
a->setArrayLengthUnchecked(len);
return a.asReturnedValue();
}
@@ -211,10 +211,10 @@ static QV4::ReturnedValue arrayFromVariantList(QV8Engine *engine, const QVariant
QV4::Scoped<QV4::ArrayObject> a(scope, e->newArrayObject());
int len = list.count();
a->arrayReserve(len);
- for (int ii = 0; ii < len; ++ii) {
- a->arrayData[ii].value = engine->fromVariant(list.at(ii));
- a->arrayDataLen = ii + 1;
- }
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < len; ++ii)
+ a->arrayPut(ii, (v = engine->fromVariant(list.at(ii))));
+
a->setArrayLengthUnchecked(len);
return a.asReturnedValue();
}
@@ -226,8 +226,13 @@ static QV4::ReturnedValue objectFromVariantMap(QV8Engine *engine, const QVariant
QV4::ScopedObject o(scope, e->newObject());
QV4::ScopedString s(scope);
QV4::ScopedValue v(scope);
- for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter)
- o->put((s = e->newString(iter.key())), (v = engine->fromVariant(iter.value())));
+ for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) {
+ s = e->newString(iter.key());
+ uint idx = s->asArrayIndex();
+ if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
+ o->initSparseArray();
+ o->put(s, (v = engine->fromVariant(iter.value())));
+ }
return o.asReturnedValue();
}
@@ -298,7 +303,8 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
return QV4::JsonObject::fromJsonObject(m_v4Engine, *reinterpret_cast<const QJsonObject *>(ptr));
case QMetaType::QJsonArray:
return QV4::JsonObject::fromJsonArray(m_v4Engine, *reinterpret_cast<const QJsonArray *>(ptr));
-
+ case QMetaType::QLocale:
+ return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
default:
break;
}
@@ -325,10 +331,9 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
const QList<QObject *> &list = *(QList<QObject *>*)ptr;
QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject());
a->arrayReserve(list.count());
- for (int ii = 0; ii < list.count(); ++ii) {
- a->arrayData[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii));
- a->arrayDataLen = ii + 1;
- }
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < list.count(); ++ii)
+ a->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii))));
a->setArrayLengthUnchecked(list.count());
return a.asReturnedValue();
} else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) {
@@ -361,7 +366,7 @@ QNetworkAccessManager *QV8Engine::networkAccessManager()
return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
}
-const QV4::IdentifierHash<bool> &QV8Engine::illegalNames() const
+const QSet<QString> &QV8Engine::illegalNames() const
{
return m_illegalNames;
}
@@ -392,6 +397,8 @@ QVariant QV8Engine::toBasicVariant(const QV4::ValueRef value)
return value->asDouble();
if (value->isString())
return value->stringValue()->toQString();
+ if (QQmlLocaleData *ld = value->as<QQmlLocaleData>())
+ return ld->locale;
if (QV4::DateObject *d = value->asDateObject())
return d->toQDateTime();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -407,7 +414,7 @@ QVariant QV8Engine::toBasicVariant(const QV4::ValueRef value)
QV4::ScopedValue v(scope);
QVariantList rv;
- int length = a->arrayLength();
+ int length = a->getLength();
for (int ii = 0; ii < length; ++ii) {
v = a->getIndexed(ii);
rv << toVariant(v, -1);
@@ -437,9 +444,8 @@ void QV8Engine::initializeGlobal()
qt_add_sqlexceptions(m_v4Engine);
{
- m_illegalNames = QV4::IdentifierHash<bool>(m_v4Engine);
for (uint i = 0; i < m_v4Engine->globalObject->internalClass->size; ++i)
- m_illegalNames.add(m_v4Engine->globalObject->internalClass->nameMap.at(i)->toQString(), true);
+ m_illegalNames.insert(m_v4Engine->globalObject->internalClass->nameMap.at(i)->toQString());
}
{
@@ -541,10 +547,9 @@ QV4::ReturnedValue QV8Engine::variantListToJS(const QVariantList &lst)
QV4::Scope scope(m_v4Engine);
QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject());
a->arrayReserve(lst.size());
- for (int i = 0; i < lst.size(); i++) {
- a->arrayData[i].value = variantToJS(lst.at(i));
- a->arrayDataLen = i + 1;
- }
+ QV4::ScopedValue v(scope);
+ for (int i = 0; i < lst.size(); i++)
+ a->arrayPut(i, (v = variantToJS(lst.at(i))));
a->setArrayLengthUnchecked(lst.size());
return a.asReturnedValue();
}
@@ -569,7 +574,7 @@ QVariantList QV8Engine::variantListFromJS(QV4::ArrayObjectRef a,
QV4::Scope scope(a->engine());
QV4::ScopedValue v(scope);
- quint32 length = a->arrayLength();
+ quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
result.append(variantFromJS(v, visitedObjects));
@@ -590,10 +595,11 @@ QV4::ReturnedValue QV8Engine::variantMapToJS(const QVariantMap &vmap)
QV4::Scoped<QV4::Object> o(scope, m_v4Engine->newObject());
QVariantMap::const_iterator it;
QV4::ScopedString s(scope);
+ QV4::ScopedValue v(scope);
for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) {
s = m_v4Engine->newIdentifier(it.key());
- QV4::Property *p = o->insertMember(s, QV4::Attr_Data);
- p->value = variantToJS(it.value());
+ v = variantToJS(it.value());
+ o->insertMember(s, v);
}
return o.asReturnedValue();
}
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index e37b0d4920..1295e671f0 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -68,7 +68,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qv4qobjectwrapper_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4object_p.h>
#include <private/qv4identifier_p.h>
@@ -117,7 +117,7 @@ namespace QV4 {
// ...
// Q_INVOKABLE void myMethod(QQmlV8Function*);
// };
-// The QQmlV8Function - and consequently the arguments and return value - only remains
+// The QQmlV8Function - and consequently the arguments and return value - only remains
// valid during the call. If the return value isn't set within myMethod(), the will return
// undefined.
class QV8Engine;
@@ -217,7 +217,7 @@ public:
virtual QNetworkAccessManager *networkAccessManager();
// Return the list of illegal id names (the names of the properties on the global object)
- const QV4::IdentifierHash<bool> &illegalNames() const;
+ const QSet<QString> &illegalNames() const;
void gc();
@@ -268,7 +268,7 @@ protected:
QVector<Deletable *> m_extensionData;
Deletable *m_listModelData;
- QV4::IdentifierHash<bool> m_illegalNames;
+ QSet<QString> m_illegalNames;
QElapsedTimer m_time;
QHash<QString, qint64> m_startedTimers;
diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri
index 2480848514..b4eb706574 100644
--- a/src/qml/qml/v8/v8.pri
+++ b/src/qml/qml/v8/v8.pri
@@ -1,6 +1,5 @@
HEADERS += \
$$PWD/qv8debug_p.h \
- $$PWD/qv8profiler_p.h \
$$PWD/qv8engine_p.h \
$$PWD/qv4domerrors_p.h \
$$PWD/qv4sqlerrors_p.h \
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 5e6a1a084a..b8920deb21 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -251,6 +251,44 @@ QQmlConnectionsParser::compile(const QList<QQmlCustomParserProperty> &props)
return rv;
}
+QByteArray QQmlConnectionsParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props)
+{
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ for (int ii = 0; ii < props.count(); ++ii) {
+ const QV4::CompiledData::Binding *binding = props.at(ii);
+ QString propName = qmlUnit->header.stringAt(binding->propertyNameIndex);
+ int propLine = binding->location.line;
+ int propColumn = binding->location.column;
+
+ if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
+ error(props.at(ii), QQmlConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
+ return QByteArray();
+ }
+
+
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
+ const QV4::CompiledData::Object *target = qmlUnit->objectAt(binding->value.objectIndex);
+ if (!qmlUnit->header.stringAt(target->inheritedTypeNameIndex).isEmpty())
+ error(binding, QQmlConnections::tr("Connections: nested objects not allowed"));
+ else
+ error(binding, QQmlConnections::tr("Connections: syntax error"));
+ return QByteArray();
+ } if (binding->type != QV4::CompiledData::Binding::Type_Script) {
+ error(binding, QQmlConnections::tr("Connections: script expected"));
+ return QByteArray();
+ } else {
+ ds << propName;
+ ds << binding->valueAsString(&qmlUnit->header);
+ ds << propLine;
+ ds << propColumn;
+ }
+ }
+
+ return rv;
+}
+
void QQmlConnectionsParser::setCustomData(QObject *object,
const QByteArray &data)
{
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index 9bc668e5f4..2579e4c239 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -85,6 +85,7 @@ class QQmlConnectionsParser : public QQmlCustomParser
{
public:
virtual QByteArray compile(const QList<QQmlCustomParserProperty> &);
+ virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
virtual void setCustomData(QObject *, const QByteArray &);
};
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 7276c0e5c6..60c6389d28 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -52,7 +52,7 @@
#include <private/qqmlincubator_p.h>
#include <private/qqmlcompiler_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -61,7 +61,7 @@ class QQmlDelegateModelItem;
struct DelegateModelGroupFunction: QV4::FunctionObject
{
- Q_MANAGED
+ V4_OBJECT
QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg);
uint flag;
@@ -71,7 +71,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
, code(code)
, flag(flag)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
@@ -93,7 +93,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
}
};
-DEFINE_MANAGED_VTABLE(DelegateModelGroupFunction);
+DEFINE_OBJECT_VTABLE(DelegateModelGroupFunction);
@@ -1629,37 +1629,46 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
proto->defineAccessorProperty(QStringLiteral("model"), QQmlDelegateModelItem::get_model, 0);
proto->defineAccessorProperty(QStringLiteral("groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
QV4::ScopedString s(scope);
+ QV4::ScopedProperty p(scope);
+
s = v4->newString(QStringLiteral("isUnresolved"));
- QV4::Property *p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, 30, QQmlDelegateModelItem::get_member));
+ p->setSetter(0);
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+
s = v4->newString(QStringLiteral("inItems"));
- p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member));
p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+
s = v4->newString(QStringLiteral("inPersistedItems"));
- p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member));
p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+
s = v4->newString(QStringLiteral("itemsIndex"));
- p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+
s = v4->newString(QStringLiteral("persistedItemsIndex"));
- p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index));
+ p->setSetter(0);
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
for (int i = 2; i < groupNames.count(); ++i) {
QString propertyName = QStringLiteral("in") + groupNames.at(i);
propertyName.replace(2, 1, propertyName.at(2).toUpper());
s = v4->newString(propertyName);
- p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_member));
p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::set_member));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
for (int i = 2; i < groupNames.count(); ++i) {
const QString propertyName = groupNames.at(i) + QStringLiteral("Index");
s = v4->newString(propertyName);
- p = proto->insertMember(s, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index));
+ p->setSetter(0);
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
modelItemProto = proto;
}
@@ -1692,7 +1701,7 @@ int QQmlDelegateModelItemMetaType::parseGroups(const QV4::ValueRef groups) const
QV4::ScopedArrayObject array(scope, groups);
if (array) {
QV4::ScopedValue v(scope);
- uint arrayLength = array->arrayLength();
+ uint arrayLength = array->getLength();
for (uint i = 0; i < arrayLength; ++i) {
v = array->getIndexed(i);
const QString groupName = v->toQString();
@@ -1786,7 +1795,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI
//---------------------------------------------------------------------------
-DEFINE_MANAGED_VTABLE(QQmlDelegateModelItemObject);
+DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject);
QQmlDelegateModelItemObject::~QQmlDelegateModelItemObject()
{
@@ -1863,11 +1872,16 @@ void QQmlDelegateModelItem::incubateObject(
incubatorPriv->compiledData = componentPriv->cc;
incubatorPriv->compiledData->addref();
- incubatorPriv->vme.init(
- context,
- componentPriv->cc,
- componentPriv->start,
- componentPriv->creationContext);
+ if (enginePriv->useNewCompiler) {
+ incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->cc, componentPriv->creationContext));
+ incubatorPriv->subComponentToCreate = componentPriv->start;
+ } else {
+ incubatorPriv->vme.init(
+ context,
+ componentPriv->cc,
+ componentPriv->start,
+ componentPriv->creationContext);
+ }
enginePriv->incubate(*incubationTask, forContext);
}
@@ -3140,11 +3154,11 @@ void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset
struct QQmlDelegateModelGroupChange : QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
: Object(engine)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
@@ -3174,17 +3188,20 @@ struct QQmlDelegateModelGroupChange : QV4::Object
QQmlChangeSet::Change change;
};
-DEFINE_MANAGED_VTABLE(QQmlDelegateModelGroupChange);
+DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
class QQmlDelegateModelGroupChangeArray : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
public:
QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine)
: Object(engine)
{
- setVTable(&static_vtbl);
- flags &= ~SimpleArray;
+ setVTable(staticVTable());
+ QV4::Scope scope(engine);
+ QV4::ScopedObject protectThis(scope, this);
+ Q_UNUSED(protectThis);
+ setArrayType(QV4::ArrayData::Custom);
}
virtual ~QQmlDelegateModelGroupChangeArray() {}
@@ -3239,7 +3256,7 @@ public:
};
-DEFINE_MANAGED_VTABLE(QQmlDelegateModelGroupChangeArray);
+DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChangeArray);
class QQmlDelegateModelGroupRemoveArray : public QQmlDelegateModelGroupChangeArray
{
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index f78cf38535..32b1154d30 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -161,11 +161,11 @@ protected:
struct QQmlDelegateModelItemObject : QV4::Object
{
- Q_MANAGED;
+ V4_OBJECT;
QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
: Object(engine)
, item(item)
- { setVTable(&static_vtbl); }
+ { setVTable(staticVTable()); }
~QQmlDelegateModelItemObject();
static void destroy(Managed *that);
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 7e441023c9..50b7614c3b 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -219,6 +219,7 @@ const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QV
case QVariant::Bool: type = Role::Bool; break;
case QVariant::String: type = Role::String; break;
case QVariant::Map: type = Role::VariantMap; break;
+ case QVariant::DateTime: type = Role::DateTime; break;
default: type = Role::Invalid; break;
}
@@ -441,7 +442,7 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
- int arrayLength = a->arrayLength();
+ int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
o = a->getIndexed(j);
subModel->append(o, eng);
@@ -517,7 +518,7 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
if (r.type == ListLayout::Role::List) {
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
- int arrayLength = a->arrayLength();
+ int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
o = a->getIndexed(j);
subModel->append(o, eng);
@@ -1188,7 +1189,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::ValueRef
QV4::Scoped<QV4::Object> o(scope);
ListModel *subModel = new ListModel(role.subLayout, 0, -1);
- int arrayLength = a->arrayLength();
+ int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
o = a->getIndexed(j);
subModel->append(o, eng);
@@ -1953,7 +1954,7 @@ void QQmlListModel::insert(QQmlV4Function *args)
if (objectArray) {
QV4::ScopedObject argObject(scope);
- int objectArrayLength = objectArray->arrayLength();
+ int objectArrayLength = objectArray->getLength();
for (int i=0 ; i < objectArrayLength ; ++i) {
argObject = objectArray->getIndexed(i);
@@ -2055,7 +2056,7 @@ void QQmlListModel::append(QQmlV4Function *args)
if (objectArray) {
QV4::Scoped<QV4::Object> argObject(scope);
- int objectArrayLength = objectArray->arrayLength();
+ int objectArrayLength = objectArray->getLength();
int index = count();
for (int i=0 ; i < objectArrayLength ; ++i) {
@@ -2384,6 +2385,136 @@ bool QQmlListModelParser::compileProperty(const QQmlCustomParserProperty &prop,
return true;
}
+bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding, QList<QQmlListModelParser::ListInstruction> &instr, QByteArray &data)
+{
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
+ const QV4::CompiledData::Object *target = qmlUnit->objectAt(binding->value.objectIndex);
+ QString objName = qmlUnit->header.stringAt(target->inheritedTypeNameIndex);
+ if (objName != listElementTypeName) {
+ const QMetaObject *mo = resolveType(objName);
+ if (mo != &QQmlListElement::staticMetaObject) {
+ error(target, QQmlListModel::tr("ListElement: cannot contain nested elements"));
+ return false;
+ }
+ listElementTypeName = objName; // cache right name for next time
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Push;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ if (!qmlUnit->header.stringAt(target->idIndex).isEmpty()) {
+ error(binding, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
+ return false;
+ }
+
+ const QV4::CompiledData::Binding *binding = target->bindingTable();
+ for (quint32 i = 0; i < target->nBindings; ++i, ++binding) {
+ QString propName = qmlUnit->header.stringAt(binding->propertyNameIndex);
+ if (propName.isEmpty()) {
+ error(binding, QQmlListModel::tr("ListElement: cannot contain nested elements"));
+ return false;
+ }
+ ListInstruction li;
+ int ref = data.count();
+ data.append(propName.toUtf8());
+ data.append('\0');
+ li.type = ListInstruction::Set;
+ li.dataIdx = ref;
+ instr << li;
+
+ if (!compileProperty(qmlUnit, binding, instr, data))
+ return false;
+
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ } else {
+ int ref = data.count();
+
+ QByteArray d;
+
+ if (binding->type == QV4::CompiledData::Binding::Type_String) {
+ d += char(QQmlScript::Variant::String);
+ d += binding->valueAsString(&qmlUnit->header).toUtf8();
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
+ d += char(QQmlScript::Variant::Number);
+ d += QByteArray::number(binding->valueAsNumber(),'g',20);
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
+ d += char(QQmlScript::Variant::Boolean);
+ d += char(binding->valueAsBoolean());
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
+ QString scriptStr = binding->valueAsScriptString(&qmlUnit->header);
+ if (definesEmptyList(scriptStr)) {
+ d[0] = char(QQmlScript::Variant::Invalid); // marks empty list
+ } else {
+ QByteArray script = scriptStr.toUtf8();
+ bool ok;
+ int v = evaluateEnum(script, &ok);
+ if (!ok) {
+ using namespace QQmlJS;
+ AST::Node *node = astForBinding(binding->value.compiledScriptIndex);
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement*>(node))
+ node = stmt->expression;
+ AST::StringLiteral *literal = 0;
+ if (AST::CallExpression *callExpr = AST::cast<AST::CallExpression *>(node)) {
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(callExpr->base)) {
+ if (idExpr->name == QLatin1String("QT_TR_NOOP") || idExpr->name == QLatin1String("QT_TRID_NOOP")) {
+ if (callExpr->arguments && !callExpr->arguments->next)
+ literal = AST::cast<AST::StringLiteral *>(callExpr->arguments->expression);
+ if (!literal) {
+ error(binding, QQmlListModel::tr("ListElement: improperly specified %1").arg(idExpr->name.toString()));
+ return false;
+ }
+ } else if (idExpr->name == QLatin1String("QT_TRANSLATE_NOOP")) {
+ if (callExpr->arguments && callExpr->arguments->next && !callExpr->arguments->next->next)
+ literal = AST::cast<AST::StringLiteral *>(callExpr->arguments->next->expression);
+ if (!literal) {
+ error(binding, QQmlListModel::tr("ListElement: improperly specified QT_TRANSLATE_NOOP"));
+ return false;
+ }
+ }
+ }
+ }
+
+ if (literal) {
+ d[0] = char(QQmlScript::Variant::String);
+ d += literal->value.toUtf8();
+ } else {
+ error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
+ return false;
+ }
+ } else {
+ d[0] = char(QQmlScript::Variant::Number);
+ d += QByteArray::number(v);
+ }
+ }
+ }
+
+ d.append('\0');
+ data.append(d);
+
+ ListInstruction li;
+ li.type = ListInstruction::Value;
+ li.dataIdx = ref;
+ instr << li;
+ }
+
+ return true;
+}
+
QByteArray QQmlListModelParser::compile(const QList<QQmlCustomParserProperty> &customProps)
{
QList<ListInstruction> instr;
@@ -2420,6 +2551,40 @@ QByteArray QQmlListModelParser::compile(const QList<QQmlCustomParserProperty> &c
return rv;
}
+QByteArray QQmlListModelParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+{
+ QList<ListInstruction> instr;
+ QByteArray data;
+ listElementTypeName = QString(); // unknown
+
+ foreach (const QV4::CompiledData::Binding *binding, bindings) {
+ QString propName = qmlUnit->header.stringAt(binding->propertyNameIndex);
+ if (!propName.isEmpty()) { // isn't default property
+ error(binding, QQmlListModel::tr("ListModel: undefined property '%1'").arg(propName));
+ return QByteArray();
+ }
+ if (!compileProperty(qmlUnit, binding, instr, data))
+ return QByteArray();
+ }
+
+ int size = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction) +
+ data.count();
+
+ QByteArray rv;
+ rv.resize(size);
+
+ ListModelData *lmd = (ListModelData *)rv.data();
+ lmd->dataOffset = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction);
+ lmd->instrCount = instr.count();
+ for (int ii = 0; ii < instr.count(); ++ii)
+ lmd->instructions()[ii] = instr.at(ii);
+ ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
+
+ return rv;
+}
+
void QQmlListModelParser::setCustomData(QObject *obj, const QByteArray &d)
{
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 722cb2b44d..172d857687 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -160,6 +160,7 @@ class QQmlListModelParser : public QQmlCustomParser
public:
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
QByteArray compile(const QList<QQmlCustomParserProperty> &);
+ QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
void setCustomData(QObject *, const QByteArray &);
private:
@@ -175,6 +176,7 @@ private:
ListInstruction *instructions() const;
};
bool compileProperty(const QQmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
+ bool compileProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding, QList<ListInstruction> &instr, QByteArray &data);
bool definesEmptyList(const QString &);
@@ -188,8 +190,12 @@ private:
ListModel *model;
int elementIndex;
};
+
+ friend class QTypeInfo<QQmlListModelParser::ListInstruction>;
};
+Q_DECLARE_TYPEINFO(QQmlListModelParser::ListInstruction, Q_PRIMITIVE_TYPE);
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQmlListModel)
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 53e45e2003..da34101c36 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -62,7 +62,7 @@
#include <private/qv8engine_p.h>
#include <private/qv4serialize_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -195,15 +195,15 @@ private:
void reportScriptException(WorkerScript *, const QQmlError &error);
};
-QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent)
+QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent)
: QV8Engine(0), p(parent), accessManager(0)
{
m_v4Engine->v8Engine = this;
}
-QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
-{
- delete accessManager;
+QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
+{
+ delete accessManager;
}
void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
@@ -264,7 +264,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
return v.asReturnedValue();
}
-QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
+QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
{
if (!accessManager) {
if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
@@ -411,7 +411,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
}
}
-void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script,
+void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script,
const QQmlError &error)
{
QQuickWorkerScriptEnginePrivate *p = QQuickWorkerScriptEnginePrivate::get(workerEngine);
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 38fdffdde6..d38e5ac3df 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -46,7 +46,7 @@
#include <private/qqmlproperty_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -219,6 +219,7 @@ public:
QV4::Scoped<QV4::Object> proto(scope, v4->newObject());
proto->defineAccessorProperty(QStringLiteral("index"), get_index, 0);
proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, 0);
+ QV4::ScopedProperty p(scope);
typedef QHash<QByteArray, int>::const_iterator iterator;
for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
@@ -226,9 +227,9 @@ public:
const QByteArray &propertyName = it.key();
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::Property *p = proto->insertMember(name, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
p->setGetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property));
p->setSetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property));
+ proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
}
prototype = proto;
}
diff --git a/src/quick/doc/snippets/qml/animatedimage.qml b/src/quick/doc/snippets/qml/animatedimage.qml
index d2f778e030..f6e8d027ea 100644
--- a/src/quick/doc/snippets/qml/animatedimage.qml
+++ b/src/quick/doc/snippets/qml/animatedimage.qml
@@ -49,7 +49,7 @@ Rectangle {
AnimatedImage { id: animation; source: "animation.gif" }
- Rectangle {
+ Rectangle {
property int frames: animation.frameCount
width: 4; height: 8
diff --git a/src/quick/doc/snippets/qml/listview/listview.qml b/src/quick/doc/snippets/qml/listview/listview.qml
index 41c7f78fbe..868ba4dfc1 100644
--- a/src/quick/doc/snippets/qml/listview/listview.qml
+++ b/src/quick/doc/snippets/qml/listview/listview.qml
@@ -141,7 +141,7 @@ ListView {
}
model: ContactModel {}
- delegate: contactsDelegate
+ delegate: contactsDelegate
focus: true
}
//![isCurrentItem]
diff --git a/src/quick/doc/snippets/qml/loader/connections.qml b/src/quick/doc/snippets/qml/loader/connections.qml
index cc63fad40d..a433f4a40e 100644
--- a/src/quick/doc/snippets/qml/loader/connections.qml
+++ b/src/quick/doc/snippets/qml/loader/connections.qml
@@ -49,7 +49,7 @@ Item {
source: "MyItem.qml"
}
- Connections {
+ Connections {
target: myLoader.item
onMessage: console.log(msg)
}
diff --git a/src/quick/doc/snippets/qml/loader/simple.qml b/src/quick/doc/snippets/qml/loader/simple.qml
index 4a68a3ce53..e9a1940ac6 100644
--- a/src/quick/doc/snippets/qml/loader/simple.qml
+++ b/src/quick/doc/snippets/qml/loader/simple.qml
@@ -46,7 +46,7 @@ Item {
Loader { id: pageLoader }
- MouseArea {
+ MouseArea {
anchors.fill: parent
onClicked: pageLoader.source = "Page1.qml"
}
diff --git a/src/quick/doc/snippets/qml/parentanimation.qml b/src/quick/doc/snippets/qml/parentanimation.qml
index c5077ba000..6652030e15 100644
--- a/src/quick/doc/snippets/qml/parentanimation.qml
+++ b/src/quick/doc/snippets/qml/parentanimation.qml
@@ -43,13 +43,13 @@ import QtQuick 2.0
Item {
width: 200; height: 100
- Rectangle {
+ Rectangle {
id: redRect
width: 100; height: 100
color: "red"
}
- Rectangle {
+ Rectangle {
id: blueRect
x: redRect.width
width: 50; height: 50
diff --git a/src/quick/doc/snippets/qml/parentchange.qml b/src/quick/doc/snippets/qml/parentchange.qml
index 777fa225eb..4f1fb2a286 100644
--- a/src/quick/doc/snippets/qml/parentchange.qml
+++ b/src/quick/doc/snippets/qml/parentchange.qml
@@ -43,13 +43,13 @@ import QtQuick 2.0
Item {
width: 200; height: 100
- Rectangle {
+ Rectangle {
id: redRect
width: 100; height: 100
color: "red"
}
- Rectangle {
+ Rectangle {
id: blueRect
x: redRect.width
width: 50; height: 50
diff --git a/src/quick/doc/snippets/qml/propertyanimation.qml b/src/quick/doc/snippets/qml/propertyanimation.qml
index 4d7140d406..db589bbc21 100644
--- a/src/quick/doc/snippets/qml/propertyanimation.qml
+++ b/src/quick/doc/snippets/qml/propertyanimation.qml
@@ -55,8 +55,8 @@ Rectangle {
}
//! [single state]
- transitions: Transition {
- PropertyAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
+ transitions: Transition {
+ PropertyAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
}
}
//![transition]
diff --git a/src/quick/doc/snippets/qml/propertychanges.qml b/src/quick/doc/snippets/qml/propertychanges.qml
index b49b9df2eb..f9f1b807e0 100644
--- a/src/quick/doc/snippets/qml/propertychanges.qml
+++ b/src/quick/doc/snippets/qml/propertychanges.qml
@@ -53,9 +53,9 @@ Item {
width: 100; height: 100
color: "red"
- MouseArea {
+ MouseArea {
id: mouseArea
- anchors.fill: parent
+ anchors.fill: parent
}
states: State {
diff --git a/src/quick/doc/snippets/qml/repeaters/repeater.qml b/src/quick/doc/snippets/qml/repeaters/repeater.qml
index 704bea6bee..3afc8c67c2 100644
--- a/src/quick/doc/snippets/qml/repeaters/repeater.qml
+++ b/src/quick/doc/snippets/qml/repeaters/repeater.qml
@@ -48,7 +48,7 @@ Row {
Row {
Repeater {
model: 3
- Rectangle {
+ Rectangle {
width: 100; height: 40
border.width: 1
color: "yellow"
@@ -60,7 +60,7 @@ Row {
//! [index]
Column {
Repeater {
- model: 10
+ model: 10
Text { text: "I'm item " + index }
}
}
@@ -79,7 +79,7 @@ Column {
Row {
Rectangle { width: 10; height: 20; color: "red" }
Repeater {
- model: 10
+ model: 10
Rectangle { width: 20; height: 20; radius: 10; color: "green" }
}
Rectangle { width: 10; height: 20; color: "blue" }
diff --git a/src/quick/doc/snippets/qml/rotationanimation.qml b/src/quick/doc/snippets/qml/rotationanimation.qml
index 3924332f86..677c798ce9 100644
--- a/src/quick/doc/snippets/qml/rotationanimation.qml
+++ b/src/quick/doc/snippets/qml/rotationanimation.qml
@@ -50,9 +50,9 @@ Item {
color: "red"
antialiasing: true
- states: State {
+ states: State {
name: "rotated"
- PropertyChanges { target: rect; rotation: 180 }
+ PropertyChanges { target: rect; rotation: 180 }
}
transitions: Transition {
diff --git a/src/quick/doc/snippets/qml/row.qml b/src/quick/doc/snippets/qml/row.qml
index ad8a21326b..88f24c9140 100644
--- a/src/quick/doc/snippets/qml/row.qml
+++ b/src/quick/doc/snippets/qml/row.qml
@@ -48,7 +48,7 @@ Rectangle {
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
-
+
spacing: 5
Rectangle { width: 100; height: 100; radius: 20.0
diff --git a/src/quick/doc/snippets/qml/state.qml b/src/quick/doc/snippets/qml/state.qml
index 03475c49ab..09afde4b6f 100644
--- a/src/quick/doc/snippets/qml/state.qml
+++ b/src/quick/doc/snippets/qml/state.qml
@@ -45,9 +45,9 @@ Rectangle {
width: 100; height: 100
color: "black"
- MouseArea {
+ MouseArea {
id: mouseArea
- anchors.fill: parent
+ anchors.fill: parent
onClicked: myRect.state == 'clicked' ? myRect.state = "" : myRect.state = 'clicked';
}
diff --git a/src/quick/doc/snippets/qml/transition-from-to.qml b/src/quick/doc/snippets/qml/transition-from-to.qml
index 415ab4f41f..7afc097eef 100644
--- a/src/quick/doc/snippets/qml/transition-from-to.qml
+++ b/src/quick/doc/snippets/qml/transition-from-to.qml
@@ -52,7 +52,7 @@ Rectangle {
PropertyChanges { target: rect; color: "yellow" }
}
- transitions: Transition {
+ transitions: Transition {
ColorAnimation { duration: 1000 }
}
}
diff --git a/src/quick/doc/snippets/qml/transition-reversible.qml b/src/quick/doc/snippets/qml/transition-reversible.qml
index 03848a37fa..1bb5a0bc5b 100644
--- a/src/quick/doc/snippets/qml/transition-reversible.qml
+++ b/src/quick/doc/snippets/qml/transition-reversible.qml
@@ -54,7 +54,7 @@ Rectangle {
}
//! [sequential animations]
- transitions: Transition {
+ transitions: Transition {
SequentialAnimation {
PropertyAnimation { property: "x"; duration: 1000 }
ColorAnimation { duration: 1000 }
diff --git a/src/quick/doc/snippets/qml/transition.qml b/src/quick/doc/snippets/qml/transition.qml
index a4189074fa..421149764c 100644
--- a/src/quick/doc/snippets/qml/transition.qml
+++ b/src/quick/doc/snippets/qml/transition.qml
@@ -55,8 +55,8 @@ Rectangle {
PropertyChanges { target: rect; x: 50; y: 50 }
}
- transitions: Transition {
- NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
+ transitions: Transition {
+ NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
}
}
//![0]
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 16075f0db3..278733de8d 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -729,6 +729,9 @@ with multiple windows.
QQuickWindow::setColor() will be used in a call to \c glClear(),
which is potentially faster.
+ \li Mipmapped Image items are not placed in global atlas and will
+ not be batched.
+
\endlist
If an application performs poorly, make sure that rendering is
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index b3a2c9f46a..ed5c8d7bcb 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -54,7 +54,7 @@
#include <QtCore/QBuffer>
#include <QtCore/qdatetime.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -180,7 +180,7 @@ QQuickCanvasItemPrivate::QQuickCanvasItemPrivate()
, renderTarget(QQuickCanvasItem::Image)
, renderStrategy(QQuickCanvasItem::Immediate)
{
- antialiasing = true;
+ implicitAntialiasing = true;
}
QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
@@ -642,7 +642,7 @@ void QQuickCanvasItem::updatePolish()
Q_D(QQuickCanvasItem);
if (d->context && d->renderStrategy != QQuickCanvasItem::Cooperative)
- d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, d->antialiasing);
+ d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing());
if (d->animationCallbacks.size() > 0 && isVisible()) {
QMap<int, QV4::PersistentValue> animationCallbacks = d->animationCallbacks;
@@ -705,7 +705,7 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
node->setFiltering(QSGTexture::Nearest);
if (d->renderStrategy == QQuickCanvasItem::Cooperative) {
- d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, d->antialiasing);
+ d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing());
d->context->flush();
}
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index b6d4f1073c..9851983201 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -65,7 +65,7 @@
#include <QtCore/qnumeric.h>
#include <private/qquickwindow_p.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -479,12 +479,12 @@ V8_DEFINE_EXTENSION(QQuickContext2DEngineData, engineData)
class QQuickJSContext2D : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
public:
QQuickJSContext2D(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
QQuickContext2D* context;
@@ -535,12 +535,12 @@ protected:
}
};
-DEFINE_MANAGED_VTABLE(QQuickJSContext2D);
+DEFINE_OBJECT_VTABLE(QQuickJSContext2D);
struct QQuickJSContext2DPrototype : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
public:
QQuickJSContext2DPrototype(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
@@ -641,19 +641,19 @@ public:
};
-DEFINE_MANAGED_VTABLE(QQuickJSContext2DPrototype);
+DEFINE_OBJECT_VTABLE(QQuickJSContext2DPrototype);
class QQuickContext2DStyle : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
public:
QQuickContext2DStyle(QV4::ExecutionEngine *e)
: QV4::Object(e)
, patternRepeatX(false)
, patternRepeatY(false)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
QBrush brush;
bool patternRepeatX:1;
@@ -667,7 +667,7 @@ protected:
}
};
-DEFINE_MANAGED_VTABLE(QQuickContext2DStyle);
+DEFINE_OBJECT_VTABLE(QQuickContext2DStyle);
QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0)
{
@@ -866,12 +866,15 @@ static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
struct QQuickJSContext2DPixelData : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
{
- setVTable(&static_vtbl);
- flags &= ~SimpleArray;
+ setVTable(staticVTable());
+ QV4::Scope scope(engine);
+ QV4::ScopedObject protectThis(scope, this);
+ Q_UNUSED(protectThis);
+ setArrayType(QV4::ArrayData::Custom);
}
static void destroy(QV4::Managed *that) {
@@ -885,15 +888,15 @@ struct QQuickJSContext2DPixelData : public QV4::Object
QImage image;
};
-DEFINE_MANAGED_VTABLE(QQuickJSContext2DPixelData);
+DEFINE_OBJECT_VTABLE(QQuickJSContext2DPixelData);
struct QQuickJSContext2DImageData : public QV4::Object
{
- Q_MANAGED
+ V4_OBJECT
QQuickJSContext2DImageData(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
pixelData = QV4::Primitive::undefinedValue();
QV4::Scope scope(engine);
@@ -915,10 +918,12 @@ struct QQuickJSContext2DImageData : public QV4::Object
- QV4::SafeValue pixelData;
+ QV4::Value pixelData;
};
-DEFINE_MANAGED_VTABLE(QQuickJSContext2DImageData);
+DEFINE_REF(QQuickJSContext2DImageData, QV4::Object);
+
+DEFINE_OBJECT_VTABLE(QQuickJSContext2DImageData);
static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV8Engine* engine, const QImage& image)
{
@@ -2109,7 +2114,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::CallContext *ctx)
QV4::ScopedValue value(scope, ctx->argument(0));
r->context->beginPath();
- if (QV4::Referenced<QV4::QObjectWrapper> qobjectWrapper = value->asRef<QV4::QObjectWrapper>()) {
+ QV4::QObjectWrapperRef qobjectWrapper = value;
+ if (!!qobjectWrapper) {
if (QQuickPath *path = qobject_cast<QQuickPath*>(qobjectWrapper->object()))
r->context->m_path = path->path();
} else {
@@ -2980,7 +2986,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
pixmap = r->context->createPixmap(url);
} else if (arg->isObject()) {
- if (QV4::Referenced<QV4::QObjectWrapper> qobjectWrapper = arg->asRef<QV4::QObjectWrapper>()) {
+ QV4::QObjectWrapperRef qobjectWrapper = arg;
+ if (!!qobjectWrapper) {
if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
pixmap = r->context->createPixmap(imageItem->source());
} else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
@@ -2990,19 +2997,22 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
} else {
V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
- } else if (QV4::Referenced<QQuickJSContext2DImageData> imageData = arg->asRef<QQuickJSContext2DImageData>()) {
- QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->pixelData.as<QQuickJSContext2DPixelData>());
- if (pix && !pix->image.isNull()) {
- pixmap.take(new QQuickCanvasPixmap(pix->image));
+ } else {
+ QQuickJSContext2DImageDataRef imageData = arg;
+ if (!!imageData) {
+ QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->pixelData.as<QQuickJSContext2DPixelData>());
+ if (pix && !pix->image.isNull()) {
+ pixmap.take(new QQuickCanvasPixmap(pix->image));
+ } else {
+ V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
+ }
} else {
- V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
+ QUrl url(arg->toQStringNoThrow());
+ if (url.isValid())
+ pixmap = r->context->createPixmap(url);
+ else
+ V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
- } else {
- QUrl url(arg->toQStringNoThrow());
- if (url.isValid())
- pixmap = r->context->createPixmap(url);
- else
- V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
} else {
V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
@@ -3260,7 +3270,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC
if (ctx->callData->argc == 1) {
QV4::ScopedValue arg0(scope, ctx->callData->args[0]);
- if (QV4::Referenced<QQuickJSContext2DImageData> imgData = arg0->asRef<QQuickJSContext2DImageData>()) {
+ QQuickJSContext2DImageDataRef imgData = arg0;
+ if (!!imgData) {
QV4::Scoped<QQuickJSContext2DPixelData> pa(scope, imgData->pixelData.as<QQuickJSContext2DPixelData>());
if (pa) {
qreal w = pa->image.width();
@@ -3337,7 +3348,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont
if (!qIsFinite(dx) || !qIsFinite(dy))
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
- QV4::Referenced<QQuickJSContext2DImageData> imageData = arg0->asRef<QQuickJSContext2DImageData>();
+ QQuickJSContext2DImageDataRef imageData = arg0;
if (!imageData)
return ctx->callData->thisObject.asReturnedValue();
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 6399da3dee..4390ae62cc 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -55,7 +55,7 @@
#include <private/qv8engine_p.h>
#include <QtCore/QWaitCondition>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
//#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose!
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 8dd48b4988..d3f2a956a3 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -427,7 +427,6 @@ QSGTexture *QQuickContext2DFBOTexture::textureForNextFrame(QSGTexture *lastTextu
if (m_fbo) {
if (!texture) {
texture = new QSGPlainTexture();
- texture->setHasMipmaps(false);
texture->setHasAlphaChannel(true);
texture->setOwnsTexture(false);
m_dirtyTexture = true;
@@ -655,7 +654,6 @@ QSGTexture *QQuickContext2DImageTexture::textureForNextFrame(QSGTexture *last)
if (!texture) {
texture = new QSGPlainTexture();
- texture->setHasMipmaps(false);
texture->setHasAlphaChannel(true);
m_dirtyTexture = true;
}
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index 41cdb3526b..cb378b424b 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -10,6 +10,7 @@ HEADERS += \
$$PWD/qquickrectangle_p_p.h \
$$PWD/qquickwindow.h \
$$PWD/qquickwindow_p.h \
+ $$PWD/qquickrendercontrol_p.h \
$$PWD/qquickfocusscope_p.h \
$$PWD/qquickitemsmodule_p.h \
$$PWD/qquickpainteditem.h \
@@ -82,6 +83,7 @@ SOURCES += \
$$PWD/qquickitem.cpp \
$$PWD/qquickrectangle.cpp \
$$PWD/qquickwindow.cpp \
+ $$PWD/qquickrendercontrol.cpp \
$$PWD/qquickfocusscope.cpp \
$$PWD/qquickitemsmodule.cpp \
$$PWD/qquickpainteditem.cpp \
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index 3c00a7d62d..b5cc6ea3ef 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -139,6 +139,57 @@ QT_BEGIN_NAMESPACE
\endtable
*/
+/*! \qmlproperty bool focusable
+ \brief This property holds whether this item is focusable.
+
+ By default, this property is false except for items where the role is one of
+ CheckBox, RadioButton, Button, MenuItem, PageTab, EditableText, SpinBox, ComboBox,
+ Terminal or ScrollBar.
+*/
+/*! \qmlproperty bool focused
+ \brief This property holds whether this item currently has the active focus.
+
+ By default, this property is false, but it will return true for items that
+ have \l QQuickItem::hasActiveFocus() returning true.
+*/
+/*! \qmlproperty bool checkable
+ \brief This property holds whether this item is checkable (like a check box or some buttons).
+*/
+/*! \qmlproperty bool checked
+ \brief This property holds whether this item is currently checked.
+*/
+/*! \qmlproperty bool editable
+ \brief This property holds whether this item has editable text.
+*/
+/*! \qmlproperty bool multiLine
+ \brief This property holds whether this item has multiple text lines.
+*/
+/*! \qmlproperty bool readOnly
+ \brief This property holds whether this item while being of type \l QAccessible::EditableText
+ is set to read-only.
+*/
+/*! \qmlproperty bool selected
+ \brief This property holds whether this item is selected.
+*/
+/*! \qmlproperty bool selectable
+ \brief This property holds whether this item can be selected.
+*/
+/*! \qmlproperty bool pressed
+ \brief This property holds whether this item is pressed (for example a button during a mouse click).
+*/
+/*! \qmlproperty bool checkStateMixed
+ \brief This property holds whether this item is in the partially checked state.
+*/
+/*! \qmlproperty bool defaultButton
+ \brief This property holds whether this item is the default button of a dialog.
+*/
+/*! \qmlproperty bool passwordEdit
+ \brief This property holds whether this item is a password text edit.
+*/
+/*! \qmlproperty bool selectableText
+ \brief This property holds whether this item contains selectable text.
+*/
+
QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
: QObject(parent), m_role(QAccessible::NoRole)
{
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index 298c473cf8..1f2c6bf532 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -55,15 +55,46 @@
QT_BEGIN_NAMESPACE
+#define STATE_PROPERTY(P) \
+ Q_PROPERTY(bool P READ P WRITE set_ ## P NOTIFY P ## Changed FINAL) \
+ bool P() const { return m_state.P ; } \
+ void set_ ## P(bool arg) \
+ { \
+ if (m_state.P == arg) \
+ return; \
+ m_state.P = arg; \
+ emit P ## Changed(arg); \
+ QAccessible::State changedState; \
+ changedState.P = true; \
+ QAccessibleStateChangeEvent ev(parent(), changedState); \
+ QAccessible::updateAccessibility(&ev); \
+ } \
+ Q_SIGNAL void P ## Changed(bool arg);
+
+
class Q_QUICK_PRIVATE_EXPORT QQuickAccessibleAttached : public QObject
{
Q_OBJECT
- Q_PROPERTY(QAccessible::Role role READ role WRITE setRole NOTIFY roleChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged)
+ Q_PROPERTY(QAccessible::Role role READ role WRITE setRole NOTIFY roleChanged FINAL)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL)
+ Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged FINAL)
public:
- Q_ENUMS(QAccessible::Role QAccessible::Event QAccessible::State)
+ Q_ENUMS(QAccessible::Role QAccessible::Event)
+ STATE_PROPERTY(checkable)
+ STATE_PROPERTY(checked)
+ STATE_PROPERTY(editable)
+ STATE_PROPERTY(focusable)
+ STATE_PROPERTY(focused)
+ STATE_PROPERTY(multiLine)
+ STATE_PROPERTY(readOnly)
+ STATE_PROPERTY(selected)
+ STATE_PROPERTY(selectable)
+ STATE_PROPERTY(pressed)
+ STATE_PROPERTY(checkStateMixed)
+ STATE_PROPERTY(defaultButton)
+ STATE_PROPERTY(passwordEdit)
+ STATE_PROPERTY(selectableText)
QQuickAccessibleAttached(QObject *parent);
~QQuickAccessibleAttached();
@@ -76,9 +107,33 @@ public:
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;
+ }
}
}
- QString name() const { return m_name; }
+ QString name() const {
+ if (m_state.passwordEdit)
+ return QString();
+ return m_name;
+ }
void setName(const QString &name) {
if (name != m_name) {
m_name = name;
@@ -102,12 +157,12 @@ public:
// Factory function
static QQuickAccessibleAttached *qmlAttachedProperties(QObject *obj);
- // Property getter
- static QObject *attachedProperties(const QObject *obj)
+ static QQuickAccessibleAttached *attachedProperties(const QObject *obj)
{
- return qmlAttachedPropertiesObject<QQuickAccessibleAttached>(obj, false);
+ return qobject_cast<QQuickAccessibleAttached*>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(obj, false));
}
+ // Property getter
static QVariant property(const QObject *object, const char *propertyName)
{
if (QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object))
@@ -128,8 +183,8 @@ public:
static QObject *findAccessible(QObject *object, QAccessible::Role role = QAccessible::NoRole)
{
while (object) {
- QObject *att = QQuickAccessibleAttached::attachedProperties(object);
- if (att && (role == QAccessible::NoRole || att->property("role").toInt() == role)) {
+ QQuickAccessibleAttached *att = QQuickAccessibleAttached::attachedProperties(object);
+ if (att && (role == QAccessible::NoRole || att->role() == role)) {
break;
}
object = object->parent();
@@ -137,6 +192,8 @@ public:
return object;
}
+ QAccessible::State state() { return m_state; }
+
public Q_SLOTS:
void valueChanged() {
QAccessibleValueChangeEvent ev(parent(), parent()->property("value"));
@@ -153,7 +210,10 @@ Q_SIGNALS:
void descriptionChanged();
private:
+ QQuickItem *item() const { return static_cast<QQuickItem*>(parent()); }
+
QAccessible::Role m_role;
+ QAccessible::State m_state;
QString m_name;
QString m_description;
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 8ecf473d85..b4a89b3107 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -619,6 +619,7 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
node->setMirror(d->mirror);
+ node->setMipmapFiltering(QSGTexture::None);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
if (innerSourceRect == QRectF(0, 0, 1, 1) && (vTiles > 1 || hTiles > 1)) {
node->setHorizontalWrapMode(QSGTexture::Repeat);
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 789d1952c0..2f2c932db5 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1262,6 +1262,8 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
return;
}
+ event->setAccepted(false);
+
int yDelta = event->angleDelta().y();
int xDelta = event->angleDelta().x();
if (yflick() && yDelta != 0) {
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 1107425575..8587da5ac3 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -630,8 +630,8 @@ void QQuickGridViewPrivate::updateViewport()
void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex)
{
if (visibleItems.count()) {
- const qreal from = isContentFlowReversed() ? -position() - size() : position();
- const qreal to = isContentFlowReversed() ? -position() : position() + size();
+ const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning;
+ const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd;
FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
qreal rowPos = firstItem->rowPos();
@@ -1534,7 +1534,35 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
of additional memory usage. It is not a substitute for creating efficient
delegates; the fewer objects and bindings in a delegate, the faster a view may be
scrolled.
+
+ The cacheBuffer operates outside of any display margins specified by
+ displayMarginBeginning or displayMarginEnd.
+*/
+
+/*!
+ \qmlproperty int QtQuick::GridView::displayMarginBeginning
+ \qmlproperty int QtQuick::GridView::displayMarginEnd
+ \since QtQuick 2.3
+
+ This property allows delegates to be displayed outside of the view geometry.
+
+ If this value is non-zero, the view will create extra delegates before the
+ start of the view, or after the end. The view will create as many delegates
+ as it can fit into the pixel size specified.
+
+ For example, if in a vertical view the delegate is 20 pixels high,
+ there are 3 columns, and
+ \c displayMarginBeginning and \c displayMarginEnd are both set to 40,
+ then 6 delegates above and 6 delegates below will be created and shown.
+
+ The default value is 0.
+
+ This property is meant for allowing certain UI configurations,
+ and not as a performance optimization. If you wish to create delegates
+ outside of the view geometry for performance reasons, you probably
+ want to use the cacheBuffer property instead.
*/
+
void QQuickGridView::setHighlightMoveDuration(int duration)
{
Q_D(QQuickGridView);
@@ -2000,8 +2028,8 @@ void QQuickGridView::viewportMoved(Qt::Orientations orient)
d->refillOrLayout();
// Set visibility of items to eliminate cost of items outside the visible area.
- qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
- qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
+ qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
+ qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxGridItemSG *item = static_cast<FxGridItemSG*>(d->visibleItems.at(i));
QQuickItemPrivate::get(item->item)->setCulled(item->rowPos() + d->rowSize() < from || item->rowPos() > to);
@@ -2350,7 +2378,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
// Insert items before the visible item.
int insertionIdx = index;
int i = count - 1;
- int from = tempPos - buffer;
+ int from = tempPos - buffer - displayMarginBeginning;
while (i >= 0) {
if (rowPos > from && insertionIdx < visibleIndex) {
@@ -2387,7 +2415,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
}
} else {
int i = 0;
- int to = buffer+tempPos+size()-1;
+ int to = buffer+displayMarginEnd+tempPos+size()-1;
while (i < count && rowPos <= to + rowSize()*(columns - colNum)/qreal(columns+1)) {
FxViewItem *item = 0;
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index 0708304051..69a39d2396 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -62,10 +62,17 @@ public:
{
}
+ void updateTexture(QSGTexture *texture) {
+ if (m_texture == texture)
+ return;
+ m_texture = texture;
+ emit textureChanged();
+ }
+
QSGTexture *texture() const {
if (m_texture) {
m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- m_texture->setMipmapFiltering(QSGTexture::Nearest);
+ m_texture->setMipmapFiltering(m_mipmap ? QSGTexture::Linear : QSGTexture::None);
m_texture->setHorizontalWrapMode(QSGTexture::ClampToEdge);
m_texture->setVerticalWrapMode(QSGTexture::ClampToEdge);
}
@@ -76,6 +83,7 @@ public:
QSGTexture *m_texture;
bool m_smooth;
+ bool m_mipmap;
};
#include "qquickimage.moc"
@@ -85,6 +93,7 @@ QQuickImagePrivate::QQuickImagePrivate()
, paintedWidth(0)
, paintedHeight(0)
, pixmapChanged(false)
+ , mipmap(false)
, hAlign(QQuickImage::AlignHCenter)
, vAlign(QQuickImage::AlignVCenter)
, provider(0)
@@ -365,6 +374,8 @@ qreal QQuickImage::paintedHeight() const
no visual or performance effect.
By default, this property is set to true.
+
+ \sa mipmap
*/
/*!
@@ -542,7 +553,8 @@ QSGTextureProvider *QQuickImage::textureProvider() const
QQuickImagePrivate *dd = const_cast<QQuickImagePrivate *>(d);
dd->provider = new QQuickImageTextureProvider;
dd->provider->m_smooth = d->smooth;
- dd->provider->m_texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window());
+ dd->provider->m_mipmap = d->mipmap;
+ dd->provider->updateTexture(d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window()));
}
return d->provider;
@@ -557,7 +569,8 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
// Copy over the current texture state into the texture provider...
if (d->provider) {
d->provider->m_smooth = d->smooth;
- d->provider->m_texture = texture;
+ d->provider->m_mipmap = d->mipmap;
+ d->provider->updateTexture(texture);
}
if (!texture || width() <= 0 || height() <= 0) {
@@ -663,16 +676,25 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
sourceRect.width() / d->pix.width(),
sourceRect.height() / d->pix.height());
+ if (targetRect.isEmpty()
+ || !qIsFinite(targetRect.width()) || !qIsFinite(targetRect.height())
+ || nsrect.isEmpty()
+ || !qIsFinite(nsrect.width()) || !qIsFinite(nsrect.height())) {
+ delete node;
+ return 0;
+ }
+
if (d->pixmapChanged) {
// force update the texture in the node to trigger reconstruction of
// geometry and the likes when a atlas segment has changed.
- if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat))
+ if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat || d->mipmap))
node->setTexture(texture->removedFromAtlas());
else
node->setTexture(texture);
d->pixmapChanged = false;
}
+ node->setMipmapFiltering(d->mipmap ? QSGTexture::Linear : QSGTexture::None);
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
@@ -739,4 +761,38 @@ void QQuickImage::setHorizontalAlignment(HAlignment align)
emit horizontalAlignmentChanged(align);
}
+/*!
+ \qmlproperty bool QtQuick::Image::mipmap
+ \since 5.3
+
+ This property holds whether the image uses mipmap filtering when scaled or
+ transformed.
+
+ Mipmap filtering gives better visual quality when scaling down
+ compared to smooth, but it may come at a performance cost (both when
+ initializing the image and during rendering).
+
+ By default, this property is set to false.
+
+ \sa smooth
+ */
+
+bool QQuickImage::mipmap() const
+{
+ Q_D(const QQuickImage);
+ return d->mipmap;
+}
+
+void QQuickImage::setMipmap(bool use)
+{
+ Q_D(QQuickImage);
+ if (d->mipmap == use)
+ return;
+ d->mipmap = use;
+ emit mipmapChanged(d->mipmap);
+
+ d->pixmapChanged = true;
+ update();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index e62c355dd4..902e613b04 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -60,6 +60,7 @@ class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase
Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged)
Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION 1)
public:
QQuickImage(QQuickItem *parent=0);
@@ -91,11 +92,15 @@ public:
bool isTextureProvider() const { return true; }
QSGTextureProvider *textureProvider() const;
+ bool mipmap() const;
+ void setMipmap(bool use);
+
Q_SIGNALS:
void fillModeChanged();
void paintedGeometryChanged();
void horizontalAlignmentChanged(HAlignment alignment);
void verticalAlignmentChanged(VAlignment alignment);
+ void mipmapChanged(bool);
protected:
QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent);
diff --git a/src/quick/items/qquickimage_p_p.h b/src/quick/items/qquickimage_p_p.h
index 632f76c51f..de88662ab8 100644
--- a/src/quick/items/qquickimage_p_p.h
+++ b/src/quick/items/qquickimage_p_p.h
@@ -73,6 +73,7 @@ public:
void setImage(const QImage &img);
bool pixmapChanged : 1;
+ bool mipmap : 1;
QQuickImage::HAlignment hAlign;
QQuickImage::VAlignment vAlign;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 88ffc7bba3..62ed5e0c85 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2709,6 +2709,8 @@ QQuickItemPrivate::QQuickItemPrivate()
, culled(false)
, hasCursor(false)
, activeFocusOnTab(false)
+ , implicitAntialiasing(false)
+ , antialiasingValid(false)
, dirtyAttributes(0)
, nextDirtyItem(0)
, prevDirtyItem(0)
@@ -3855,7 +3857,7 @@ void QQuickItem::polish()
Q_D(QQuickItem);
if (!d->polishScheduled) {
d->polishScheduled = true;
- if (d->window) {
+ if (d->window && (isVisible() || (d->extra.isAllocated() && d->extra->effectRefCount>0))) {
QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window);
bool maybeupdate = p->itemsToPolish.isEmpty();
p->itemsToPolish.insert(this);
@@ -4480,96 +4482,6 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
}
#endif // QT_NO_IM
-void QQuickItemPrivate::deliverFocusEvent(QFocusEvent *e)
-{
- Q_Q(QQuickItem);
-
- if (e->type() == QEvent::FocusIn) {
- q->focusInEvent(e);
- } else {
- q->focusOutEvent(e);
- }
-}
-
-void QQuickItemPrivate::deliverMouseEvent(QMouseEvent *e)
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(e->isAccepted());
-
- switch (e->type()) {
- default:
- Q_ASSERT(!"Unknown event type");
- case QEvent::MouseMove:
- q->mouseMoveEvent(e);
- break;
- case QEvent::MouseButtonPress:
- q->mousePressEvent(e);
- break;
- case QEvent::MouseButtonRelease:
- q->mouseReleaseEvent(e);
- break;
- case QEvent::MouseButtonDblClick:
- q->mouseDoubleClickEvent(e);
- break;
- }
-}
-
-#ifndef QT_NO_WHEELEVENT
-void QQuickItemPrivate::deliverWheelEvent(QWheelEvent *e)
-{
- Q_Q(QQuickItem);
- q->wheelEvent(e);
-}
-#endif
-
-void QQuickItemPrivate::deliverTouchEvent(QTouchEvent *e)
-{
- Q_Q(QQuickItem);
- q->touchEvent(e);
-}
-
-void QQuickItemPrivate::deliverHoverEvent(QHoverEvent *e)
-{
- Q_Q(QQuickItem);
- switch (e->type()) {
- default:
- Q_ASSERT(!"Unknown event type");
- case QEvent::HoverEnter:
- q->hoverEnterEvent(e);
- break;
- case QEvent::HoverLeave:
- q->hoverLeaveEvent(e);
- break;
- case QEvent::HoverMove:
- q->hoverMoveEvent(e);
- break;
- }
-}
-
-#ifndef QT_NO_DRAGANDDROP
-void QQuickItemPrivate::deliverDragEvent(QEvent *e)
-{
- Q_Q(QQuickItem);
- switch (e->type()) {
- default:
- Q_ASSERT(!"Unknown event type");
- case QEvent::DragEnter:
- q->dragEnterEvent(static_cast<QDragEnterEvent *>(e));
- break;
- case QEvent::DragLeave:
- q->dragLeaveEvent(static_cast<QDragLeaveEvent *>(e));
- break;
- case QEvent::DragMove:
- q->dragMoveEvent(static_cast<QDragMoveEvent *>(e));
- break;
- case QEvent::Drop:
- q->dropEvent(static_cast<QDropEvent *>(e));
- break;
- }
-}
-#endif // QT_NO_DRAGANDDROP
-
/*!
Called when \a change occurs for this item.
@@ -5329,6 +5241,8 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
if (windowPriv->mouseGrabberItem == q)
q->ungrabMouse();
+ if (polishScheduled)
+ windowPriv->itemsToPolish.insert(q);
}
bool childVisibilityChanged = false;
@@ -5575,6 +5489,9 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
}
break;
+ case QQuickItem::ItemAntialiasingHasChanged:
+ q->itemChange(change, data);
+ break;
}
}
@@ -5668,37 +5585,65 @@ void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab)
/*!
\qmlproperty bool QtQuick::Item::antialiasing
- Primarily used in Rectangle and image based elements to decide if the item should
- use antialiasing or not. Items with antialiasing enabled require more memory and
- are potentially slower to render.
+ Used by visual elements to decide if the item should use antialiasing or not.
+ In some cases items with antialiasing require more memory and are potentially
+ slower to render (see \l {Antialiasing} for more details).
- The default is false.
+ The default is false, but may be overridden by derived elements.
*/
/*!
\property QQuickItem::antialiasing
\brief Specifies whether the item is antialiased or not
- Primarily used in Rectangle and image based elements to decide if the item should
- use antialiasing or not. Items with antialiasing enabled require more memory and
- are potentially slower to render.
+ Used by visual elements to decide if the item should use antialiasing or not.
+ In some cases items with antialiasing require more memory and are potentially
+ slower to render (see \l {Antialiasing} for more details).
- The default is false.
+ The default is false, but may be overridden by derived elements.
*/
bool QQuickItem::antialiasing() const
{
Q_D(const QQuickItem);
- return d->antialiasing;
+ return d->antialiasingValid ? d->antialiasing : d->implicitAntialiasing;
}
-void QQuickItem::setAntialiasing(bool antialiasing)
+
+void QQuickItem::setAntialiasing(bool aa)
{
Q_D(QQuickItem);
- if (d->antialiasing == antialiasing)
+
+ bool changed = (aa != antialiasing());
+ d->antialiasingValid = true;
+
+ if (!changed)
return;
- d->antialiasing = antialiasing;
+ d->antialiasing = aa;
d->dirty(QQuickItemPrivate::Antialiasing);
- emit antialiasingChanged(antialiasing);
+ d->itemChange(ItemAntialiasingHasChanged, d->antialiasing);
+
+ emit antialiasingChanged(antialiasing());
+}
+
+void QQuickItem::resetAntialiasing()
+{
+ Q_D(QQuickItem);
+ if (!d->antialiasingValid)
+ return;
+
+ d->antialiasingValid = false;
+
+ if (d->implicitAntialiasing != d->antialiasing)
+ emit antialiasingChanged(antialiasing());
+}
+
+void QQuickItemPrivate::setImplicitAntialiasing(bool antialiasing)
+{
+ Q_Q(QQuickItem);
+ bool prev = q->antialiasing();
+ implicitAntialiasing = antialiasing;
+ if (componentComplete && (q->antialiasing() != prev))
+ emit q->antialiasingChanged(q->antialiasing());
}
/*!
@@ -6541,6 +6486,17 @@ void QQuickItemPrivate::incrementCursorCount(int delta)
#endif
}
+void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e)
+{
+ Q_Q(QQuickItem);
+ QQmlData *ddata = QQmlData::get(q);
+ if (ddata)
+ ddata->jsWrapper.markOnce(e);
+
+ foreach (QQuickItem *child, childItems)
+ QQuickItemPrivate::get(child)->markObjects(e);
+}
+
#ifndef QT_NO_CURSOR
/*!
@@ -6983,18 +6939,17 @@ QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const
*/
bool QQuickItem::event(QEvent *ev)
{
+ Q_D(QQuickItem);
+
+ switch (ev->type()) {
#if 0
- if (ev->type() == QEvent::PolishRequest) {
- Q_D(QQuickItem);
+ case QEvent::PolishRequest:
d->polishScheduled = false;
updatePolish();
- return true;
- } else {
- return QObject::event(ev);
- }
+ break;
#endif
#ifndef QT_NO_IM
- if (ev->type() == QEvent::InputMethodQuery) {
+ case QEvent::InputMethodQuery: {
QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev);
Qt::InputMethodQueries queries = query->queries();
for (uint i = 0; i < 32; ++i) {
@@ -7005,20 +6960,79 @@ bool QQuickItem::event(QEvent *ev)
}
}
query->accept();
- return true;
- } else if (ev->type() == QEvent::InputMethod) {
+ break;
+ }
+ case QEvent::InputMethod:
inputMethodEvent(static_cast<QInputMethodEvent *>(ev));
- return true;
- } else
+ break;
#endif // QT_NO_IM
- if (ev->type() == QEvent::StyleAnimationUpdate) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ case QEvent::TouchCancel:
+ touchEvent(static_cast<QTouchEvent*>(ev));
+ break;
+ case QEvent::StyleAnimationUpdate:
if (isVisible()) {
ev->accept();
update();
}
- return true;
+ break;
+ case QEvent::HoverEnter:
+ hoverEnterEvent(static_cast<QHoverEvent*>(ev));
+ break;
+ case QEvent::HoverLeave:
+ hoverLeaveEvent(static_cast<QHoverEvent*>(ev));
+ break;
+ case QEvent::HoverMove:
+ hoverMoveEvent(static_cast<QHoverEvent*>(ev));
+ break;
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ d->deliverKeyEvent(static_cast<QKeyEvent*>(ev));
+ break;
+ case QEvent::FocusIn:
+ focusInEvent(static_cast<QFocusEvent*>(ev));
+ break;
+ case QEvent::FocusOut:
+ focusOutEvent(static_cast<QFocusEvent*>(ev));
+ break;
+ case QEvent::MouseMove:
+ mouseMoveEvent(static_cast<QMouseEvent*>(ev));
+ break;
+ case QEvent::MouseButtonPress:
+ mousePressEvent(static_cast<QMouseEvent*>(ev));
+ break;
+ case QEvent::MouseButtonRelease:
+ mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
+ break;
+ case QEvent::MouseButtonDblClick:
+ mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
+ break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ wheelEvent(static_cast<QWheelEvent*>(ev));
+ break;
+#endif
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::DragEnter:
+ dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
+ break;
+ case QEvent::DragLeave:
+ dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
+ break;
+ case QEvent::DragMove:
+ dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
+ break;
+ case QEvent::Drop:
+ dropEvent(static_cast<QDropEvent*>(ev));
+ break;
+#endif // QT_NO_DRAGANDDROP
+ default:
+ return QObject::event(ev);
}
- return QObject::event(ev);
+
+ return true;
}
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 2500a2d33a..2b08cc2598 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
class QQuickItem;
class QQuickTransformPrivate;
-class QQuickTransform : public QObject
+class Q_QUICK_EXPORT QQuickTransform : public QObject
{
Q_OBJECT
public:
@@ -141,7 +141,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PROPERTY(QQmlListProperty<QQuickTransform> transform READ transform DESIGNABLE false FINAL)
Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged)
- Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged)
+ Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged RESET resetAntialiasing)
Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged)
Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged)
@@ -172,7 +172,8 @@ public:
ItemParentHasChanged, // value.item
ItemOpacityHasChanged, // value.realValue
ItemActiveFocusHasChanged, // value.boolValue
- ItemRotationHasChanged // value.realValue
+ ItemRotationHasChanged, // value.realValue
+ ItemAntialiasingHasChanged // value.boolValue
};
union ItemChangeData {
@@ -267,6 +268,7 @@ public:
bool antialiasing() const;
void setAntialiasing(bool);
+ void resetAntialiasing();
Flags flags() const;
void setFlag(Flag flag, bool enabled = true);
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 44eabcf0d5..96cb9e8843 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -422,6 +422,8 @@ public:
bool hasCursor:1;
// Bit 32
bool activeFocusOnTab:1;
+ bool implicitAntialiasing:1;
+ bool antialiasingValid:1;
enum DirtyType {
TransformOrigin = 0x00000001,
@@ -521,6 +523,8 @@ public:
virtual void implicitWidthChanged();
virtual void implicitHeightChanged();
+ void setImplicitAntialiasing(bool antialiasing);
+
void resolveLayoutMirror();
void setImplicitLayoutMirror(bool mirror, bool inherit);
void setLayoutMirror(bool mirror);
@@ -540,16 +544,6 @@ public:
#ifndef QT_NO_IM
void deliverInputMethodEvent(QInputMethodEvent *);
#endif
- void deliverFocusEvent(QFocusEvent *);
- void deliverMouseEvent(QMouseEvent *);
-#ifndef QT_NO_WHEELEVENT
- void deliverWheelEvent(QWheelEvent *);
-#endif
- void deliverTouchEvent(QTouchEvent *);
- void deliverHoverEvent(QHoverEvent *);
-#ifndef QT_NO_DRAGANDDROP
- void deliverDragEvent(QEvent *);
-#endif
bool calcEffectiveVisible() const;
bool setEffectiveVisibleRecur(bool);
@@ -589,6 +583,9 @@ public:
virtual void mirrorChange() {}
void incrementCursorCount(int delta);
+
+ // recursive helper to let a visual parent mark its visual children
+ void markObjects(QV4::ExecutionEngine *e);
};
/*
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index a5b78b28e1..c9c8eeace3 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -184,6 +184,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickTranslate>(uri,major,minor,"Translate");
qmlRegisterType<QQuickRotation>(uri,major,minor,"Rotation");
qmlRegisterType<QQuickScale>(uri,major,minor,"Scale");
+ qmlRegisterType<QQuickMatrix4x4>(uri,2,4,"Matrix4x4");
qmlRegisterType<QQuickText>(uri,major,minor,"Text");
qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit");
qmlRegisterType<QQuickTextEdit,1>(uri,2,1,"TextEdit");
@@ -261,12 +262,17 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickItem, 1>(uri, 2, 1,"Item");
qmlRegisterType<QQuickGrid, 1>(uri, 2, 1, "Grid");
qmlRegisterUncreatableType<QQuickItemView, 1>(uri, 2, 1, "ItemView", QQuickItemView::tr("ItemView is an abstract base class"));
+ qmlRegisterUncreatableType<QQuickItemView, 2>(uri, 2, 3, "ItemView", QQuickItemView::tr("ItemView is an abstract base class"));
qmlRegisterType<QQuickListView, 1>(uri, 2, 1, "ListView");
qmlRegisterType<QQuickGridView, 1>(uri, 2, 1, "GridView");
qmlRegisterType<QQuickTextEdit, 1>(uri, 2, 1, "TextEdit");
qmlRegisterType<QQuickText, 2>(uri, 2, 2, "Text");
qmlRegisterType<QQuickTextEdit, 2>(uri, 2, 2, "TextEdit");
+
+ qmlRegisterType<QQuickText, 3>(uri, 2, 3, "Text");
+ qmlRegisterType<QQuickTextEdit, 3>(uri, 2, 3, "TextEdit");
+ qmlRegisterType<QQuickImage, 1>(uri, 2, 3,"Image");
}
static void initResources()
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index d6cedbb78d..30d0619f7a 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -460,6 +460,41 @@ void QQuickItemView::setCacheBuffer(int b)
}
}
+int QQuickItemView::displayMarginBeginning() const
+{
+ Q_D(const QQuickItemView);
+ return d->displayMarginBeginning;
+}
+
+void QQuickItemView::setDisplayMarginBeginning(int margin)
+{
+ Q_D(QQuickItemView);
+ if (d->displayMarginBeginning != margin) {
+ d->displayMarginBeginning = margin;
+ if (isComponentComplete()) {
+ d->refillOrLayout();
+ }
+ emit displayMarginBeginningChanged();
+ }
+}
+
+int QQuickItemView::displayMarginEnd() const
+{
+ Q_D(const QQuickItemView);
+ return d->displayMarginEnd;
+}
+
+void QQuickItemView::setDisplayMarginEnd(int margin)
+{
+ Q_D(QQuickItemView);
+ if (d->displayMarginEnd != margin) {
+ d->displayMarginEnd = margin;
+ if (isComponentComplete()) {
+ d->refillOrLayout();
+ }
+ emit displayMarginEndChanged();
+ }
+}
Qt::LayoutDirection QQuickItemView::layoutDirection() const
{
@@ -1444,6 +1479,7 @@ void QQuickItemView::componentComplete()
QQuickItemViewPrivate::QQuickItemViewPrivate()
: itemCount(0)
, buffer(QML_VIEW_DEFAULTCACHEBUFFER), bufferMode(BufferBefore | BufferAfter)
+ , displayMarginBeginning(0), displayMarginEnd(0)
, layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom)
, moveReason(Other)
, visibleIndex(0)
@@ -1683,9 +1719,9 @@ void QQuickItemViewPrivate::refill()
{
qreal s = qMax(size(), qreal(0.));
if (isContentFlowReversed())
- refill(-position()-s, -position());
+ refill(-position()-displayMarginBeginning-s, -position()+displayMarginEnd);
else
- refill(position(), position()+s);
+ refill(position()-displayMarginBeginning, position()+displayMarginEnd+s);
}
void QQuickItemViewPrivate::refill(qreal from, qreal to)
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 17d150f480..ad026a3152 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -63,6 +63,8 @@ class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable
Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+ Q_PROPERTY(int displayMarginBeginning READ displayMarginBeginning WRITE setDisplayMarginBeginning NOTIFY displayMarginBeginningChanged REVISION 2)
+ Q_PROPERTY(int displayMarginEnd READ displayMarginEnd WRITE setDisplayMarginEnd NOTIFY displayMarginEndChanged REVISION 2)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
@@ -133,6 +135,12 @@ public:
int cacheBuffer() const;
void setCacheBuffer(int);
+ int displayMarginBeginning() const;
+ void setDisplayMarginBeginning(int);
+
+ int displayMarginEnd() const;
+ void setDisplayMarginEnd(int);
+
Qt::LayoutDirection layoutDirection() const;
void setLayoutDirection(Qt::LayoutDirection);
Qt::LayoutDirection effectiveLayoutDirection() const;
@@ -218,6 +226,8 @@ Q_SIGNALS:
void keyNavigationWrapsChanged();
void cacheBufferChanged();
+ void displayMarginBeginningChanged();
+ void displayMarginEndChanged();
void layoutDirectionChanged();
void effectiveLayoutDirectionChanged();
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index e0f08fd50f..af7c23c02e 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -257,6 +257,8 @@ public:
int itemCount;
int buffer;
int bufferMode;
+ int displayMarginBeginning;
+ int displayMarginEnd;
Qt::LayoutDirection layoutDirection;
QQuickItemView::VerticalLayoutDirection verticalLayoutDirection;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 06749be819..2dd61e386f 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -777,8 +777,8 @@ void QQuickListViewPrivate::visibleItemsChanged()
void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex)
{
if (!visibleItems.isEmpty()) {
- const qreal from = isContentFlowReversed() ? -position() - size() : position();
- const qreal to = isContentFlowReversed() ? -position() : position() + size();
+ const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning;
+ const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd;
FxViewItem *firstItem = *visibleItems.constBegin();
bool fixedCurrent = currentItem && firstItem->item == currentItem->item;
@@ -2145,8 +2145,33 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation)
of additional memory usage. It is not a substitute for creating efficient
delegates; the fewer objects and bindings in a delegate, the faster a view can be
scrolled.
+
+ The cacheBuffer operates outside of any display margins specified by
+ displayMarginBeginning or displayMarginEnd.
*/
+/*!
+ \qmlproperty int QtQuick::ListView::displayMarginBeginning
+ \qmlproperty int QtQuick::ListView::displayMarginEnd
+ \since QtQuick 2.3
+
+ This property allows delegates to be displayed outside of the view geometry.
+
+ If this value is non-zero, the view will create extra delegates before the
+ start of the view, or after the end. The view will create as many delegates
+ as it can fit into the pixel size specified.
+
+ For example, if in a vertical view the delegate is 20 pixels high and
+ \c displayMarginBeginning and \c displayMarginEnd are both set to 40,
+ then 2 delegates above and 2 delegates below will be created and shown.
+
+ The default value is 0.
+
+ This property is meant for allowing certain UI configurations,
+ and not as a performance optimization. If you wish to create delegates
+ outside of the view geometry for performance reasons, you probably
+ want to use the cacheBuffer property instead.
+*/
/*!
\qmlpropertygroup QtQuick::ListView::section
@@ -2703,8 +2728,8 @@ void QQuickListView::viewportMoved(Qt::Orientations orient)
d->refillOrLayout();
// Set visibility of items to eliminate cost of items outside the visible area.
- qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
- qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
+ qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
+ qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
@@ -2910,7 +2935,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
// there are no visible items except items marked for removal
index = visibleItems.count();
} else if (visibleItems.at(i)->index + 1 == modelIndex
- && visibleItems.at(i)->endPosition() <= buffer+tempPos+size()) {
+ && visibleItems.at(i)->endPosition() <= buffer+displayMarginEnd+tempPos+size()) {
// Special case of appending an item to the model.
index = visibleItems.count();
} else {
@@ -2939,7 +2964,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
// Insert items before the visible item.
int insertionIdx = index;
int i = 0;
- int from = tempPos - buffer;
+ int from = tempPos - displayMarginBeginning - buffer;
for (i = count-1; i >= 0; --i) {
if (pos > from && insertionIdx < visibleIndex) {
@@ -2970,7 +2995,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
}
} else {
int i = 0;
- int to = buffer+tempPos+size();
+ int to = buffer+displayMarginEnd+tempPos+size();
for (i = 0; i < count && pos <= to; ++i) {
FxViewItem *item = 0;
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 32c271222d..5783418619 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -58,7 +58,7 @@
#include "qquickitemchangelistener_p.h"
#include <qqmlincubator.h>
-#include <private/qv4value_p.h>
+#include <private/qv4value_inl_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 7a4b359d91..f07571d3cc 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -49,6 +49,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qevent.h>
+#include <QtGui/qstylehints.h>
#include <float.h>
@@ -56,8 +57,6 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
-static const int PressAndHoldDelay = 800;
-
QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
: enabled(true), hovered(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
@@ -627,7 +626,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
#endif
setHovered(true);
d->startScene = event->windowPos();
- d->pressAndHoldTimer.start(PressAndHoldDelay, this);
+ d->pressAndHoldTimer.start(qApp->styleHints()->mousePressAndHoldInterval(), this);
setKeepMouseGrab(d->stealMouse);
event->setAccepted(setPressed(event->button(), true));
}
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index e0eb641528..973f6efdcc 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -43,6 +43,7 @@
#include <QtQuick/qquickwindow.h>
#include <private/qsgadaptationlayer_p.h>
#include <private/qquickitem_p.h>
+#include <private/qguiapplication_p.h>
#include <QEvent>
#include <QMouseEvent>
#include <math.h>
@@ -677,6 +678,10 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers());
mouseEvent.setAccepted(false);
+ QGuiApplicationPrivate::setMouseEventCapsAndVelocity(&mouseEvent,
+ QGuiApplicationPrivate::mouseEventCaps(event),
+ QGuiApplicationPrivate::mouseEventVelocity(event));
+ QGuiApplicationPrivate::setMouseEventSource(&mouseEvent, Qt::MouseEventSynthesizedByQt);
switch (mouseEvent.type()) {
case QEvent::MouseMove:
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index e50f772e89..8d9f6b9d4a 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -333,6 +333,16 @@ void QQuickRectangle::doUpdate()
}
/*!
+ \qmlproperty bool QtQuick::Rectangle::antialiasing
+
+ Used to decide if the Rectangle should use antialiasing or not.
+ \l {Antialiasing} provides information on the performance implications
+ of this property.
+
+ The default is true for Rectangles with a radius, and false otherwise.
+*/
+
+/*!
\qmlpropertygroup QtQuick::Rectangle::border
\qmlproperty int QtQuick::Rectangle::border.width
\qmlproperty color QtQuick::Rectangle::border.color
@@ -421,6 +431,8 @@ void QQuickRectangle::setRadius(qreal radius)
return;
d->radius = radius;
+ d->setImplicitAntialiasing(radius != 0.0);
+
update();
emit radiusChanged();
}
@@ -488,7 +500,7 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
}
rectangle->setRadius(d->radius);
- rectangle->setAntialiasing(d->antialiasing || d->radius > 0);
+ rectangle->setAntialiasing(antialiasing());
QGradientStops stops;
if (d->gradient) {
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
new file mode 100644
index 0000000000..faee1358ae
--- /dev/null
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickrendercontrol_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTime>
+#include <QtCore/private/qabstractanimation_p.h>
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
+#include <QtQml/private/qqmlglobal_p.h>
+
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qqmlprofilerservice_p.h>
+#include <QtCore/private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+class QQuickRenderControlPrivate : public QObjectPrivate
+{
+public:
+ QQuickRenderControlPrivate()
+ : window(0)
+ {
+ sg = QSGContext::createDefaultContext();
+ rc = new QSGRenderContext(sg);
+ }
+
+ ~QQuickRenderControlPrivate()
+ {
+ delete rc;
+ delete sg;
+ }
+
+ QQuickWindow *window;
+ QSGContext *sg;
+ QSGRenderContext *rc;
+};
+
+/*!
+ \class QQuickRenderControl
+ \brief The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph.
+
+ \internal
+
+ \inmodule QtQuick
+*/
+
+QQuickRenderControl::QQuickRenderControl()
+ : QObject(*(new QQuickRenderControlPrivate), 0)
+{
+}
+
+QQuickRenderControl::~QQuickRenderControl()
+{
+}
+
+void QQuickRenderControl::windowDestroyed()
+{
+ Q_D(QQuickRenderControl);
+ if (d->window == 0) {
+ d->rc->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+}
+
+void QQuickRenderControl::initialize(QOpenGLContext *gl)
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window)
+ return;
+
+ // It is the caller's responsiblity to make a context/surface current.
+ // It cannot be done here since the surface to use may not be the
+ // surface belonging to window. In fact window may not have a native
+ // window/surface at all.
+
+ QQuickWindowPrivate::get(d->window)->context->initialize(gl);
+}
+
+void QQuickRenderControl::invalidate()
+{
+ Q_D(QQuickRenderControl);
+ QQuickWindowPrivate::get(d->window)->context->invalidate();
+}
+
+/*!
+ This function should be called as late as possible before
+ sync(). In a threaded scenario, rendering can happen in parallel with this function.
+ */
+void QQuickRenderControl::polishItems()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window || !QQuickWindowPrivate::get(d->window)->isRenderable())
+ return;
+
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->polishItems();
+}
+
+/*!
+ Synchronize GUI and scenegraph. Returns true if the scene graph was changed.
+
+ This function is a synchronization point. Rendering can not happen in parallel.
+ */
+bool QQuickRenderControl::sync()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window || !QQuickWindowPrivate::get(d->window)->isRenderable())
+ return false;
+
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->syncSceneGraph();
+
+ // TODO: find out if the sync actually caused a scenegraph update.
+ return true;
+}
+
+/*!
+ Render the scenegraph using the current context.
+ */
+void QQuickRenderControl::render()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window || !QQuickWindowPrivate::get(d->window)->isRenderable())
+ return;
+
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->renderSceneGraph(d->window->size());
+}
+
+
+/*!
+ \fn void QQuickRenderControl::renderRequested()
+
+ This signal is emitted when the scene graph needs to be rendered. It is not necessary to call sync().
+*/
+
+/*!
+ \fn void QQuickRenderControl::sceneChanged()
+
+ This signal is emitted when the scene graph is updated, meaning that
+ polishItems() and sync() needs to be called. If sync() returns
+ true, then render() needs to be called.
+*/
+
+
+QImage QQuickRenderControl::grab()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window)
+ return QImage();
+
+ render();
+ QImage grabContent = qt_gl_read_framebuffer(d->window->size(), false, false);
+ return grabContent;
+}
+
+QSGContext *QQuickRenderControl::sceneGraphContext() const
+{
+ Q_D(const QQuickRenderControl);
+ return d->sg;
+}
+
+QSGRenderContext *QQuickRenderControl::renderContext(QSGContext *) const
+{
+ Q_D(const QQuickRenderControl);
+ return d->rc;
+}
+
+void QQuickRenderControl::setWindow(QQuickWindow *window)
+{
+ Q_D(QQuickRenderControl);
+ d->window = window;
+}
+
+QQuickWindow *QQuickRenderControl::window() const
+{
+ Q_D(const QQuickRenderControl);
+ return d->window;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h
new file mode 100644
index 0000000000..7255a9ae0b
--- /dev/null
+++ b/src/quick/items/qquickrendercontrol_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKRENDERCONTROL_P_H
+#define QQUICKRENDERCONTROL_P_H
+
+#include <QtGui/QImage>
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWindow;
+class QSGContext;
+class QSGRenderContext;
+class QAnimationDriver;
+class QOpenGLContext;
+class QQuickRenderControlPrivate;
+
+class Q_QUICK_PRIVATE_EXPORT QQuickRenderControl : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickRenderControl)
+public:
+ QQuickRenderControl();
+ ~QQuickRenderControl();
+
+ QQuickWindow *window() const;
+
+ void windowDestroyed();
+
+ void initialize(QOpenGLContext *gl);
+ void invalidate();
+ void polishItems();
+ void render();
+ bool sync();
+
+ QImage grab();
+
+Q_SIGNALS:
+ void renderRequested();
+ void sceneChanged();
+
+private:
+ friend class QQuickWindowPrivate;
+ friend class QQuickWindow;
+ void setWindow(QQuickWindow *window);
+ inline void update() { /*emit*/ renderRequested(); }
+ inline void maybeUpdate() { /*emit*/ sceneChanged(); }
+
+ QSGContext *sceneGraphContext() const;
+ QSGRenderContext *renderContext(QSGContext *) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKRENDERCONTROL_P_H
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index 410f18e767..54c7527eec 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -323,7 +323,7 @@ void QQuickScreenAttached::screenChanged(QScreen *screen)
this, SIGNAL(orientationChanged()));
connect(screen, SIGNAL(primaryOrientationChanged(Qt::ScreenOrientation)),
this, SIGNAL(primaryOrientationChanged()));
- connect(screen, SIGNAL(virtualGeometryChanged(const QRect &)),
+ connect(screen, SIGNAL(virtualGeometryChanged(QRect)),
this, SIGNAL(desktopGeometryChanged()));
connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)),
this, SIGNAL(logicalPixelDensityChanged()));
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index 9a20703f18..e57b7abddc 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -478,6 +478,19 @@ void QQuickShaderEffectCommon::sourceDestroyed(QObject *object)
}
}
+static bool qquick_uniqueInUniformData(QQuickItem *source, const QVector<QQuickShaderEffectMaterial::UniformData> *uniformData, int typeToSkip, int indexToSkip)
+{
+ for (int s=0; s<QQuickShaderEffectMaterialKey::ShaderTypeCount; ++s) {
+ for (int i=0; i<uniformData[s].size(); ++i) {
+ if (s == typeToSkip && i == indexToSkip)
+ continue;
+ const QQuickShaderEffectMaterial::UniformData &d = uniformData[s][i];
+ if (d.specialType == QQuickShaderEffectMaterial::UniformData::Sampler && qvariant_cast<QObject *>(d.value) == source)
+ return false;
+ }
+ }
+ return true;
+}
void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
bool *textureProviderChanged)
@@ -490,7 +503,13 @@ void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
if (source) {
if (item->window())
QQuickItemPrivate::get(source)->derefWindow();
- QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
+
+ // QObject::disconnect() will disconnect all matching connections. If the same
+ // source has been attached to two separate samplers, then changing one of them
+ // would trigger both to be disconnected. Without the connection we'll end up
+ // with a dangling pointer in the uniformData.
+ if (qquick_uniqueInUniformData(source, uniformData, shaderType, index))
+ QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
}
d.value = item->property(d.name.constData());
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index c9dee9a986..287173957f 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -88,6 +88,7 @@ QQuickTextPrivate::QQuickTextPrivate()
, truncated(false), hAlignImplicit(true), rightToLeftText(false)
, layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false)
{
+ implicitAntialiasing = true;
}
QQuickTextPrivate::ExtraData::ExtraData()
@@ -114,6 +115,7 @@ QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuic
{
setUndoRedoEnabled(false);
documentLayout()->registerHandler(QTextFormat::ImageObject, this);
+ connect(this, SIGNAL(baseUrlChanged(QUrl)), this, SLOT(reset()));
}
QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
@@ -125,14 +127,13 @@ QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
{
QQmlContext *context = qmlContext(parent());
- QUrl url = m_baseUrl.resolved(name);
if (type == QTextDocument::ImageResource) {
- QQuickPixmap *p = loadPixmap(context, url);
+ QQuickPixmap *p = loadPixmap(context, name);
return p->image();
}
- return QTextDocument::loadResource(type,url); // The *resolved* URL
+ return QTextDocument::loadResource(type, name);
}
void QQuickTextDocumentWithImageResources::requestFinished()
@@ -144,14 +145,6 @@ void QQuickTextDocumentWithImageResources::requestFinished()
}
}
-void QQuickTextDocumentWithImageResources::clear()
-{
- clearResources();
-
- QTextDocument::clear();
-}
-
-
QSizeF QQuickTextDocumentWithImageResources::intrinsicSize(
QTextDocument *, int, const QTextFormat &format)
{
@@ -166,7 +159,7 @@ QSizeF QQuickTextDocumentWithImageResources::intrinsicSize(
QSizeF size(width, height);
if (!hasWidth || !hasHeight) {
QQmlContext *context = qmlContext(parent());
- QUrl url = m_baseUrl.resolved(QUrl(imageFormat.name()));
+ QUrl url = baseUrl().resolved(QUrl(imageFormat.name()));
QQuickPixmap *p = loadPixmap(context, url);
if (!p->isReady()) {
@@ -204,19 +197,16 @@ void QQuickTextDocumentWithImageResources::drawObject(
QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format)
{
QQmlContext *context = qmlContext(parent());
- QUrl url = m_baseUrl.resolved(QUrl(format.name()));
+ QUrl url = baseUrl().resolved(QUrl(format.name()));
QQuickPixmap *p = loadPixmap(context, url);
return p->image();
}
-void QQuickTextDocumentWithImageResources::setBaseUrl(const QUrl &url, bool clear)
+void QQuickTextDocumentWithImageResources::reset()
{
- m_baseUrl = url;
- if (clear) {
- clearResources();
- markContentsDirty(0, characterCount());
- }
+ clearResources();
+ markContentsDirty(0, characterCount());
}
QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap(
@@ -297,6 +287,15 @@ qreal QQuickTextPrivate::getImplicitHeight() const
return implicitHeight;
}
+/*!
+ \qmlproperty bool QtQuick::Text::antialiasing
+
+ Used to decide if the Text should use antialiasing or not. Only Text
+ with renderType of Text.NativeRendering can disable antialiasing.
+
+ The default is true.
+*/
+
void QQuickText::q_imagesLoaded()
{
Q_D(QQuickText);
@@ -620,8 +619,9 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,
textLine->setHeight(0);
textLine->setLineOffset(lineOffset);
- // use the text item's width by default if it has one and wrap is on
- if (q->widthValid() && q->wrapMode() != QQuickText::NoWrap)
+ // use the text item's width by default if it has one and wrap is on or text must be aligned
+ if (q->widthValid() && (q->wrapMode() != QQuickText::NoWrap ||
+ q->effectiveHAlign() != QQuickText::AlignLeft))
textLine->setWidth(q->width());
else
textLine->setWidth(INT_MAX);
@@ -959,7 +959,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
// If the horizontal alignment is not left and the width was not valid we need to relayout
// now that we know the maximum line width.
- if (!implicitWidthValid && lineCount > 1 && q->effectiveHAlign() != QQuickText::AlignLeft) {
+ if (!implicitWidthValid && unwrappedLineCount > 1 && q->effectiveHAlign() != QQuickText::AlignLeft) {
widthExceeded = false;
heightExceeded = false;
continue;
@@ -1415,6 +1415,9 @@ void QQuickText::setFont(const QFont &font)
QFont oldFont = d->font;
d->font = font;
+ if (!antialiasing())
+ d->font.setStyleStrategy(QFont::NoAntialias);
+
if (d->font.pointSizeF() != -1) {
// 0.5pt resolution
qreal size = qRound(d->font.pointSizeF()*2.0);
@@ -1434,6 +1437,21 @@ void QQuickText::setFont(const QFont &font)
emit fontChanged(d->sourceFont);
}
+void QQuickText::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ Q_D(QQuickText);
+ Q_UNUSED(value);
+ if (change == ItemAntialiasingHasChanged) {
+ if (!antialiasing())
+ d->font.setStyleStrategy(QFont::NoAntialias);
+ else
+ d->font.setStyleStrategy(QFont::PreferAntialias);
+ d->implicitWidthValid = false;
+ d->implicitHeightValid = false;
+ d->updateLayout();
+ }
+}
+
/*!
\qmlproperty string QtQuick::Text::text
@@ -2198,7 +2216,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
else
node = static_cast<QQuickTextNode *>(oldNode);
- node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
+ node->setUseNativeRenderer(d->renderType == NativeRendering);
node->deleteContent();
node->setMatrix(QMatrix4x4());
@@ -2555,7 +2573,7 @@ bool QQuickTextPrivate::isLinkHoveredConnected()
text. The link must be in rich text or HTML format and the \a link
string provides access to the particular link.
- \sa hoveredLink
+ \sa hoveredLink, linkAt()
*/
/*!
@@ -2566,7 +2584,7 @@ bool QQuickTextPrivate::isLinkHoveredConnected()
embedded in the text. The link must be in rich text or HTML format
and the \a hoveredLink string provides access to the particular link.
- \sa onLinkHovered
+ \sa onLinkHovered, linkAt()
*/
QString QQuickText::hoveredLink() const
@@ -2635,9 +2653,6 @@ void QQuickText::hoverLeaveEvent(QHoverEvent *event)
not require advanced features such as transformation of the text. Using such features in
combination with the NativeRendering render type will lend poor and sometimes pixelated
results.
-
- On HighDpi "retina" displays and mobile and embedded platforms, this property is ignored
- and QtRendering is always used.
*/
QQuickText::RenderType QQuickText::renderType() const
{
@@ -2669,4 +2684,19 @@ void QQuickText::doLayout()
d->updateSize();
}
+/*!
+ \qmlmethod QtQuick::Text::linkAt(real x, real y)
+ \since 5.3
+
+ Returns the link string at point \a x, \a y in content coordinates,
+ or an empty string if no link exists at that point.
+
+ \sa hoveredLink
+*/
+QString QQuickText::linkAt(qreal x, qreal y) const
+{
+ Q_D(const QQuickText);
+ return d->anchorAt(QPointF(x, y));
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 489ef58344..44bd5aa9b0 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -210,6 +210,8 @@ public:
QString hoveredLink() const;
+ Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const;
+
Q_SIGNALS:
void textChanged(const QString &text);
void linkActivated(const QString &link);
@@ -241,6 +243,7 @@ Q_SIGNALS:
protected:
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
+ virtual void itemChange(ItemChange change, const ItemChangeData &value);
virtual void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry);
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 1f6cd3eab5..12113f416c 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -195,16 +195,13 @@ public:
void setText(const QString &);
int resourcesLoading() const { return outstanding; }
- void clearResources();
-
- void clear();
-
QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format);
void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format);
QImage image(const QTextImageFormat &format);
- void setBaseUrl(const QUrl &url, bool clear = true);
+public Q_SLOTS:
+ void clearResources();
Q_SIGNALS:
void imagesLoaded();
@@ -215,11 +212,11 @@ protected:
QQuickPixmap *loadPixmap(QQmlContext *context, const QUrl &name);
private Q_SLOTS:
+ void reset();
void requestFinished();
private:
QHash<QUrl, QQuickPixmap *> m_resources;
- QUrl m_baseUrl;
int outstanding;
static QSet<QUrl> errors;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index ffc732621d..810a47cfa8 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -418,9 +418,6 @@ void QQuickTextEdit::setTextFormat(TextFormat format)
not require advanced features such as transformation of the text. Using such features in
combination with the NativeRendering render type will lend poor and sometimes pixelated
results.
-
- On HighDpi "retina" displays and mobile and embedded platforms, this property is ignored
- and QtRendering is always used.
*/
QQuickTextEdit::RenderType QQuickTextEdit::renderType() const
{
@@ -830,7 +827,7 @@ void QQuickTextEdit::setBaseUrl(const QUrl &url)
if (baseUrl() != url) {
d->baseUrl = url;
- d->document->setBaseUrl(url, d->richText);
+ d->document->setBaseUrl(url);
emit baseUrlChanged();
}
}
@@ -1281,7 +1278,7 @@ void QQuickTextEdit::componentComplete()
Q_D(QQuickTextEdit);
QQuickImplicitSizeItem::componentComplete();
- d->document->setBaseUrl(baseUrl(), d->richText);
+ d->document->setBaseUrl(baseUrl());
#ifndef QT_NO_TEXTHTML_PARSER
if (d->richText)
d->control->setHtml(d->text);
@@ -2371,7 +2368,7 @@ QQuickTextNode *QQuickTextEditPrivate::createTextNode()
{
Q_Q(QQuickTextEdit);
QQuickTextNode* node = new QQuickTextNode(q);
- node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering && window->devicePixelRatio() <= 1);
+ node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering);
node->initEngine(color, selectedTextColor, selectionColor);
return node;
}
@@ -2518,7 +2515,7 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected()
The link must be in rich text or HTML format and the
\a link string provides access to the particular link.
- \sa hoveredLink
+ \sa hoveredLink, linkAt()
*/
/*!
@@ -2529,7 +2526,7 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected()
embedded in the text. The link must be in rich text or HTML format
and the link string provides access to the particular link.
- \sa onLinkHovered
+ \sa onLinkHovered, linkAt()
*/
QString QQuickTextEdit::hoveredLink() const
@@ -2602,4 +2599,19 @@ void QQuickTextEdit::append(const QString &text)
d->control->updateCursorRectangle(false);
}
+/*!
+ \qmlmethod QtQuick::TextEdit::linkAt(real x, real y)
+ \since 5.3
+
+ Returns the link string at point \a x, \a y in content coordinates,
+ or an empty string if no link exists at that point.
+
+ \sa hoveredLink
+*/
+QString QQuickTextEdit::linkAt(qreal x, qreal y) const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->anchorAt(QPointF(x, y));
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index 8057f76be5..b84552d255 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -258,6 +258,8 @@ public:
QString hoveredLink() const;
+ Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const;
+
Q_SIGNALS:
void textChanged();
void contentSizeChanged();
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 1dd1dfa57e..ad79f0eadf 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -155,9 +155,6 @@ void QQuickTextInput::setText(const QString &s)
not require advanced features such as transformation of the text. Using such features in
combination with the NativeRendering render type will lend poor and sometimes pixelated
results.
-
- On HighDpi "retina" displays and mobile and embedded platforms, this property is ignored
- and QtRendering is always used.
*/
QQuickTextInput::RenderType QQuickTextInput::renderType() const
{
@@ -1713,6 +1710,8 @@ void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
if (!d->inLayout) {
if (newGeometry.width() != oldGeometry.width())
d->updateLayout();
+ else if (newGeometry.height() != oldGeometry.height() && d->vAlign != QQuickTextInput::AlignTop)
+ d->updateBaselineOffset();
updateCursorRectangle();
}
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
@@ -1862,7 +1861,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
}
}
} else {
- node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
+ node->setUseNativeRenderer(d->renderType == NativeRendering);
node->deleteContent();
node->setMatrix(QMatrix4x4());
@@ -2858,10 +2857,35 @@ void QQuickTextInputPrivate::updateLayout()
else
q->setImplicitHeight(height);
+ updateBaselineOffset();
+
if (previousSize != contentSize)
emit q->contentSizeChanged();
}
+/*!
+ \internal
+ \brief QQuickTextInputPrivate::updateBaselineOffset
+
+ Assumes contentSize.height() is already calculated.
+ */
+void QQuickTextInputPrivate::updateBaselineOffset()
+{
+ Q_Q(QQuickTextInput);
+ if (!q->isComponentComplete())
+ return;
+ QFontMetricsF fm(font);
+ qreal yoff = 0;
+ if (q->heightValid()) {
+ const qreal surplusHeight = q->height() - contentSize.height();
+ if (vAlign == QQuickTextInput::AlignBottom)
+ yoff = surplusHeight;
+ else if (vAlign == QQuickTextInput::AlignVCenter)
+ yoff = surplusHeight/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+}
+
#ifndef QT_NO_CLIPBOARD
/*!
\internal
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 240fc7a599..21bd1bd6d7 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -423,6 +423,7 @@ public:
void setCursorBlinkPeriod(int msec);
void updateLayout();
+ void updateBaselineOffset();
qreal getImplicitWidth() const;
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 18ee1a479d..1133636a74 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -144,11 +144,9 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun
{
QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext();
QRawFont font = glyphs.rawFont();
- bool smoothScalable = QFontDatabase().isSmoothlyScalable(font.familyName(),
- font.styleName());
- QSGGlyphNode *node = m_useNativeRenderer || !smoothScalable
- ? sg->sceneGraphContext()->createNativeGlyphNode(sg)
- : sg->sceneGraphContext()->createGlyphNode(sg);
+ bool smoothScalable = QFontDatabase().isSmoothlyScalable(font.familyName(), font.styleName());
+ bool preferNativeGlyphNode = m_useNativeRenderer || !smoothScalable;
+ QSGGlyphNode *node = sg->sceneGraphContext()->createGlyphNode(sg, preferNativeGlyphNode);
node->setOwnerElement(m_ownerElement);
node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs);
diff --git a/src/quick/items/qquicktranslate.cpp b/src/quick/items/qquicktranslate.cpp
index 20eb1dce5b..14f8c204f3 100644
--- a/src/quick/items/qquicktranslate.cpp
+++ b/src/quick/items/qquicktranslate.cpp
@@ -458,4 +458,79 @@ void QQuickRotation::applyTo(QMatrix4x4 *matrix) const
matrix->translate(-d->origin);
}
+class QQuickMatrix4x4Private : public QQuickTransformPrivate
+{
+public:
+ QQuickMatrix4x4Private()
+ : matrix() {}
+ QMatrix4x4 matrix;
+};
+
+/*!
+ \qmltype Matrix4x4
+ \instantiates QQuickMatrix4x4
+ \inqmlmodule QtQuick
+ \ingroup qtquick-visual-transforms
+ \brief Provides a way to apply a 4x4 tranformation matrix to an \l Item
+
+ The Matrix4x4 type provides a way to apply a transformation to an
+ \l Item through a 4x4 matrix.
+
+ It allows for a combination of rotation, scale, translatation and shearing
+ by using just one tranformation provided in a 4x4-matrix.
+
+ The following example rotates a Rectangle 45 degress (PI/4):
+
+ \qml
+ Rectangle {
+ width: 100
+ height: 100
+ color: "red"
+
+ transform: Matrix4x4 {
+ property real a: Math.PI / 4
+ matrix: Qt.matrix4x4(Math.cos(a), -Math.sin(a), 0, 0,
+ Math.sin(a), Math.cos(a), 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1)
+ }
+ }
+ \endqml
+*/
+QQuickMatrix4x4::QQuickMatrix4x4(QObject *parent)
+ : QQuickTransform(*new QQuickMatrix4x4Private, parent)
+{
+}
+
+QQuickMatrix4x4::~QQuickMatrix4x4()
+{
+}
+
+/*!
+ \qmlproperty QMatrix4x4 QtQuick::Matrix4x4::matrix
+
+ 4x4-matrix which will be used in the tranformation of an \l Item
+*/
+QMatrix4x4 QQuickMatrix4x4::matrix() const
+{
+ Q_D(const QQuickMatrix4x4);
+ return d->matrix;
+}
+
+void QQuickMatrix4x4::setMatrix(const QMatrix4x4 &matrix)
+{
+ Q_D(QQuickMatrix4x4);
+ if (d->matrix == matrix)
+ return;
+ d->matrix = matrix;
+ update();
+ emit matrixChanged();
+}
+
+void QQuickMatrix4x4::applyTo(QMatrix4x4 *matrix) const
+{
+ Q_D(const QQuickMatrix4x4);
+ *matrix *= d->matrix;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h
index d7843fe103..dd93275a28 100644
--- a/src/quick/items/qquicktranslate_p.h
+++ b/src/quick/items/qquicktranslate_p.h
@@ -148,6 +148,29 @@ private:
Q_DECLARE_PRIVATE(QQuickRotation)
};
+class QQuickMatrix4x4Private;
+class Q_AUTOTEST_EXPORT QQuickMatrix4x4 : public QQuickTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY matrixChanged)
+public:
+ QQuickMatrix4x4(QObject *parent = 0);
+ ~QQuickMatrix4x4();
+
+ QMatrix4x4 matrix() const;
+ void setMatrix(const QMatrix4x4& matrix);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void matrixChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickMatrix4x4)
+};
+
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTranslate)
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index d1fe489dcb..5c9ecb93dd 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -46,7 +46,7 @@
#include "qquickitem_p.h"
#include "qquickitemchangelistener_p.h"
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
#include <private/qqmlinspectorservice_p.h>
#include <private/qqmlmemoryprofiler_p.h>
@@ -56,6 +56,26 @@
QT_BEGIN_NAMESPACE
+DEFINE_OBJECT_VTABLE(QQuickRootItemMarker);
+
+QQuickRootItemMarker::QQuickRootItemMarker(QQuickViewPrivate *view)
+ : QV4::Object(QQmlEnginePrivate::getV4Engine(view->engine.data()))
+ , view(view)
+{
+ setVTable(staticVTable());
+}
+
+void QQuickRootItemMarker::markObjects(QV4::Managed *that, QV4::ExecutionEngine *e)
+{
+ QQuickItem *root = static_cast<QQuickRootItemMarker*>(that)->view->root;
+ if (root) {
+ QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root);
+ rootPrivate->markObjects(e);
+ }
+
+ QV4::Object::markObjects(that, e);
+}
+
void QQuickViewPrivate::init(QQmlEngine* e)
{
Q_Q(QQuickView);
@@ -68,6 +88,13 @@ void QQuickViewPrivate::init(QQmlEngine* e)
if (!engine.data()->incubationController())
engine.data()->setIncubationController(q->incubationController());
+ {
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine.data());
+ QV4::Scope scope(v4);
+ QV4::Scoped<QQuickRootItemMarker> v(scope, new (v4->memoryManager) QQuickRootItemMarker(this));
+ rootItemMarker = v;
+ }
+
if (QQmlDebugService::isDebuggingEnabled())
QQmlInspectorService::instance()->addView(q);
}
@@ -576,7 +603,7 @@ void QQuickView::resizeEvent(QResizeEvent *e)
/*! \reimp */
void QQuickView::keyPressEvent(QKeyEvent *e)
{
- QQmlProfilerService::addEvent(QQmlProfilerService::Key);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
QQuickWindow::keyPressEvent(e);
}
@@ -584,7 +611,7 @@ void QQuickView::keyPressEvent(QKeyEvent *e)
/*! \reimp */
void QQuickView::keyReleaseEvent(QKeyEvent *e)
{
- QQmlProfilerService::addEvent(QQmlProfilerService::Key);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
QQuickWindow::keyReleaseEvent(e);
}
@@ -592,7 +619,7 @@ void QQuickView::keyReleaseEvent(QKeyEvent *e)
/*! \reimp */
void QQuickView::mouseMoveEvent(QMouseEvent *e)
{
- QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
QQuickWindow::mouseMoveEvent(e);
}
@@ -600,7 +627,7 @@ void QQuickView::mouseMoveEvent(QMouseEvent *e)
/*! \reimp */
void QQuickView::mousePressEvent(QMouseEvent *e)
{
- QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
QQuickWindow::mousePressEvent(e);
}
@@ -608,7 +635,7 @@ void QQuickView::mousePressEvent(QMouseEvent *e)
/*! \reimp */
void QQuickView::mouseReleaseEvent(QMouseEvent *e)
{
- QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
QQuickWindow::mouseReleaseEvent(e);
}
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
index 170c93a6cf..74e40081e9 100644
--- a/src/quick/items/qquickview_p.h
+++ b/src/quick/items/qquickview_p.h
@@ -51,12 +51,17 @@
#include <QtCore/QWeakPointer>
#include <QtQml/qqmlengine.h>
+#include <private/qv4object_p.h>
#include "qquickwindow_p.h"
#include "qquickitemchangelistener_p.h"
QT_BEGIN_NAMESPACE
+namespace QV4 {
+struct ExecutionEngine;
+}
+
class QQmlContext;
class QQmlError;
class QQuickItem;
@@ -94,6 +99,23 @@ public:
QQuickView::ResizeMode resizeMode;
QSize initialSize;
QElapsedTimer frameTimer;
+ QV4::PersistentValue rootItemMarker;
+};
+
+struct QQuickRootItemMarker : public QV4::Object
+{
+ V4_OBJECT
+
+ QQuickRootItemMarker(QQuickViewPrivate *view);
+
+ static void destroy(Managed *that)
+ {
+ static_cast<QQuickRootItemMarker*>(that)->~QQuickRootItemMarker();
+ }
+
+ static void markObjects(Managed *that, QV4::ExecutionEngine *e);
+
+ QQuickViewPrivate *view;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 532021932f..014fb51572 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -51,6 +51,7 @@
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <private/qsgrenderloop_p.h>
+#include <private/qquickrendercontrol_p.h>
#include <private/qquickanimatorcontroller_p.h>
#include <private/qguiapplication_p.h>
@@ -210,25 +211,32 @@ QQuickRootItem::QQuickRootItem()
void QQuickWindow::exposeEvent(QExposeEvent *)
{
Q_D(QQuickWindow);
- d->windowManager->exposureChanged(this);
+ if (d->windowManager)
+ d->windowManager->exposureChanged(this);
}
/*! \reimp */
void QQuickWindow::resizeEvent(QResizeEvent *)
{
- d_func()->windowManager->resize(this);
+ Q_D(QQuickWindow);
+ if (d->windowManager)
+ d->windowManager->resize(this);
}
/*! \reimp */
void QQuickWindow::showEvent(QShowEvent *)
{
- d_func()->windowManager->show(this);
+ Q_D(QQuickWindow);
+ if (d->windowManager)
+ d->windowManager->show(this);
}
/*! \reimp */
void QQuickWindow::hideEvent(QHideEvent *)
{
- d_func()->windowManager->hide(this);
+ Q_D(QQuickWindow);
+ if (d->windowManager)
+ d->windowManager->hide(this);
}
/*! \reimp */
@@ -246,7 +254,6 @@ void QQuickWindow::focusInEvent(QFocusEvent *ev)
d->updateFocusItemTransform();
}
-
void QQuickWindowPrivate::polishItems()
{
int maxPolishCycles = 100000;
@@ -278,7 +285,10 @@ void QQuickWindowPrivate::polishItems()
void QQuickWindow::update()
{
Q_D(QQuickWindow);
- d->windowManager->update(this);
+ if (d->windowManager)
+ d->windowManager->update(this);
+ else
+ d->renderControl->update();
}
void forcePolishHelper(QQuickItem *item)
@@ -342,6 +352,7 @@ void QQuickWindowPrivate::syncSceneGraph()
mode |= QSGRenderer::ClearColorBuffer;
renderer->setClearMode(mode);
+ renderer->setCustomRenderMode(customRenderMode);
context->endSync();
}
@@ -350,6 +361,9 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
{
QML_MEMORY_SCOPE_STRING("SceneGraph");
Q_Q(QQuickWindow);
+ if (!renderer)
+ return;
+
animationController->advance();
emit q->beforeRendering();
int fboId = 0;
@@ -384,12 +398,14 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, context(0)
, renderer(0)
, windowManager(0)
+ , renderControl(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
, persistentGLContext(true)
, persistentSceneGraph(true)
, lastWheelEventAccepted(false)
, componentCompleted(true)
+ , forceRendering(false)
, renderTarget(0)
, renderTargetId(0)
, incubationController(0)
@@ -403,7 +419,7 @@ QQuickWindowPrivate::~QQuickWindowPrivate()
{
}
-void QQuickWindowPrivate::init(QQuickWindow *c)
+void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
{
q_ptr = c;
@@ -416,9 +432,25 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
contentItemPrivate->windowRefCount = 1;
contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
- windowManager = QSGRenderLoop::instance();
- QSGContext *sg = windowManager->sceneGraphContext();
- context = windowManager->createRenderContext(sg);
+ customRenderMode = qgetenv("QSG_VISUALIZE");
+ renderControl = control;
+ if (renderControl)
+ renderControl->setWindow(q);
+
+ if (!renderControl)
+ windowManager = QSGRenderLoop::instance();
+
+ Q_ASSERT(windowManager || renderControl);
+
+ QSGContext *sg;
+ if (renderControl) {
+ sg = renderControl->sceneGraphContext();
+ context = renderControl->renderContext(sg);
+ } else {
+ sg = windowManager->sceneGraphContext();
+ context = windowManager->createRenderContext(sg);
+ }
+
q->setSurfaceType(QWindow::OpenGLSurface);
q->setFormat(sg->defaultSurfaceFormat());
@@ -472,6 +504,7 @@ static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::Touc
transformedVelocity = transformMatrix.mapVector(p.velocity()).toVector2D();
}
QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, event->device()->capabilities(), transformedVelocity);
+ QGuiApplicationPrivate::setMouseEventSource(me, Qt::MouseEventSynthesizedByQt);
return me;
}
@@ -525,7 +558,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
item->grabMouse();
item->grabTouchPoints(QVector<int>() << touchMouseId);
- QQuickItemPrivate::get(item)->deliverMouseEvent(mousePress.data());
+ QCoreApplication::sendEvent(item, mousePress.data());
event->setAccepted(mousePress->isAccepted());
if (!mousePress->isAccepted()) {
touchMouseId = -1;
@@ -538,7 +571,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
if (mousePress->isAccepted() && checkIfDoubleClicked(event->timestamp())) {
QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item));
- QQuickItemPrivate::get(item)->deliverMouseEvent(mouseDoubleClick.data());
+ QCoreApplication::sendEvent(item, mouseDoubleClick.data());
event->setAccepted(mouseDoubleClick->isAccepted());
if (mouseDoubleClick->isAccepted()) {
return true;
@@ -559,7 +592,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
if (p.state() & Qt::TouchPointMoved) {
if (mouseGrabberItem) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, mouseGrabberItem));
- QQuickItemPrivate::get(item)->deliverMouseEvent(me.data());
+ QCoreApplication::sendEvent(item, me.data());
event->setAccepted(me->isAccepted());
if (me->isAccepted()) {
itemForTouchPointId[p.id()] = mouseGrabberItem; // N.B. the mouseGrabberItem may be different after returning from sendEvent()
@@ -589,7 +622,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
touchMouseId = -1;
if (mouseGrabberItem) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event, mouseGrabberItem));
- QQuickItemPrivate::get(item)->deliverMouseEvent(me.data());
+ QCoreApplication::sendEvent(item, me.data());
if (mouseGrabberItem) // might have ungrabbed due to event
mouseGrabberItem->ungrabMouse();
return me->isAccepted();
@@ -1031,6 +1064,18 @@ QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
}
/*!
+ \internal
+*/
+QQuickWindow::QQuickWindow(QQuickRenderControl *control)
+ : QWindow(*(new QQuickWindowPrivate), 0)
+{
+ Q_D(QQuickWindow);
+ d->init(this, control);
+}
+
+
+
+/*!
Destroys the window.
*/
QQuickWindow::~QQuickWindow()
@@ -1038,7 +1083,10 @@ QQuickWindow::~QQuickWindow()
Q_D(QQuickWindow);
d->animationController->deleteLater();
- d->windowManager->windowDestroyed(this);
+ if (d->renderControl)
+ d->renderControl->windowDestroyed();
+ else
+ d->windowManager->windowDestroyed(this);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete d->incubationController; d->incubationController = 0;
@@ -1066,7 +1114,8 @@ QQuickWindow::~QQuickWindow()
void QQuickWindow::releaseResources()
{
Q_D(QQuickWindow);
- d->windowManager->releaseResources(this);
+ if (d->windowManager)
+ d->windowManager->releaseResources(this);
QQuickPixmap::purgeCache();
}
@@ -1298,24 +1347,43 @@ bool QQuickWindow::event(QEvent *e)
void QQuickWindow::keyPressEvent(QKeyEvent *e)
{
Q_D(QQuickWindow);
-
-#ifndef QT_NO_SHORTCUT
- // Try looking for a Shortcut before sending key events
- if (QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focusObject(), e))
- return;
-#endif
-
- if (d->activeFocusItem)
- sendEvent(d->activeFocusItem, e);
+ d->deliverKeyEvent(e);
}
/*! \reimp */
void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
{
Q_D(QQuickWindow);
+ d->deliverKeyEvent(e);
+}
- if (d->activeFocusItem)
- sendEvent(d->activeFocusItem, e);
+void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e)
+{
+ Q_Q(QQuickWindow);
+
+#ifndef QT_NO_SHORTCUT
+ // Try looking for a Shortcut before sending key events
+ if (e->type() == QEvent::KeyPress
+ && QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(q->focusObject(), e))
+ return;
+#endif
+
+ if (activeFocusItem)
+ q->sendEvent(activeFocusItem, e);
+#ifdef Q_OS_MAC
+ else {
+ // This is the case for popup windows on Mac, where popup windows get focus
+ // in Qt (after exposure) but they are not "key windows" in the Cocoa sense.
+ // Therefore, the will never receive key events from Cocoa. Instead, the
+ // toplevel non-popup window (the application current "key window") will
+ // receive them. (QWidgetWindow does something similar for widgets, by keeping
+ // a list of popup windows, and forwarding the key event to the top-most popup.)
+ QWindow *focusWindow = qApp->focusWindow();
+ if (focusWindow && focusWindow != q
+ && (focusWindow->flags() & Qt::Popup) == Qt::Popup)
+ QGuiApplication::sendEvent(focusWindow, e);
+ }
+#endif
}
QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos)
@@ -1327,6 +1395,7 @@ QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *t
event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers());
QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, caps, velocity);
+ QGuiApplicationPrivate::setMouseEventSource(me, QGuiApplicationPrivate::mouseEventSource(event));
me->setTimestamp(event->timestamp());
return me;
}
@@ -1403,6 +1472,12 @@ bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
void QQuickWindow::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ event->accept();
+ return;
+ }
+
#ifdef MOUSE_DEBUG
qWarning() << "QQuickWindow::mousePressEvent()" << event->localPos() << event->button() << event->buttons();
#endif
@@ -1414,6 +1489,12 @@ void QQuickWindow::mousePressEvent(QMouseEvent *event)
void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ event->accept();
+ return;
+ }
+
#ifdef MOUSE_DEBUG
qWarning() << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons();
#endif
@@ -1432,6 +1513,12 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ event->accept();
+ return;
+ }
+
#ifdef MOUSE_DEBUG
qWarning() << "QQuickWindow::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons();
#endif
@@ -1467,6 +1554,12 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickWindow);
+
+ if (event->source() == Qt::MouseEventSynthesizedBySystem) {
+ event->accept();
+ return;
+ }
+
#ifdef MOUSE_DEBUG
qWarning() << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons();
#endif
@@ -1815,11 +1908,11 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
itemForTouchPointId[id] = item;
// Deliver the touch event to the given item
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->deliverTouchEvent(touchEvent.data());
+ QCoreApplication::sendEvent(item, touchEvent.data());
touchEventAccepted = touchEvent->isAccepted();
// If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it.
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (!touchEventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
// send mouse event
event->setAccepted(translateTouchToMouse(item, event));
@@ -2214,7 +2307,7 @@ void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
bool QQuickWindowPrivate::isRenderable() const
{
Q_Q(const QQuickWindow);
- return q->isExposed() && q->isVisible() && q->geometry().isValid();
+ return (forceRendering || (q->isExposed() && q->isVisible())) && q->geometry().isValid();
}
/*!
@@ -2237,16 +2330,12 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
case QEvent::KeyPress:
case QEvent::KeyRelease:
e->accept();
- QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
+ QCoreApplication::sendEvent(item, e);
while (!e->isAccepted() && (item = item->parentItem())) {
e->accept();
- QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
+ QCoreApplication::sendEvent(item, e);
}
break;
- case QEvent::FocusIn:
- case QEvent::FocusOut:
- QQuickItemPrivate::get(item)->deliverFocusEvent(static_cast<QFocusEvent *>(e));
- break;
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
@@ -2255,7 +2344,7 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
// accept because qml items by default accept and have to explicitly opt out of accepting
e->accept();
- QQuickItemPrivate::get(item)->deliverMouseEvent(static_cast<QMouseEvent *>(e));
+ QCoreApplication::sendEvent(item, e);
}
break;
case QEvent::UngrabMouse:
@@ -2266,30 +2355,26 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
break;
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
- QQuickItemPrivate::get(item)->deliverWheelEvent(static_cast<QWheelEvent *>(e));
- break;
#endif
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ case QEvent::DragLeave:
+ case QEvent::Drop:
+#endif
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
- QQuickItemPrivate::get(item)->deliverHoverEvent(static_cast<QHoverEvent *>(e));
+ case QEvent::TouchCancel:
+ QCoreApplication::sendEvent(item, e);
break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
d->sendFilteredTouchEvent(item->parentItem(), item, static_cast<QTouchEvent *>(e));
break;
- case QEvent::TouchCancel:
- QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
- break;
-#ifndef QT_NO_DRAGANDDROP
- case QEvent::DragEnter:
- case QEvent::DragMove:
- case QEvent::DragLeave:
- case QEvent::Drop:
- QQuickItemPrivate::get(item)->deliverDragEvent(e);
- break;
-#endif
default:
break;
}
@@ -2590,10 +2675,24 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
}
+bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
+{
+ Q_Q(QQuickWindow);
+ static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWindow::sceneGraphError);
+ if (q->isSignalConnected(errorSignal)) {
+ emit q->sceneGraphError(error, msg);
+ return true;
+ }
+ return false;
+}
+
void QQuickWindow::maybeUpdate()
{
Q_D(QQuickWindow);
- d->windowManager->maybeUpdate(this);
+ if (d->renderControl)
+ d->renderControl->maybeUpdate();
+ else
+ d->windowManager->maybeUpdate(this);
}
void QQuickWindow::cleanupSceneGraph()
@@ -2662,6 +2761,21 @@ QOpenGLContext *QQuickWindow::openglContext() const
*/
/*!
+ \fn void QQuickWindow::sceneGraphError(SceneGraphError error, const QString &message)
+
+ This signal is emitted when an error occurred during scene graph initialization.
+
+ Applications should connect to this signal if they wish to handle errors,
+ like OpenGL context creation failures, in a custom way. When no slot is
+ connected to the signal, the behavior will be different: Quick will print
+ the message, or show a message box, and terminate the application.
+
+ This signal will be emitted from the gui thread.
+
+ \since 5.3
+ */
+
+/*!
\class QQuickCloseEvent
\internal
\since 5.1
@@ -2852,7 +2966,7 @@ QImage QQuickWindow::grabWindow()
return image;
}
- return d->windowManager->grab(this);
+ return d->renderControl ? d->renderControl->grab() : d->windowManager->grab(this);
}
/*!
@@ -2867,6 +2981,9 @@ QQmlIncubationController *QQuickWindow::incubationController() const
{
Q_D(const QQuickWindow);
+ if (!d->windowManager)
+ return 0; // TODO: make sure that this is safe
+
if (!d->incubationController)
d->incubationController = new QQuickWindowIncubationController(d->windowManager);
return d->incubationController;
@@ -2892,6 +3009,20 @@ QQmlIncubationController *QQuickWindow::incubationController() const
*/
/*!
+ \enum QQuickWindow::SceneGraphError
+
+ This enum describes the error in a sceneGraphError() signal.
+
+ \value ContextNotAvailable OpenGL context creation failed. This typically means that
+ no suitable OpenGL implementation was found, for example because no graphics drivers
+ are installed and so no OpenGL 2 support is present. On mobile and embedded boards
+ that use OpenGL ES such an error is likely to indicate issues in the windowing system
+ integration and possibly an incorrect configuration of Qt.
+
+ \since 5.3
+ */
+
+/*!
\fn void QQuickWindow::beforeSynchronizing()
This signal is emitted before the scene graph is synchronized with the QML state.
@@ -2949,6 +3080,16 @@ QQmlIncubationController *QQuickWindow::incubationController() const
do so can result in the scene not rendering properly.
*/
+/*!
+ \fn void QQuickWindow::afterAnimating()
+
+ This signal is emitted on the gui thread before requesting the render thread to
+ perform the synchronization of the scene graph.
+
+ Unlike the other similar signals, this one is emitted on the gui thread instead
+ of the render thread. It can be used to synchronize external animation systems
+ with the QML content.
+ */
/*!
@@ -3053,7 +3194,6 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create
QSGPlainTexture *texture = new QSGPlainTexture();
texture->setTextureId(id);
texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
- texture->setHasMipmaps(options & TextureHasMipmaps);
texture->setOwnsTexture(options & TextureOwnsGLTexture);
texture->setTextureSize(size);
return texture;
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 5063b3b5db..8be6cc88b7 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -58,6 +58,7 @@ class QOpenGLFramebufferObject;
class QQmlIncubationController;
class QInputMethodEvent;
class QQuickCloseEvent;
+class QQuickRenderControl;
class Q_QUICK_EXPORT QQuickWindow : public QWindow
{
@@ -78,6 +79,11 @@ public:
Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
+ enum SceneGraphError {
+ ContextNotAvailable = 1
+ };
+ Q_ENUMS(SceneGraphError)
+
QQuickWindow(QWindow *parent = 0);
virtual ~QQuickWindow();
@@ -137,9 +143,11 @@ Q_SIGNALS:
void beforeSynchronizing();
void beforeRendering();
void afterRendering();
+ void afterAnimating();
Q_REVISION(1) void closing(QQuickCloseEvent *close);
void colorChanged(const QColor &);
Q_REVISION(1) void activeFocusItemChanged();
+ void sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message);
public Q_SLOTS:
void update();
@@ -177,7 +185,10 @@ private Q_SLOTS:
private:
friend class QQuickItem;
+ friend class QQuickWidget;
+ friend class QQuickWidgetPrivate;
friend class QQuickAnimatorController;
+ explicit QQuickWindow(QQuickRenderControl*);
Q_DISABLE_COPY(QQuickWindow)
};
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 418633b6ac..4fb3d0fa08 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -57,6 +57,7 @@
#include "qquickwindow.h"
#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgbatchrenderer_p.h>
#include <QtCore/qthread.h>
#include <QtCore/qmutex.h>
@@ -73,6 +74,7 @@ QT_BEGIN_NAMESPACE
class QQuickAnimatorController;
class QSGRenderLoop;
+class QQuickRenderControl;
class QQuickDragGrabber;
class QQuickRootItem : public QQuickItem
@@ -102,7 +104,7 @@ public:
QQuickWindowPrivate();
virtual ~QQuickWindowPrivate();
- void init(QQuickWindow *);
+ void init(QQuickWindow *, QQuickRenderControl *control = 0);
void initContentItem();//Currently only used if items added in QML
QQuickRootItem *contentItem;
@@ -111,6 +113,8 @@ public:
QQuickItem *activeFocusItem;
+ void deliverKeyEvent(QKeyEvent *e);
+
// Keeps track of the item currently receiving mouse events
QQuickItem *mouseGrabberItem;
#ifndef QT_NO_CURSOR
@@ -180,6 +184,8 @@ public:
bool isRenderable() const;
+ bool emitError(QQuickWindow::SceneGraphError error, const QString &msg);
+
QQuickItem::UpdatePaintNodeData updatePaintNodeData;
QQuickItem *dirtyItemList;
@@ -198,8 +204,10 @@ public:
QSGRenderContext *context;
QSGRenderer *renderer;
+ QByteArray customRenderMode; // Default renderer supports "clip", "overdraw", "changes", "batches" and blank.
QSGRenderLoop *windowManager;
+ QQuickRenderControl *renderControl;
QQuickAnimatorController *animationController;
QColor clearColor;
@@ -213,6 +221,7 @@ public:
uint lastWheelEventAccepted : 1;
bool componentCompleted : 1;
+ bool forceRendering : 1;
QOpenGLFramebufferObject *renderTarget;
uint renderTargetId;
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index ee5034c108..9d2a0b0f75 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -49,6 +49,7 @@
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
+#include <private/qquickprofiler_p.h>
#include <private/qquickapplication_p.h>
#include <QtQuick/private/qquickpropertychanges_p.h>
#include <QtQuick/private/qquickstate_p.h>
@@ -189,9 +190,10 @@ void QQmlQtQuick2Module::defineModule()
QQuickValueTypes::registerValueTypes();
- if (QQmlEngineDebugService::isDebuggingEnabled()) {
+ if (QQmlDebugService::isDebuggingEnabled()) {
QQmlEngineDebugService::instance()->setStatesDelegate(
new QQmlQtQuick2DebugStatesDelegate);
+ QQuickProfiler::initialize();
}
}
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
index 5168ec2c24..38e743cc5c 100644
--- a/src/quick/quick.pro
+++ b/src/quick/quick.pro
@@ -6,6 +6,7 @@ QT_PRIVATE = network
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+win32:!wince:!winrt: LIBS += -luser32
exists("qqml_enable_gcov") {
QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
@@ -16,8 +17,6 @@ QMAKE_DOCS = $$PWD/doc/qtquick.qdocconf
ANDROID_LIB_DEPENDENCIES = \
lib/libQt5QuickParticles.so
-ANDROID_LIB_DEPENDENCY_REPLACEMENTS = \
- "plugins/platforms/android/libqtforandroid.so:plugins/platforms/android/libqtforandroidGL.so"
MODULE_PLUGIN_TYPES += \
accessible/libqtaccessiblequick.so
ANDROID_BUNDLED_FILES += \
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 8da776d754..30081093f2 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -43,13 +43,18 @@
#include "qsgbatchrenderer_p.h"
#include <private/qsgshadersourcebuilder_p.h>
+#include <QQuickWindow>
+
+#include <qmath.h>
+
#include <QtCore/QElapsedTimer>
+#include <QtCore/QtNumeric>
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/QOpenGLVertexArrayObject>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
#include <algorithm>
@@ -107,7 +112,7 @@ bool qsg_sort_batch_is_valid(Batch *a, Batch *b) { return a->first && !b->first;
bool qsg_sort_batch_increasing_order(Batch *a, Batch *b) { return a->first->order < b->first->order; }
bool qsg_sort_batch_decreasing_order(Batch *a, Batch *b) { return a->first->order > b->first->order; }
-QSGMaterial::Flag QSGMaterial_RequiresFullMatrixBit = (QSGMaterial::Flag) (QSGMaterial::RequiresFullMatrix & ~QSGMaterial::RequiresFullMatrixExceptTranslate);
+QSGMaterial::Flag QSGMaterial_FullMatrix = (QSGMaterial::Flag) (QSGMaterial::RequiresFullMatrix & ~QSGMaterial::RequiresFullMatrixExceptTranslate);
struct QMatrix4x4_Accessor
{
@@ -129,7 +134,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
return shader;
#ifndef QSG_NO_RENDER_TIMING
- if (qsg_render_timing || QQmlProfilerService::enabled)
+ if (qsg_render_timing || QQuickProfiler::enabled)
qsg_renderer_timer.start();
#endif
@@ -163,11 +168,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
if (qsg_render_timing)
qDebug(" - compiling material: %dms", (int) qsg_renderer_timer.elapsed());
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphContextFrame,
- qsg_renderer_timer.nsecsElapsed());
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphContextFrame, (
+ qsg_renderer_timer.nsecsElapsed()));
#endif
rewrittenShaders[type] = shader;
@@ -182,7 +184,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
return shader;
#ifndef QSG_NO_RENDER_TIMING
- if (qsg_render_timing || QQmlProfilerService::enabled)
+ if (qsg_render_timing || QQuickProfiler::enabled)
qsg_renderer_timer.start();
#endif
@@ -202,11 +204,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
if (qsg_render_timing)
qDebug(" - compiling material: %dms", (int) qsg_renderer_timer.elapsed());
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphContextFrame,
- qsg_renderer_timer.nsecsElapsed());
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphContextFrame, (
+ qsg_renderer_timer.nsecsElapsed()));
#endif
return shader;
@@ -304,6 +303,9 @@ void Updater::updateStates(QSGNode *n)
qDebug() << " - forceupdate";
}
+ if (Q_UNLIKELY(renderer->m_visualizeMode == Renderer::VisualizeChanges))
+ renderer->visualizeChangesPrepare(sn);
+
visitNode(sn);
}
@@ -763,6 +765,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_currentClip(0)
, m_currentClipType(NoClip)
, m_vao(0)
+ , m_visualizeMode(VisualizeNothing)
{
setNodeUpdater(new Updater(this));
@@ -1676,7 +1679,7 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData,
*indexCount += iCount;
}
-const QMatrix4x4 &Renderer::matrixForRoot(Node *node)
+static QMatrix4x4 qsg_matrixForRoot(Node *node)
{
if (node->type() == QSGNode::TransformNodeType)
return static_cast<QSGTransformNode *>(node->sgNode)->combinedMatrix();
@@ -1709,14 +1712,12 @@ void Renderer::uploadBatch(Batch *b)
QSGGeometryNode *gn = b->first->node;
QSGGeometry *g = gn->geometry();
-
+ QSGMaterial::Flags flags = gn->activeMaterial()->flags();
bool canMerge = (g->drawingMode() == GL_TRIANGLES || g->drawingMode() == GL_TRIANGLE_STRIP)
&& b->positionAttribute >= 0
&& g->indexType() == GL_UNSIGNED_SHORT
- && (gn->activeMaterial()->flags() & QSGMaterial::CustomCompileStep) == 0
- && (((gn->activeMaterial()->flags() & QSGMaterial::RequiresDeterminant) == 0)
- || (((gn->activeMaterial()->flags() & QSGMaterial_RequiresFullMatrixBit) == 0) && b->isTranslateOnlyToRoot())
- )
+ && (flags & (QSGMaterial::CustomCompileStep | QSGMaterial_FullMatrix)) == 0
+ && ((flags & QSGMaterial::RequiresFullMatrixExceptTranslate) == 0 || b->isTranslateOnlyToRoot())
&& b->isSafeToBatch();
b->merged = canMerge;
@@ -2012,7 +2013,7 @@ void Renderer::renderMergedBatch(const Batch *batch)
// We always have dirty matrix as all batches are at a unique z range.
QSGMaterialShader::RenderState::DirtyStates dirty = QSGMaterialShader::RenderState::DirtyMatrix;
if (batch->root)
- m_current_model_view_matrix = matrixForRoot(batch->root);
+ m_current_model_view_matrix = qsg_matrixForRoot(batch->root);
else
m_current_model_view_matrix.setToIdentity();
m_current_determinant = m_current_model_view_matrix.determinant();
@@ -2141,7 +2142,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
char *iOffset = indexBase + batch->vertexCount * gn->geometry()->sizeOfVertex();
#endif
- QMatrix4x4 rootMatrix = batch->root ? matrixForRoot(batch->root) : QMatrix4x4();
+ QMatrix4x4 rootMatrix = batch->root ? qsg_matrixForRoot(batch->root) : QMatrix4x4();
while (e) {
gn = e->node;
@@ -2175,6 +2176,10 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES)
glLineWidth(g->lineWidth());
+#if !defined(QT_OPENGL_ES_2)
+ else if (g->drawingMode() == GL_POINTS)
+ glPointSize(g->lineWidth());
+#endif
if (g->indexCount())
glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), iOffset);
@@ -2361,7 +2366,6 @@ void Renderer::render()
cleanupBatches(&m_opaqueBatches);
cleanupBatches(&m_alphaBatches);
-
if (m_rebuild & BuildBatches) {
prepareOpaqueBatches();
prepareAlphaBatches();
@@ -2411,6 +2415,9 @@ void Renderer::render()
m_rebuild = 0;
+ if (m_visualizeMode != VisualizeNothing)
+ visualize();
+
if (m_vao)
m_vao->release();
}
@@ -2449,7 +2456,7 @@ void Renderer::renderRenderNode(Batch *batch)
QMatrix4x4 matrix;
while (xform != rootNode()) {
if (xform->type() == QSGNode::TransformNodeType) {
- matrix = matrixForRoot(e->root) * static_cast<QSGTransformNode *>(xform)->combinedMatrix();
+ matrix = qsg_matrixForRoot(e->root) * static_cast<QSGTransformNode *>(xform)->combinedMatrix();
break;
}
xform = xform->parent();
@@ -2513,6 +2520,312 @@ void Renderer::renderRenderNode(Batch *batch)
}
+class VisualizeShader : public QOpenGLShaderProgram
+{
+public:
+ int color;
+ int matrix;
+ int rotation;
+ int tweak;
+};
+
+void Renderer::visualizeDrawGeometry(const QSGGeometry *g)
+{
+ if (g->attributeCount() < 1)
+ return;
+ const QSGGeometry::Attribute *a = g->attributes();
+ glVertexAttribPointer(0, a->tupleSize, a->type, false, g->sizeOfVertex(), g->vertexData());
+ if (g->indexCount())
+ glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData());
+ else
+ glDrawArrays(g->drawingMode(), 0, g->vertexCount());
+
+}
+
+void Renderer::visualizeBatch(Batch *b)
+{
+ VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
+
+ if (b->positionAttribute != 0)
+ return;
+
+ QSGGeometryNode *gn = b->first->node;
+ QSGGeometry *g = gn->geometry();
+ const QSGGeometry::Attribute &a = g->attributes()[b->positionAttribute];
+
+ glBindBuffer(GL_ARRAY_BUFFER, b->vbo.id);
+
+ QMatrix4x4 matrix(m_current_projection_matrix);
+ if (b->root)
+ matrix = matrix * qsg_matrixForRoot(b->root);
+
+ QRect viewport = viewportRect();
+ shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), b->merged ? 0 : 1, 0);
+
+ QColor color = QColor::fromHsvF((rand() & 1023) / 1023.0, 1.0, 1.0);
+ float cr = color.redF();
+ float cg = color.greenF();
+ float cb = color.blueF();
+ shader->setUniformValue(shader->color, cr, cg, cb, 1.0);
+
+ if (b->merged) {
+ shader->setUniformValue(shader->matrix, matrix);
+ for (int ds=0; ds<b->drawSets.size(); ++ds) {
+ const DrawSet &set = b->drawSets.at(ds);
+ glVertexAttribPointer(a.position, 2, a.type, false, g->sizeOfVertex(), (void *) (qintptr) (set.vertices));
+ glDrawElements(g->drawingMode(), set.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (b->vbo.data + set.indices));
+ }
+ } else {
+ Element *e = b->first;
+ int offset = 0;
+ while (e) {
+ gn = e->node;
+ g = gn->geometry();
+ shader->setUniformValue(shader->matrix, matrix * *gn->matrix());
+ glVertexAttribPointer(a.position, a.tupleSize, a.type, false, g->sizeOfVertex(), (void *) (qintptr) offset);
+ glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData());
+ offset += g->sizeOfVertex() * g->vertexCount();
+ e = e->nextInBatch;
+ }
+ }
+}
+
+
+
+
+void Renderer::visualizeClipping(QSGNode *node)
+{
+ if (node->type() == QSGNode::ClipNodeType) {
+ VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
+ QSGClipNode *clipNode = static_cast<QSGClipNode *>(node);
+ QMatrix4x4 matrix = m_current_projection_matrix;
+ if (clipNode->matrix())
+ matrix = matrix * *clipNode->matrix();
+ shader->setUniformValue(shader->matrix, matrix);
+ visualizeDrawGeometry(clipNode->geometry());
+ }
+
+ QSGNODE_TRAVERSE(node) {
+ visualizeClipping(child);
+ }
+}
+
+#define QSGNODE_DIRTY_PARENT (QSGNode::DirtyNodeAdded \
+ | QSGNode::DirtyOpacity \
+ | QSGNode::DirtyMatrix \
+ | QSGNode::DirtyNodeRemoved)
+
+void Renderer::visualizeChangesPrepare(Node *n, uint parentChanges)
+{
+ uint childDirty = (parentChanges | n->dirtyState) & QSGNODE_DIRTY_PARENT;
+ uint selfDirty = n->dirtyState | parentChanges;
+ if (n->type() == QSGNode::GeometryNodeType && selfDirty != 0)
+ m_visualizeChanceSet.insert(n, selfDirty);
+ SHADOWNODE_TRAVERSE(n) {
+ visualizeChangesPrepare(*child, childDirty);
+ }
+}
+
+void Renderer::visualizeChanges(Node *n)
+{
+
+ if (n->type() == QSGNode::GeometryNodeType && m_visualizeChanceSet.contains(n)) {
+ uint dirty = m_visualizeChanceSet.value(n);
+ bool tinted = (dirty & QSGNODE_DIRTY_PARENT) != 0;
+
+ VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
+ QColor color = QColor::fromHsvF((rand() & 1023) / 1023.0, 0.3, 1.0);
+ float ca = 0.5;
+ float cr = color.redF() * ca;
+ float cg = color.greenF() * ca;
+ float cb = color.blueF() * ca;
+ shader->setUniformValue(shader->color, cr, cg, cb, ca);
+
+ QRect viewport = viewportRect();
+ shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), tinted ? 0.5 : 0, 0);
+
+ QSGGeometryNode *gn = static_cast<QSGGeometryNode *>(n->sgNode);
+
+ QMatrix4x4 matrix = m_current_projection_matrix;
+ if (n->element()->batch->root)
+ matrix = matrix * qsg_matrixForRoot(n->element()->batch->root);
+ matrix = matrix * *gn->matrix();
+ shader->setUniformValue(shader->matrix, matrix);
+ visualizeDrawGeometry(gn->geometry());
+
+ // This is because many changes don't propegate their dirty state to the
+ // parent so the node updater will not unset these states. They are
+ // not used for anything so, unsetting it should have no side effects.
+ n->dirtyState = 0;
+ }
+
+ SHADOWNODE_TRAVERSE(n) {
+ visualizeChanges(*child);
+ }
+}
+
+void Renderer::visualizeOverdraw_helper(Node *node)
+{
+ if (node->type() == QSGNode::GeometryNodeType) {
+ VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
+ QSGGeometryNode *gn = static_cast<QSGGeometryNode *>(node->sgNode);
+
+ QMatrix4x4 matrix = m_current_projection_matrix;
+ matrix(2, 2) = m_zRange;
+ matrix(2, 3) = 1.0f - node->element()->order * m_zRange;
+
+ if (node->element()->batch->root)
+ matrix = matrix * qsg_matrixForRoot(node->element()->batch->root);
+ matrix = matrix * *gn->matrix();
+ shader->setUniformValue(shader->matrix, matrix);
+
+ QColor color = node->element()->batch->isOpaque ? QColor::fromRgbF(0.3, 1.0, 0.3) : QColor::fromRgbF(1.0, 0.3, 0.3);
+ float ca = 0.33;
+ shader->setUniformValue(shader->color, color.redF() * ca, color.greenF() * ca, color.blueF() * ca, ca);
+
+ visualizeDrawGeometry(gn->geometry());
+ }
+
+ SHADOWNODE_TRAVERSE(node) {
+ visualizeOverdraw_helper(*child);
+ }
+}
+
+void Renderer::visualizeOverdraw()
+{
+ VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
+ shader->setUniformValue(shader->color, 0.5, 0.5, 1, 1);
+
+ QRect viewport = viewportRect();
+ shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), 0, 1);
+
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ static float step = 0;
+ step += M_PI * 2 / 1000.;
+ if (step > M_PI * 2)
+ step = 0;
+ float angle = 80.0 * sin(step);
+
+ QMatrix4x4 xrot; xrot.rotate(20, 1, 0, 0);
+ QMatrix4x4 zrot; zrot.rotate(angle, 0, 0, 1);
+ QMatrix4x4 tx; tx.translate(0, 0, 1);
+
+ QMatrix4x4 m;
+
+// m.rotate(180, 0, 1, 0);
+
+ m.translate(0, 0.5, 4);
+ m.scale(2, 2, 1);
+
+ m.rotate(-30, 1, 0, 0);
+ m.rotate(angle, 0, 1, 0);
+ m.translate(0, 0, -1);
+
+ shader->setUniformValue(shader->rotation, m);
+
+ float box[] = {
+ // lower
+ -1, 1, 0, 1, 1, 0,
+ -1, 1, 0, -1, -1, 0,
+ 1, 1, 0, 1, -1, 0,
+ -1, -1, 0, 1, -1, 0,
+
+ // upper
+ -1, 1, 1, 1, 1, 1,
+ -1, 1, 1, -1, -1, 1,
+ 1, 1, 1, 1, -1, 1,
+ -1, -1, 1, 1, -1, 1,
+
+ // sides
+ -1, -1, 0, -1, -1, 1,
+ 1, -1, 0, 1, -1, 1,
+ -1, 1, 0, -1, 1, 1,
+ 1, 1, 0, 1, 1, 1
+ };
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, box);
+ glLineWidth(2);
+ glDrawArrays(GL_LINES, 0, 24);
+
+ visualizeOverdraw_helper(m_nodes.value(rootNode()));
+
+ // Animate the view...
+ QSurface *surface = QOpenGLContext::currentContext()->surface();
+ if (surface->surfaceClass() == QSurface::Window)
+ if (QQuickWindow *window = qobject_cast<QQuickWindow *>(static_cast<QWindow *>(surface)))
+ window->update();
+}
+
+void Renderer::setCustomRenderMode(const QByteArray &mode)
+{
+ if (mode.isEmpty()) m_visualizeMode = VisualizeNothing;
+ else if (mode == "clip") m_visualizeMode = VisualizeClipping;
+ else if (mode == "overdraw") m_visualizeMode = VisualizeOverdraw;
+ else if (mode == "batches") m_visualizeMode = VisualizeBatches;
+ else if (mode == "changes") m_visualizeMode = VisualizeChanges;
+}
+
+void Renderer::visualize()
+{
+ if (!m_shaderManager->visualizeProgram) {
+ VisualizeShader *prog = new VisualizeShader();
+ QSGShaderSourceBuilder::initializeProgramFromFiles(
+ prog,
+ QStringLiteral(":/scenegraph/shaders/visualization.vert"),
+ QStringLiteral(":/scenegraph/shaders/visualization.frag"));
+ prog->bindAttributeLocation("v", 0);
+ prog->link();
+ prog->bind();
+ prog->color = prog->uniformLocation("color");
+ prog->tweak = prog->uniformLocation("tweak");
+ prog->matrix = prog->uniformLocation("matrix");
+ prog->rotation = prog->uniformLocation("rotation");
+ m_shaderManager->visualizeProgram = prog;
+ } else {
+ m_shaderManager->visualizeProgram->bind();
+ }
+ VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
+
+ glDisable(GL_DEPTH_TEST);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glEnableVertexAttribArray(0);
+
+ // Blacken out the actual rendered content...
+ float bgOpacity = 0.8;
+ if (m_visualizeMode == VisualizeBatches)
+ bgOpacity = 1.0;
+ float v[] = { -1, 1, 1, 1, -1, -1, 1, -1 };
+ shader->setUniformValue(shader->color, 0, 0, 0, bgOpacity);
+ shader->setUniformValue(shader->matrix, QMatrix4x4());
+ shader->setUniformValue(shader->rotation, QMatrix4x4());
+ shader->setUniformValue(shader->tweak, 0, 0, 0, 0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, v);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ if (m_visualizeMode == VisualizeBatches) {
+ srand(0); // To force random colors to be roughly the same every time..
+ for (int i=0; i<m_opaqueBatches.size(); ++i) visualizeBatch(m_opaqueBatches.at(i));
+ for (int i=0; i<m_alphaBatches.size(); ++i) visualizeBatch(m_alphaBatches.at(i));
+ } else if (m_visualizeMode == VisualizeClipping) {
+ QRect viewport = viewportRect();
+ shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), 0.5, 0);
+ shader->setUniformValue(shader->color, 0.2, 0, 0, 0.2);
+ visualizeClipping(rootNode());
+ } else if (m_visualizeMode == VisualizeChanges) {
+ visualizeChanges(m_nodes.value(rootNode()));
+ m_visualizeChanceSet.clear();
+ } else if (m_visualizeMode == VisualizeOverdraw) {
+ visualizeOverdraw();
+ }
+
+ // Reset state back to defaults..
+ glDisable(GL_BLEND);
+ glDisableVertexAttribArray(0);
+ shader->release();
+}
+
QT_END_NAMESPACE
}
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 128ae2765e..7c06de774a 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -371,7 +371,7 @@ public:
float lastOpacity;
};
- ShaderManager(QSGRenderContext *ctx) : blitProgram(0), context(ctx) { }
+ ShaderManager(QSGRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { }
~ShaderManager() {
qDeleteAll(rewrittenShaders.values());
qDeleteAll(stockShaders.values());
@@ -388,6 +388,7 @@ public:
QHash<QSGMaterialType *, Shader *> stockShaders;
QOpenGLShaderProgram *blitProgram;
+ QOpenGLShaderProgram *visualizeProgram;
QSGRenderContext *context;
};
@@ -397,6 +398,14 @@ public:
Renderer(QSGRenderContext *);
~Renderer();
+ enum VisualizeMode {
+ VisualizeNothing,
+ VisualizeBatches,
+ VisualizeClipping,
+ VisualizeChanges,
+ VisualizeOverdraw
+ };
+
protected:
void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
void preprocess() Q_DECL_OVERRIDE;
@@ -452,6 +461,16 @@ private:
inline Batch *newBatch();
void invalidateAndRecycleBatch(Batch *b);
+ void visualize();
+ void visualizeBatch(Batch *b);
+ void visualizeClipping(QSGNode *node);
+ void visualizeChangesPrepare(Node *n, uint parentChanges = 0);
+ void visualizeChanges(Node *n);
+ void visualizeOverdraw();
+ void visualizeOverdraw_helper(Node *node);
+ void visualizeDrawGeometry(const QSGGeometry *g);
+ void setCustomRenderMode(const QByteArray &mode);
+
QSet<Node *> m_taggedRoots;
QDataBuffer<Element *> m_opaqueRenderList;
QDataBuffer<Element *> m_alphaRenderList;
@@ -488,6 +507,9 @@ private:
// For minimal OpenGL core profile support
QOpenGLVertexArrayObject *m_vao;
+
+ QHash<Node *, uint> m_visualizeChanceSet;
+ VisualizeMode m_visualizeMode;
};
Batch *Renderer::newBatch()
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index ffb11fc6fa..40e0a014ab 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -525,8 +525,9 @@ void QSGGeometry::setDrawingMode(GLenum mode)
}
/*!
- Gets the current line width to be used for this geometry. This property only
- applies where the drawingMode is GL_LINES or a related value.
+ Gets the current line or point width or to be used for this geometry. This property
+ only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or
+ \c GL_LINE_LOOP, and only applies to point size when the drawingMode is \c GL_POINTS.
The default value is \c 1.0
@@ -538,8 +539,9 @@ float QSGGeometry::lineWidth() const
}
/*!
- Sets the line width to be used for this geometry to \a width. The line width
- only applies where the drawingMode is \c GL_LINES or a related value.
+ Sets the line or point width to be used for this geometry to \a width. This property
+ only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or
+ \c GL_LINE_LOOP, and only applies to point size when the drawingMode is \c GL_POINTS.
\sa lineWidth(), drawingMode()
*/
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index e35bfe5494..cc8793c0cf 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -54,7 +54,7 @@
#include <qdatetime.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
QT_BEGIN_NAMESPACE
@@ -227,7 +227,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames)
frameTimer.start();
qint64 bindTime = 0;
@@ -287,14 +287,11 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
int(renderTime / 1000000));
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphRendererFrame,
- preprocessTime,
- updatePassTime - preprocessTime,
- bindTime - updatePassTime,
- renderTime - bindTime);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphRendererFrame, (
+ preprocessTime,
+ updatePassTime - preprocessTime,
+ bindTime - updatePassTime,
+ renderTime - bindTime));
#endif
}
@@ -378,7 +375,7 @@ void QSGRenderer::preprocess()
}
#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames)
preprocessTime = frameTimer.nsecsElapsed();
#endif
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index 12ba381064..55c9444365 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -132,6 +132,8 @@ public:
void setClearMode(ClearMode mode) { m_clear_mode = mode; }
ClearMode clearMode() const { return m_clear_mode; }
+ virtual void setCustomRenderMode(const QByteArray &) { };
+
Q_SIGNALS:
void sceneGraphChanged(); // Add, remove, ChangeFlags changes...
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index cb9e4bdf88..17f4ba1243 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -48,7 +48,7 @@
#include <QtGui/qguiapplication.h>
#include <qdir.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
#include <QElapsedTimer>
QT_BEGIN_NAMESPACE
@@ -164,7 +164,7 @@ void QSGDistanceFieldGlyphCache::update()
return;
#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames)
qsg_render_timer.start();
#endif
@@ -196,13 +196,10 @@ void QSGDistanceFieldGlyphCache::update()
(int) qsg_render_timer.elapsed());
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphAdaptationLayerFrame,
- count,
- renderTime,
- qsg_render_timer.nsecsElapsed() - renderTime);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphAdaptationLayerFrame, (
+ count,
+ renderTime,
+ qsg_render_timer.nsecsElapsed() - renderTime));
#endif
}
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index c58ae85f30..0fe23f68ba 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -258,32 +258,14 @@ QSGImageNode *QSGContext::createImageNode()
}
/*!
- Factory function for scene graph backends of the Text elements which supports native
- text rendering. Used in special cases where native look and feel is a main objective.
-*/
-QSGGlyphNode *QSGContext::createNativeGlyphNode(QSGRenderContext *rc)
-{
-#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_ES_2_ANGLE)
- Q_D(QSGContext);
- if (d->distanceFieldDisabled)
- return new QSGDefaultGlyphNode;
- else
- return createGlyphNode(rc);
-#else
- Q_UNUSED(rc);
- return new QSGDefaultGlyphNode;
-#endif
-}
-
-/*!
Factory function for scene graph backends of the Text elements;
*/
-QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc)
+QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode)
{
Q_D(QSGContext);
- if (d->distanceFieldDisabled) {
- return createNativeGlyphNode(rc);
+ if (d->distanceFieldDisabled || preferNativeGlyphNode) {
+ return new QSGDefaultGlyphNode;
} else {
QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(rc);
node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing);
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 6f55dd6f12..2ab78ce289 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -162,8 +162,7 @@ public:
virtual QSGRectangleNode *createRectangleNode();
virtual QSGImageNode *createImageNode();
- virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc);
- virtual QSGGlyphNode *createNativeGlyphNode(QSGRenderContext *rc);
+ virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode);
virtual QAnimationDriver *createAnimationDriver(QObject *parent);
virtual QSize minimumFBOSize() const;
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index c5c4e18e37..4a8d908d2f 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -61,28 +61,18 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistance
, m_maxTextureSize(0)
, m_maxTextureCount(3)
, m_blitProgram(0)
+ , m_blitBuffer(QOpenGLBuffer::VertexBuffer)
, m_fboGuard(0)
#if !defined(QT_OPENGL_ES_2)
, m_funcs(0)
#endif
{
- m_blitVertexCoordinateArray[0] = -1.0f;
- m_blitVertexCoordinateArray[1] = -1.0f;
- m_blitVertexCoordinateArray[2] = 1.0f;
- m_blitVertexCoordinateArray[3] = -1.0f;
- m_blitVertexCoordinateArray[4] = 1.0f;
- m_blitVertexCoordinateArray[5] = 1.0f;
- m_blitVertexCoordinateArray[6] = -1.0f;
- m_blitVertexCoordinateArray[7] = 1.0f;
-
- m_blitTextureCoordinateArray[0] = 0.0f;
- m_blitTextureCoordinateArray[1] = 0.0f;
- m_blitTextureCoordinateArray[2] = 1.0f;
- m_blitTextureCoordinateArray[3] = 0.0f;
- m_blitTextureCoordinateArray[4] = 1.0f;
- m_blitTextureCoordinateArray[5] = 1.0f;
- m_blitTextureCoordinateArray[6] = 0.0f;
- m_blitTextureCoordinateArray[7] = 1.0f;
+ m_blitBuffer.create();
+ m_blitBuffer.bind();
+ static GLfloat buffer[16] = {1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
+ m_blitBuffer.allocate(buffer, sizeof(buffer));
+ m_blitBuffer.release();
m_areaAllocator = new QSGAreaAllocator(QSize(maxTextureSize(), m_maxTextureCount * maxTextureSize()));
}
@@ -415,12 +405,13 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
glViewport(0, 0, oldWidth, oldHeight);
- ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_blitVertexCoordinateArray);
- ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_blitTextureCoordinateArray);
+ m_blitBuffer.bind();
m_blitProgram->bind();
m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2);
+ m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, 8, 2);
m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR));
m_blitProgram->setUniformValue("imageTexture", GLuint(0));
@@ -456,6 +447,7 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ m_blitBuffer.release();
}
bool QSGDefaultDistanceFieldGlyphCache::useTextureResizeWorkaround() const
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index a5833af5fb..b561bc08f7 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -45,6 +45,7 @@
#include "qsgadaptationlayer_p.h"
#include <QtGui/qopenglfunctions.h>
#include <qopenglshaderprogram.h>
+#include <qopenglbuffer.h>
#include <QtGui/private/qopenglengineshadersource_p.h>
#include <private/qsgareaallocator_p.h>
@@ -133,8 +134,7 @@ private:
QSGAreaAllocator *m_areaAllocator;
QOpenGLShaderProgram *m_blitProgram;
- GLfloat m_blitVertexCoordinateArray[8];
- GLfloat m_blitTextureCoordinateArray[8];
+ QOpenGLBuffer m_blitBuffer;
QOpenGLSharedResourceGuard *m_fboGuard;
#if !defined(QT_OPENGL_ES_2)
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 35c4d1c506..ad0c9dad07 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -69,7 +69,7 @@ static inline QVector4D qsg_premultiply(const QVector4D &c, float globalOpacity)
class QSGTextMaskShader : public QSGMaterialShader
{
public:
- QSGTextMaskShader(QFontEngineGlyphCache::Type cacheType);
+ QSGTextMaskShader(QFontEngine::GlyphFormat glyphFormat);
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
@@ -81,7 +81,7 @@ protected:
int m_color_id;
int m_textureScale_id;
- QFontEngineGlyphCache::Type m_cacheType;
+ QFontEngine::GlyphFormat m_glyphFormat;
};
char const *const *QSGTextMaskShader::attributeNames() const
@@ -90,9 +90,9 @@ char const *const *QSGTextMaskShader::attributeNames() const
return attr;
}
-QSGTextMaskShader::QSGTextMaskShader(QFontEngineGlyphCache::Type cacheType)
+QSGTextMaskShader::QSGTextMaskShader(QFontEngine::GlyphFormat glyphFormat)
: QSGMaterialShader(*new QSGMaterialShaderPrivate),
- m_cacheType(cacheType)
+ m_glyphFormat(glyphFormat)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/textmask.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/textmask.frag"));
@@ -162,8 +162,8 @@ void QSGTextMaskShader::updateState(const RenderState &state, QSGMaterial *newEf
class QSG8BitTextMaskShader : public QSGTextMaskShader
{
public:
- QSG8BitTextMaskShader(QFontEngineGlyphCache::Type cacheType)
- : QSGTextMaskShader(cacheType)
+ QSG8BitTextMaskShader(QFontEngine::GlyphFormat glyphFormat)
+ : QSGTextMaskShader(glyphFormat)
{
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/8bittextmask.frag"));
}
@@ -186,8 +186,8 @@ void QSG8BitTextMaskShader::updateState(const RenderState &state, QSGMaterial *n
class QSG24BitTextMaskShader : public QSGTextMaskShader
{
public:
- QSG24BitTextMaskShader(QFontEngineGlyphCache::Type cacheType)
- : QSGTextMaskShader(cacheType)
+ QSG24BitTextMaskShader(QFontEngine::GlyphFormat glyphFormat)
+ : QSGTextMaskShader(glyphFormat)
, m_useSRGB(false)
{
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/24bittextmask.frag"));
@@ -207,7 +207,7 @@ void QSG24BitTextMaskShader::initialize()
// 0.25 was found to be acceptable error margin by experimentation. On Mac, the gamma is 2.0,
// but using sRGB looks okay.
if (strstr((const char *) glGetString(GL_EXTENSIONS), "GL_ARB_framebuffer_sRGB")
- && m_cacheType == QFontEngineGlyphCache::Raster_RGBMask
+ && m_glyphFormat == QFontEngine::Format_A32
&& qAbs(fontSmoothingGamma() - 2.2) < 0.25) {
m_useSRGB = true;
}
@@ -259,8 +259,8 @@ void QSG24BitTextMaskShader::updateState(const RenderState &state, QSGMaterial *
class QSGStyledTextShader : public QSG8BitTextMaskShader
{
public:
- QSGStyledTextShader(QFontEngineGlyphCache::Type cacheType)
- : QSG8BitTextMaskShader(cacheType)
+ QSGStyledTextShader(QFontEngine::GlyphFormat glyphFormat)
+ : QSG8BitTextMaskShader(glyphFormat)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/styledtext.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/styledtext.frag"));
@@ -330,27 +330,27 @@ void QSGStyledTextShader::updateState(const RenderState &state,
class QSGOutlinedTextShader : public QSGStyledTextShader
{
public:
- QSGOutlinedTextShader(QFontEngineGlyphCache::Type cacheType)
- : QSGStyledTextShader(cacheType)
+ QSGOutlinedTextShader(QFontEngine::GlyphFormat glyphFormat)
+ : QSGStyledTextShader(glyphFormat)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/outlinedtext.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/outlinedtext.frag"));
}
};
-QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font, int cacheType)
+QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font, QFontEngine::GlyphFormat glyphFormat)
: m_texture(0)
, m_glyphCache(0)
, m_font(font)
{
- init(cacheType);
+ init(glyphFormat);
}
QSGTextMaskMaterial::~QSGTextMaskMaterial()
{
}
-void QSGTextMaskMaterial::init(int cacheType)
+void QSGTextMaskMaterial::init(QFontEngine::GlyphFormat glyphFormat)
{
Q_ASSERT(m_font.isValid());
@@ -367,17 +367,14 @@ void QSGTextMaskMaterial::init(int cacheType)
QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
if (fontD->fontEngine != 0) {
- if (cacheType < 0) {
- cacheType = fontD->fontEngine->glyphFormat < 0
- ? QFontEngineGlyphCache::Raster_RGBMask
- : fontD->fontEngine->glyphFormat;
+ if (glyphFormat == QFontEngine::Format_None) {
+ glyphFormat = fontD->fontEngine->glyphFormat != QFontEngine::Format_None
+ ? fontD->fontEngine->glyphFormat
+ : QFontEngine::Format_A32;
}
- m_glyphCache = fontD->fontEngine->glyphCache(ctx,
- QFontEngineGlyphCache::Type(cacheType),
- QTransform());
- if (!m_glyphCache || int(m_glyphCache->cacheType()) != cacheType) {
- m_glyphCache = new QOpenGLTextureGlyphCache(QFontEngineGlyphCache::Type(cacheType),
- QTransform());
+ m_glyphCache = fontD->fontEngine->glyphCache(ctx, glyphFormat, QTransform());
+ if (!m_glyphCache || int(m_glyphCache->glyphFormat()) != glyphFormat) {
+ m_glyphCache = new QOpenGLTextureGlyphCache(glyphFormat, QTransform());
fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data());
QSGRenderContext *sg = QSGRenderContext::from(ctx);
Q_ASSERT(sg);
@@ -406,7 +403,7 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
fixedPointPositions.data());
cache->fillInPendingGlyphs();
- int margin = fontD->fontEngine->glyphMargin(cache->cacheType());
+ int margin = fontD->fontEngine->glyphMargin(cache->glyphFormat());
Q_ASSERT(geometry->indexType() == GL_UNSIGNED_SHORT);
geometry->allocate(glyphIndexes.size() * 4, glyphIndexes.size() * 6);
@@ -461,7 +458,7 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
QSGMaterialType *QSGTextMaskMaterial::type() const
{
static QSGMaterialType rgb, gray;
- return glyphCache()->cacheType() == QFontEngineGlyphCache::Raster_RGBMask ? &rgb : &gray;
+ return glyphCache()->glyphFormat() == QFontEngine::Format_A32 ? &rgb : &gray;
}
QOpenGLTextureGlyphCache *QSGTextMaskMaterial::glyphCache() const
@@ -471,10 +468,10 @@ QOpenGLTextureGlyphCache *QSGTextMaskMaterial::glyphCache() const
QSGMaterialShader *QSGTextMaskMaterial::createShader() const
{
- QFontEngineGlyphCache::Type type = glyphCache()->cacheType();
- return type == QFontEngineGlyphCache::Raster_RGBMask
- ? (QSGMaterialShader *) new QSG24BitTextMaskShader(type)
- : (QSGMaterialShader *) new QSG8BitTextMaskShader(type);
+ QFontEngine::GlyphFormat glyphFormat = glyphCache()->glyphFormat();
+ return glyphFormat == QFontEngine::Format_A32
+ ? (QSGMaterialShader *) new QSG24BitTextMaskShader(glyphFormat)
+ : (QSGMaterialShader *) new QSG8BitTextMaskShader(glyphFormat);
}
static inline int qsg_colorDiff(const QVector4D &a, const QVector4D &b)
@@ -530,7 +527,7 @@ int QSGTextMaskMaterial::cacheTextureHeight() const
QSGStyledTextMaterial::QSGStyledTextMaterial(const QRawFont &font)
- : QSGTextMaskMaterial(font, QFontEngineGlyphCache::Raster_A8)
+ : QSGTextMaskMaterial(font, QFontEngine::Format_A8)
{
}
@@ -542,7 +539,7 @@ QSGMaterialType *QSGStyledTextMaterial::type() const
QSGMaterialShader *QSGStyledTextMaterial::createShader() const
{
- return new QSGStyledTextShader(glyphCache()->cacheType());
+ return new QSGStyledTextShader(glyphCache()->glyphFormat());
}
int QSGStyledTextMaterial::compare(const QSGMaterial *o) const
@@ -572,7 +569,7 @@ QSGMaterialType *QSGOutlinedTextMaterial::type() const
QSGMaterialShader *QSGOutlinedTextMaterial::createShader() const
{
- return new QSGOutlinedTextShader(glyphCache()->cacheType());
+ return new QSGOutlinedTextShader(glyphCache()->glyphFormat());
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
index 5143921a1e..4e197b9d1f 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
@@ -59,7 +59,7 @@ class Geometry;
class QSGTextMaskMaterial: public QSGMaterial
{
public:
- QSGTextMaskMaterial(const QRawFont &font, int cacheType = -1);
+ QSGTextMaskMaterial(const QRawFont &font, QFontEngine::GlyphFormat glyphFormat = QFontEngine::Format_None);
virtual ~QSGTextMaskMaterial();
virtual QSGMaterialType *type() const;
@@ -84,7 +84,7 @@ public:
const QMargins &margins = QMargins(0, 0, 0, 0));
private:
- void init(int cacheType);
+ void init(QFontEngine::GlyphFormat glyphFormat);
QSGPlainTexture *m_texture;
QExplicitlySharedDataPointer<QFontEngineGlyphCache> m_glyphCache;
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index f0ac725f22..08ab3809b3 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -57,7 +57,7 @@
#include <QtQuick/QQuickWindow>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuick/private/qsgcontext_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
QT_BEGIN_NAMESPACE
@@ -281,9 +281,18 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (QSGContext::sharedOpenGLContext())
gl->setShareContext(QSGContext::sharedOpenGLContext());
if (!gl->create()) {
- qWarning("QtQuick: failed to create OpenGL context");
delete gl;
gl = 0;
+ QString formatStr;
+ QDebug(&formatStr) << window->requestedFormat();
+ QString contextType = QLatin1String(QOpenGLFunctions::isES() ? "EGL" : "OpenGL");
+ const char *msg = QT_TRANSLATE_NOOP("QSGGuiThreadRenderLoop", "Failed to create %1 context for format %2");
+ QString translatedMsg = tr(msg).arg(contextType).arg(formatStr);
+ QString nonTranslatedMsg = QString(QLatin1String(msg)).arg(contextType).arg(formatStr);
+ bool signalEmitted = QQuickWindowPrivate::get(window)->emitError(QQuickWindow::ContextNotAvailable,
+ translatedMsg);
+ if (!signalEmitted)
+ qFatal("%s", qPrintable(nonTranslatedMsg));
} else {
current = gl->makeCurrent(window);
}
@@ -302,9 +311,11 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
cd->polishItems();
+ emit window->afterAnimating();
+
qint64 renderTime = 0, syncTime = 0;
QElapsedTimer renderTimer;
- bool profileFrames = qsg_render_timing() || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing() || QQuickProfiler::enabled;
if (profileFrames)
renderTimer.start();
@@ -343,13 +354,10 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
lastFrameTime = QTime::currentTime();
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphRenderLoopFrame,
- syncTime,
- renderTime,
- swapTime);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphRenderLoopFrame, (
+ syncTime,
+ renderTime,
+ swapTime));
// Might have been set during syncSceneGraph()
if (data.updatePending)
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 207a4915e1..7b5f161174 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -58,7 +58,7 @@
#include "qsgthreadedrenderloop_p.h"
#include <private/qquickanimatorcontroller_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
/*
Overall design:
@@ -539,7 +539,7 @@ void QSGRenderThread::sync()
void QSGRenderThread::syncAndRender()
{
#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames) {
sinceLastTime = threadTimer.nsecsElapsed();
threadTimer.start();
@@ -609,13 +609,10 @@ void QSGRenderThread::syncAndRender()
int((renderTime - syncTime)/1000000),
int(threadTimer.elapsed() - renderTime/1000000));
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphRenderLoopFrame,
- syncTime,
- renderTime - syncTime,
- threadTimer.nsecsElapsed() - renderTime);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphRenderLoopFrame, (
+ syncTime,
+ renderTime - syncTime,
+ threadTimer.nsecsElapsed() - renderTime));
#endif
}
@@ -917,7 +914,17 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
if (!w->thread->gl->create()) {
delete w->thread->gl;
w->thread->gl = 0;
- qWarning("QtQuick: failed to create OpenGL context");
+ QString formatStr;
+ QDebug(&formatStr) << w->window->requestedFormat();
+ QString contextType = QLatin1String(QOpenGLFunctions::isES() ? "EGL" : "OpenGL");
+ const char *msg = QT_TRANSLATE_NOOP("QSGThreadedRenderLoop",
+ "Failed to create %1 context for format %2");
+ QString translatedMsg = tr(msg).arg(contextType).arg(formatStr);
+ QString nonTranslatedMsg = QString(QLatin1String(msg)).arg(contextType).arg(formatStr);
+ bool signalEmitted = QQuickWindowPrivate::get(w->window)->emitError(QQuickWindow::ContextNotAvailable,
+ translatedMsg);
+ if (!signalEmitted)
+ qFatal("%s", qPrintable(nonTranslatedMsg));
return;
}
@@ -1084,7 +1091,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
qint64 polishTime = 0;
qint64 waitTime = 0;
qint64 syncTime = 0;
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames)
timer.start();
#endif
@@ -1099,6 +1106,8 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
w->updateDuringSync = false;
+ emit w->window->afterAnimating();
+
QSG_GUI_DEBUG(w->window, " - lock for sync...");
w->thread->mutex.lock();
m_locked = true;
@@ -1143,14 +1152,11 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
int((syncTime - waitTime)/1000000),
int((timer.nsecsElapsed() - syncTime)/1000000));
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphPolishAndSync,
- polishTime,
- waitTime - polishTime,
- syncTime - waitTime,
- timer.nsecsElapsed() - syncTime);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphPolishAndSync, (
+ polishTime,
+ waitTime - polishTime,
+ syncTime - waitTime,
+ timer.nsecsElapsed() - syncTime));
#endif
}
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 6a6a6ab570..8af0401478 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -42,6 +42,7 @@
#include "qsgwindowsrenderloop_p.h"
#include <QtCore/QCoreApplication>
+#include <QtCore/QLibraryInfo>
#include <QtGui/QScreen>
#include <QtGui/QGuiApplication>
@@ -51,7 +52,7 @@
#include <QtQuick/QQuickWindow>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
QT_BEGIN_NAMESPACE
@@ -69,7 +70,7 @@ static QElapsedTimer qsg_debug_timer;
#ifndef QSG_NO_RENDER_TIMING
static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty();
static QElapsedTimer qsg_render_timer;
-#define QSG_RENDER_TIMING_SAMPLE(sampleName) qint64 sampleName = 0; if (qsg_render_timing || QQmlProfilerService::enabled) sampleName = qsg_render_timer.nsecsElapsed()
+#define QSG_RENDER_TIMING_SAMPLE(sampleName) qint64 sampleName = 0; if (qsg_render_timing || QQuickProfiler::enabled) sampleName = qsg_render_timer.nsecsElapsed()
#else
#define QSG_RENDER_TIMING_SAMPLE(sampleName)
#endif
@@ -182,9 +183,35 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window)
m_gl->setShareContext(QSGContext::sharedOpenGLContext());
bool created = m_gl->create();
if (!created) {
- qWarning("QtQuick: failed to create OpenGL context");
+ const bool isDebug = QLibraryInfo::isDebugBuild();
+ QString eglLibName = QLatin1String(isDebug ? "libEGLd.dll" : "libEGL.dll");
+ QString glesLibName = QLatin1String(isDebug ? "libGLESv2d.dll" : "libGLESv2.dll");
+ QString contextType = QLatin1String(QOpenGLFunctions::isES() ? "EGL" : "OpenGL");
+ const char *msg = QT_TRANSLATE_NOOP(
+ "QSGWindowsRenderLoop",
+ "Failed to create %1 context. "
+ "This is most likely caused by not having the necessary graphics drivers installed.\n\n"
+ "Install a driver providing OpenGL 2.0 or higher, or, if this is not possible, "
+ "make sure the Angle Open GL ES 2.0 emulation libraries (%2, %3 and d3dcompiler_*.dll) "
+ "are available in the application executable's directory or in a location listed in PATH.");
+ QString translatedMsg = tr(msg).arg(contextType).arg(eglLibName).arg(glesLibName);
+ QString nonTranslatedMsg = QString(QLatin1String(msg)).arg(contextType).arg(eglLibName).arg(glesLibName);
+ // If there is a slot connected to the error signal, emit it and leave it to
+ // the application to do something with the message. If nothing is connected,
+ // show a message on our own and terminate.
+ bool signalEmitted = QQuickWindowPrivate::get(window)->emitError(QQuickWindow::ContextNotAvailable,
+ translatedMsg);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+ if (!signalEmitted && !isDebug && !GetConsoleWindow()) {
+ MessageBox(0, (LPCTSTR) translatedMsg.utf16(),
+ (LPCTSTR)(QCoreApplication::applicationName().utf16()),
+ MB_OK | MB_ICONERROR);
+ }
+#endif // !Q_OS_WINCE && !Q_OS_WINRT
delete m_gl;
m_gl = 0;
+ if (!signalEmitted)
+ qFatal("%s", qPrintable(nonTranslatedMsg));
return;
}
QSG_RENDER_TIMING_SAMPLE(time_created);
@@ -202,13 +229,10 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window)
int((time_current - time_created)/1000000),
int((qsg_render_timer.nsecsElapsed() - time_current)/1000000));
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphWindowsRenderShow,
- time_created - time_start,
- time_current - time_created,
- qsg_render_timer.nsecsElapsed() - time_current);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphWindowsRenderShow, (
+ time_created - time_start,
+ time_current - time_created,
+ qsg_render_timer.nsecsElapsed() - time_current));
#endif
}
@@ -407,11 +431,8 @@ void QSGWindowsRenderLoop::render()
qDebug("WindowsRenderLoop: animations=%d ms",
int((qsg_render_timer.nsecsElapsed() - time_start)/1000000));
}
- if (QQmlProfilerService::Enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphWindowsAnimations,
- qsg_render_timer.nsecsElapsed() - time_start);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphWindowsAnimations, (
+ qsg_render_timer.nsecsElapsed() - time_start));
#endif
// It is not given that animations triggered another maybeUpdate()
@@ -448,6 +469,8 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
d->polishItems();
QSG_RENDER_TIMING_SAMPLE(time_polished);
+ emit window->afterAnimating();
+
RLDEBUG(" - syncing");
d->syncSceneGraph();
QSG_RENDER_TIMING_SAMPLE(time_synced);
@@ -473,19 +496,13 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
int((time_rendered - time_synced)/1000000),
int((time_swapped - time_rendered)/1000000));
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphWindowsPolishFrame,
- time_polished - time_start
- );
-
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphRenderLoopFrame,
- time_synced - time_polished,
- time_rendered - time_synced,
- time_swapped - time_rendered
- );
- }
+
+ Q_QUICK_SG_PROFILE2(QQuickProfiler::SceneGraphWindowsPolishFrame,
+ QQuickProfiler::SceneGraphRenderLoopFrame, (
+ time_synced - time_polished,
+ time_rendered - time_synced,
+ time_swapped - time_rendered,
+ time_polished - time_start));
#endif
}
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 6868e10b90..570d6b92b5 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -160,5 +160,7 @@ OTHER_FILES += \
$$PWD/shaders/textmask_core.vert \
$$PWD/shaders/texture_core.frag \
$$PWD/shaders/vertexcolor_core.frag \
- $$PWD/shaders/vertexcolor_core.vert
+ $$PWD/shaders/vertexcolor_core.vert \
+ scenegraph/shaders/visualization.frag \
+ scenegraph/shaders/visualization.vert
diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc
index 2be8b246d3..e6a90c9120 100644
--- a/src/quick/scenegraph/scenegraph.qrc
+++ b/src/quick/scenegraph/scenegraph.qrc
@@ -64,5 +64,7 @@
<file>shaders/texture_core.frag</file>
<file>shaders/vertexcolor_core.frag</file>
<file>shaders/vertexcolor_core.vert</file>
+ <file>shaders/visualization.vert</file>
+ <file>shaders/visualization.frag</file>
</qresource>
</RCC>
diff --git a/src/quick/scenegraph/shaders/visualization.frag b/src/quick/scenegraph/shaders/visualization.frag
new file mode 100644
index 0000000000..205b726c03
--- /dev/null
+++ b/src/quick/scenegraph/shaders/visualization.frag
@@ -0,0 +1,11 @@
+uniform lowp vec4 color;
+uniform mediump vec4 tweak; // x,y -> width, height; z -> intensity of ;
+
+varying mediump vec2 pos;
+
+void main(void)
+{
+ lowp vec4 c = color;
+ c.xyz += pow(max(sin(pos.x + pos.y), 0.0), 2.0) * tweak.z * 0.1;
+ gl_FragColor = c;
+}
diff --git a/src/quick/scenegraph/shaders/visualization.vert b/src/quick/scenegraph/shaders/visualization.vert
new file mode 100644
index 0000000000..f1892b71da
--- /dev/null
+++ b/src/quick/scenegraph/shaders/visualization.vert
@@ -0,0 +1,22 @@
+attribute highp vec4 v;
+uniform highp mat4 matrix;
+uniform highp mat4 rotation;
+
+// w -> apply 3d rotation and projection
+uniform lowp vec4 tweak;
+
+varying mediump vec2 pos;
+
+void main()
+{
+ vec4 p = matrix * v;
+
+ if (tweak.w > 0.0) {
+ vec4 proj = rotation * p;
+ gl_Position = vec4(proj.x, proj.y, 0, proj.z);
+ } else {
+ gl_Position = p;
+ }
+
+ pos = v.xy * 1.37;
+}
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 378451c307..333bc62143 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -52,7 +52,7 @@
#include <private/qsgtexture_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
QT_BEGIN_NAMESPACE
@@ -140,7 +140,6 @@ Atlas::Atlas(const QSize &size)
: m_allocator(size)
, m_texture_id(0)
, m_size(size)
- , m_filtering(QSGTexture::Linear)
, m_allocated(false)
{
@@ -148,9 +147,10 @@ Atlas::Atlas(const QSize &size)
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
- static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0;
+ static bool wrongfullyReportsBgra8888Support = deviceName != 0
+ && (deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0);
#else
static bool wrongfullyReportsBgra8888Support = false;
#endif
@@ -314,9 +314,8 @@ void Atlas::uploadBgra(Texture *texture)
}
-bool Atlas::bind(QSGTexture::Filtering filtering)
+void Atlas::bind(QSGTexture::Filtering filtering)
{
- bool forceUpdate = false;
if (!m_allocated) {
m_allocated = true;
@@ -361,19 +360,18 @@ bool Atlas::bind(QSGTexture::Filtering filtering)
glDeleteTextures(1, &m_texture_id);
m_texture_id = 0;
}
- forceUpdate = true;
} else {
glBindTexture(GL_TEXTURE_2D, m_texture_id);
}
if (m_texture_id == 0)
- return false;
+ return;
// Upload all pending images..
for (int i=0; i<m_pending_uploads.size(); ++i) {
#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames)
qsg_renderer_timer.start();
#endif
@@ -393,28 +391,20 @@ bool Atlas::bind(QSGTexture::Filtering filtering)
(int) (qsg_renderer_timer.elapsed()));
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphTexturePrepare,
- 0, // bind (not relevant)
- 0, // convert (not relevant)
- 0, // swizzle (not relevant)
- qsg_renderer_timer.nsecsElapsed(), // (upload all of the above)
- 0); // mipmap (not used ever...)
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTexturePrepare, (
+ 0, // bind (not relevant)
+ 0, // convert (not relevant)
+ 0, // swizzle (not relevant)
+ qsg_renderer_timer.nsecsElapsed(), // (upload all of the above)
+ 0)); // mipmap (not used ever...)
#endif
}
- if (filtering != m_filtering) {
- GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f);
- m_filtering = filtering;
- }
+ GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f);
m_pending_uploads.clear();
-
- return forceUpdate;
}
void Atlas::remove(Texture *t)
@@ -461,6 +451,7 @@ QSGTexture *Texture::removedFromAtlas() const
m_nonatlas_texture = new QSGPlainTexture();
m_nonatlas_texture->setImage(m_image);
m_nonatlas_texture->setFiltering(filtering());
+ m_nonatlas_texture->setMipmapFiltering(mipmapFiltering());
}
return m_nonatlas_texture;
}
diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h
index ade7b8f00e..51439cdb26 100644
--- a/src/quick/scenegraph/util/qsgatlastexture_p.h
+++ b/src/quick/scenegraph/util/qsgatlastexture_p.h
@@ -85,7 +85,7 @@ public:
void invalidate();
int textureId() const;
- bool bind(QSGTexture::Filtering filteing);
+ void bind(QSGTexture::Filtering filtering);
void upload(Texture *texture);
void uploadBgra(Texture *texture);
@@ -104,8 +104,6 @@ private:
GLuint m_internalFormat;
GLuint m_externalFormat;
- QSGTexture::Filtering m_filtering;
-
uint m_allocated : 1;
uint m_use_bgra_fallback: 1;
diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp
index 797fc4d145..ec44a994e0 100644
--- a/src/quick/scenegraph/util/qsgpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgpainternode.cpp
@@ -205,7 +205,6 @@ void QSGPainterNode::update()
void QSGPainterNode::updateTexture()
{
- m_texture->setHasMipmaps(m_mipmapping);
m_texture->setHasAlphaChannel(!m_opaquePainting);
m_material.setTexture(m_texture);
m_materialO.setTexture(m_texture);
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index bfa0eaf920..3bbcb0c112 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -45,7 +45,7 @@
#include <qopenglfunctions.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <qthread.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
#include <private/qqmlglobal_p.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
@@ -533,7 +533,6 @@ QSGPlainTexture::QSGPlainTexture()
: QSGTexture()
, m_texture_id(0)
, m_has_alpha(false)
- , m_has_mipmaps(false)
, m_dirty_texture(false)
, m_dirty_bind_options(false)
, m_owns_texture(true)
@@ -597,18 +596,11 @@ void QSGPlainTexture::setTextureId(int id)
m_mipmaps_generated = false;
}
-void QSGPlainTexture::setHasMipmaps(bool mm)
-{
- m_has_mipmaps = mm;
- m_mipmaps_generated = false;
-}
-
-
void QSGPlainTexture::bind()
{
if (!m_dirty_texture) {
glBindTexture(GL_TEXTURE_2D, m_texture_id);
- if (m_has_mipmaps && !m_mipmaps_generated) {
+ if (mipmapFiltering() != QSGTexture::None && !m_mipmaps_generated) {
QOpenGLContext *ctx = QOpenGLContext::currentContext();
ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
m_mipmaps_generated = true;
@@ -621,7 +613,7 @@ void QSGPlainTexture::bind()
m_dirty_texture = false;
#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+ bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
if (profileFrames)
qsg_renderer_timer.start();
#endif
@@ -636,20 +628,14 @@ void QSGPlainTexture::bind()
m_texture_size.width(),
m_texture_size.height());
}
- if (QQmlProfilerService::enabled) {
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphTextureDeletion,
- qsg_renderer_timer.nsecsElapsed());
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTextureDeletion, (
+ qsg_renderer_timer.nsecsElapsed()));
#endif
}
m_texture_id = 0;
m_texture_size = QSize();
- m_has_mipmaps = false;
m_has_alpha = false;
-
-
return;
}
@@ -687,9 +673,10 @@ void QSGPlainTexture::bind()
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
- static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0;
+ static bool wrongfullyReportsBgra8888Support = deviceName != 0
+ && (deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0);
#else
static bool wrongfullyReportsBgra8888Support = false;
#endif
@@ -728,7 +715,7 @@ void QSGPlainTexture::bind()
#endif
- if (m_has_mipmaps) {
+ if (mipmapFiltering() != QSGTexture::None) {
context->functions()->glGenerateMipmap(GL_TEXTURE_2D);
m_mipmaps_generated = true;
}
@@ -751,17 +738,12 @@ void QSGPlainTexture::bind()
}
- if (QQmlProfilerService::enabled) {
- mipmapTime = qsg_renderer_timer.nsecsElapsed();
-
- QQmlProfilerService::sceneGraphFrame(
- QQmlProfilerService::SceneGraphTexturePrepare,
- bindTime,
- convertTime - bindTime,
- swizzleTime - convertTime,
- uploadTime - swizzleTime,
- mipmapTime - uploadTime);
- }
+ Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTexturePrepare, (
+ bindTime,
+ convertTime - bindTime,
+ swizzleTime - convertTime,
+ uploadTime - swizzleTime,
+ qsg_renderer_timer.nsecsElapsed() - uploadTime));
#endif
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
index e0d386e20c..bc81569f84 100644
--- a/src/quick/scenegraph/util/qsgtexture_p.h
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -85,8 +85,7 @@ public:
void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
bool hasAlphaChannel() const { return m_has_alpha; }
- void setHasMipmaps(bool mm);
- bool hasMipmaps() const { return m_has_mipmaps; }
+ bool hasMipmaps() const { return mipmapFiltering() != QSGTexture::None; }
void setImage(const QImage &image);
const QImage &image() { return m_image; }
@@ -107,7 +106,6 @@ protected:
QRectF m_texture_rect;
uint m_has_alpha : 1;
- uint m_has_mipmaps : 1;
uint m_dirty_texture : 1;
uint m_dirty_bind_options : 1;
uint m_owns_texture : 1;
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index fa6f615649..3bc4cef5b9 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -271,7 +271,7 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller
m_helper = new Helper();
m_helper->item = m_target;
m_controller->m_transforms.insert(m_target, m_helper);
- QObject::connect(m_target, SIGNAL(destroyed(QObject *)), m_controller, SLOT(itemDestroyed(QObject*)), Qt::DirectConnection);
+ QObject::connect(m_target, SIGNAL(destroyed(QObject*)), m_controller, SLOT(itemDestroyed(QObject*)), Qt::DirectConnection);
} else {
++m_helper->ref;
// Make sure leftovers from previous runs are being used...
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index 460e2ca554..74e5b40ab1 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -180,12 +180,15 @@ void QQuickBehavior::write(const QVariant &value)
if (!bypass)
qmlExecuteDeferred(this);
if (!d->animation || bypass) {
+ if (d->animationInstance)
+ d->animationInstance->stop();
QQmlPropertyPrivate::write(d->property, value, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
d->targetValue = value;
return;
}
- if (d->animation->isRunning() && value == d->targetValue)
+ bool behaviorActive = d->animation->isRunning();
+ if (behaviorActive && value == d->targetValue)
return;
d->targetValue = value;
@@ -201,6 +204,14 @@ void QQuickBehavior::write(const QVariant &value)
// to the item, so we need to read the value after.
const QVariant &currentValue = d->property.read();
+ // Don't unnecessarily wake up the animation system if no real animation
+ // is needed (value has not changed). If the Behavior was already
+ // running, let it continue as normal to ensure correct behavior and state.
+ if (!behaviorActive && d->targetValue == currentValue) {
+ QQmlPropertyPrivate::write(d->property, value, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ return;
+ }
+
QQuickStateOperation::ActionList actions;
QQuickStateAction action;
action.property = d->property;
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 152d1f34c9..5ae74c2fec 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -398,7 +398,7 @@ public:
if (!array)
return QMatrix4x4();
- if (array->arrayLength() != 16)
+ if (array->getLength() != 16)
return QMatrix4x4();
float matVals[16];
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index 450238bd41..16c18d2594 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -147,8 +147,8 @@ QImage QQuickTextureFactory::image() const
Image { source: "image://myimageprovider/image.png" }
\endqml
- This specifies that the image should be loaded by the image provider named
- "myimageprovider", and the image to be loaded is named "image.png". The QML engine
+ This specifies that the image should be loaded by the image provider named
+ "myimageprovider", and the image to be loaded is named "image.png". The QML engine
invokes the appropriate image provider according to the providers that have
been registered through QQmlEngine::addImageProvider().
@@ -173,11 +173,11 @@ QImage QQuickTextureFactory::image() const
When these images are loaded by QML, it looks for a matching image provider
and calls its requestImage() or requestPixmap() method (depending on its
- imageType()) to load the image. The method is called with the \c id
+ imageType()) to load the image. The method is called with the \c id
parameter set to "yellow" for the first image, and "red" for the second.
- Here is an image provider implementation that can load the images
- requested by the above QML. This implementation dynamically
+ Here is an image provider implementation that can load the images
+ requested by the above QML. This implementation dynamically
generates QPixmap images that are filled with the requested color:
\snippet imageprovider/imageprovider.cpp 0
@@ -188,7 +188,7 @@ QImage QQuickTextureFactory::image() const
with a "colors" identifier:
\code
- int main(int argc, char *argv[])
+ int main(int argc, char *argv[])
{
...
@@ -203,7 +203,7 @@ QImage QQuickTextureFactory::image() const
\image imageprovider.png
- A complete example is available in Qt's
+ A complete example is available in Qt's
\l {qml/imageprovider}{examples/quick/imageprovider}
directory. Note the example registers the provider via a \l{QQmlExtensionPlugin}{plugin}
instead of registering it in the application \c main() function as shown above.
@@ -214,7 +214,7 @@ QImage QQuickTextureFactory::image() const
Image providers that support QImage or Texture loading automatically include support
for asychronous loading of images. To enable asynchronous loading for an
image source, set the \c asynchronous property to \c true for the relevant
- \l Image, \l BorderImage or \l AnimatedImage object. When this is enabled,
+ \l Image, \l BorderImage or \l AnimatedImage object. When this is enabled,
the image request to the provider is run in a low priority thread,
allowing image loading to be executed in the background, and reducing the
performance impact on the user interface.
@@ -285,7 +285,7 @@ QQuickImageProvider::Flags QQuickImageProvider::flags() const
}
/*!
- Implement this method to return the image with \a id. The default
+ Implement this method to return the image with \a id. The default
implementation returns an empty image.
The \a id is the requested image source, with the "image:" scheme and
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 055d6b7e29..a7f9174219 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -71,7 +71,7 @@
#include <QQmlFile>
#include <QMetaMethod>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
@@ -234,7 +234,7 @@ class QQuickPixmapData
{
public:
QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QString &e)
- : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error),
+ : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error),
url(u), errorString(e), requestSize(s), textureFactory(0), reply(0), prevUnreferenced(0),
prevUnreferencedPtr(0), nextUnreferenced(0)
{
@@ -242,7 +242,7 @@ public:
}
QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r)
- : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading),
+ : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading),
url(u), requestSize(r), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
nextUnreferenced(0)
{
@@ -286,7 +286,7 @@ public:
uint refCount;
bool inCache:1;
-
+
QQuickPixmap::Status pixmapStatus;
QUrl url;
QString errorString;
@@ -337,7 +337,7 @@ QNetworkAccessManager *QQuickPixmapReader::networkAccessManager()
return accessManager;
}
-static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
+static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
const QSize &requestSize)
{
QImageReader imgio(dev);
@@ -469,17 +469,17 @@ QQuickPixmapReaderThreadObject::QQuickPixmapReaderThreadObject(QQuickPixmapReade
{
}
-void QQuickPixmapReaderThreadObject::processJobs()
-{
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+void QQuickPixmapReaderThreadObject::processJobs()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
-bool QQuickPixmapReaderThreadObject::event(QEvent *e)
+bool QQuickPixmapReaderThreadObject::event(QEvent *e)
{
- if (e->type() == QEvent::User) {
- reader->processJobs();
- return true;
- } else {
+ if (e->type() == QEvent::User) {
+ reader->processJobs();
+ return true;
+ } else {
return QObject::event(e);
}
}
@@ -495,7 +495,7 @@ void QQuickPixmapReader::processJobs()
QMutexLocker locker(&mutex);
while (true) {
- if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
+ if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
return; // Nothing else to do
// Clean cancelled jobs
@@ -519,8 +519,7 @@ void QQuickPixmapReader::processJobs()
runningJob->loading = true;
QUrl url = runningJob->url;
- QQmlPixmapProfiler pixmapProfiler;
- pixmapProfiler.startLoading(url);
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
QSize requestSize = runningJob->requestSize;
locker.unlock();
@@ -530,7 +529,7 @@ void QQuickPixmapReader::processJobs()
}
}
-void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url,
+void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url,
const QSize &requestSize)
{
// fetch
@@ -650,7 +649,7 @@ QQuickPixmapReply *QQuickPixmapReader::getImage(QQuickPixmapData *data)
QQuickPixmapReply *reply = new QQuickPixmapReply(data);
reply->engineForReader = engine;
jobs.append(reply);
- // XXX
+ // XXX
if (threadObject) threadObject->processJobs();
mutex.unlock();
return reply;
@@ -662,7 +661,7 @@ void QQuickPixmapReader::cancel(QQuickPixmapReply *reply)
if (reply->loading) {
cancelled.append(reply);
reply->data = 0;
- // XXX
+ // XXX
if (threadObject) threadObject->processJobs();
} else {
jobs.removeAll(reply);
@@ -817,7 +816,7 @@ void QQuickPixmapStore::referencePixmap(QQuickPixmapData *data)
Q_ASSERT(data->prevUnreferencedPtr);
*data->prevUnreferencedPtr = data->nextUnreferenced;
- if (data->nextUnreferenced) {
+ if (data->nextUnreferenced) {
data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr;
data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced;
}
@@ -895,14 +894,13 @@ bool QQuickPixmapReply::event(QEvent *event)
if (data) {
Event *de = static_cast<Event *>(event);
data->pixmapStatus = (de->error == NoError) ? QQuickPixmap::Ready : QQuickPixmap::Error;
- QQmlPixmapProfiler pixmapProfiler;
if (data->pixmapStatus == QQuickPixmap::Ready) {
- pixmapProfiler.finishLoading(data->url);
data->textureFactory = de->textureFactory;
data->implicitSize = de->implicitSize;
- pixmapProfiler.setSize(url, data->requestSize.width() > 0 ? data->requestSize : data->implicitSize);
+ Q_QUICK_PROFILE(pixmapLoadingFinished(data->url,
+ data->requestSize.width() > 0 ? data->requestSize : data->implicitSize));
} else {
- pixmapProfiler.errorLoading(data->url);
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(data->url));
data->errorString = de->errorString;
data->removeFromCache(); // We don't continue to cache error'd pixmaps
}
@@ -928,8 +926,8 @@ int QQuickPixmapData::cost() const
void QQuickPixmapData::addref()
{
++refCount;
- QQmlPixmapProfiler().referenceCountChanged(url, refCount);
- if (prevUnreferencedPtr)
+ Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
+ if (prevUnreferencedPtr)
pixmapStore()->referencePixmap(this);
}
@@ -937,7 +935,7 @@ void QQuickPixmapData::release()
{
Q_ASSERT(refCount > 0);
--refCount;
- QQmlPixmapProfiler().referenceCountChanged(url, refCount);
+ Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
if (refCount == 0) {
if (reply) {
QQuickPixmapReply *cancelReply = reply;
@@ -968,8 +966,8 @@ void QQuickPixmapData::addToCache()
QQuickPixmapKey key = { &url, &requestSize };
pixmapStore()->m_cache.insert(key, this);
inCache = true;
- QQmlPixmapProfiler pixmapProfiler;
- pixmapProfiler.cacheCountChanged(url, pixmapStore()->m_cache.count());
+ Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
+ url, pixmapStore()->m_cache.count()));
}
}
@@ -977,7 +975,8 @@ void QQuickPixmapData::removeFromCache()
{
if (inCache) {
QQuickPixmapKey key = { &url, &requestSize };
- QQmlPixmapProfiler().cacheCountChanged(url, pixmapStore()->m_cache.count());
+ Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
+ url, pixmapStore()->m_cache.count()));
pixmapStore()->m_cache.remove(key);
inCache = false;
}
@@ -1030,7 +1029,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
}
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
- if (localFile.isEmpty())
+ if (localFile.isEmpty())
return 0;
QFile f(localFile);
@@ -1131,7 +1130,7 @@ const QUrl &QQuickPixmap::url() const
const QSize &QQuickPixmap::implicitSize() const
{
- if (d)
+ if (d)
return d->implicitSize;
else
return nullPixmap()->size;
@@ -1240,21 +1239,20 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
if (!(options & QQuickPixmap::Asynchronous)) {
bool ok = false;
- QQmlPixmapProfiler pixmapProfiler;
- pixmapProfiler.startLoading(url);
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
d = createPixmapDataSync(this, engine, url, requestSize, &ok);
if (ok) {
- pixmapProfiler.finishLoading(url);
- pixmapProfiler.setSize(url, d->requestSize.width() > 0 ? d->requestSize : d->implicitSize);
+ Q_QUICK_PROFILE(pixmapLoadingFinished(url,
+ d->requestSize.width() > 0 ? d->requestSize : d->implicitSize));
if (options & QQuickPixmap::Cache)
d->addToCache();
return;
}
if (d) { // loadable, but encountered error while loading
- pixmapProfiler.errorLoading(url);
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
return;
}
- }
+ }
if (!engine)
return;
@@ -1285,7 +1283,7 @@ void QQuickPixmap::clear()
void QQuickPixmap::clear(QObject *obj)
{
if (d) {
- if (d->reply)
+ if (d->reply)
QObject::disconnect(d->reply, 0, obj, 0);
d->declarativePixmaps.remove(this);
d->release();
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
new file mode 100644
index 0000000000..a706fb1e77
--- /dev/null
+++ b/src/quick/util/qquickprofiler.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickprofiler_p.h"
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmlprofilerservice_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// instance will be set, unset in constructor. Allows static methods to be inlined.
+QQuickProfiler *QQuickProfiler::s_instance = 0;
+bool QQuickProfiler::enabled = false;
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+// (see tst_qqmldebugtrace::trace() benchmark)
+void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
+{
+ QByteArray data;
+ Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
+ for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
+ if ((messageType & (1 << decodedMessageType)) == 0)
+ continue;
+
+ for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
+ if ((detailType & (1 << decodedDetailType)) == 0)
+ continue;
+
+ //### using QDataStream is relatively expensive
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << time << decodedMessageType << decodedDetailType;
+
+ switch (decodedMessageType) {
+ case QQuickProfiler::Event:
+ if (decodedDetailType == (int)QQuickProfiler::AnimationFrame)
+ ds << framerate << count;
+ break;
+ case QQuickProfiler::PixmapCacheEvent:
+ ds << detailUrl.toString();
+ switch (decodedDetailType) {
+ case QQuickProfiler::PixmapSizeKnown: ds << x << y; break;
+ case QQuickProfiler::PixmapReferenceCountChanged: ds << count; break;
+ case QQuickProfiler::PixmapCacheCountChanged: ds << count; break;
+ default: break;
+ }
+ break;
+ case QQuickProfiler::SceneGraphFrame:
+ switch (decodedDetailType) {
+ // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
+ case QQuickProfiler::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
+ // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
+ case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << (int)subtime_1 << subtime_2 << subtime_3; break;
+ // ContextFrame: compiling material time
+ case QQuickProfiler::SceneGraphContextFrame: ds << subtime_1; break;
+ // RenderLoop: syncTime, renderTime, swapTime
+ case QQuickProfiler::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break;
+ // TexturePrepare: bind, convert, swizzle, upload, mipmap
+ case QQuickProfiler::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break;
+ // TextureDeletion: deletionTime
+ case QQuickProfiler::SceneGraphTextureDeletion: ds << subtime_1; break;
+ // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
+ case QQuickProfiler::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
+ // WindowsRenderLoop: GL time, make current time, SceneGraph time
+ case QQuickProfiler::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break;
+ // WindowsAnimations: update time
+ case QQuickProfiler::SceneGraphWindowsAnimations: ds << subtime_1; break;
+ // WindowsRenderWindow: polish time; always comes packed after a RenderLoop
+ case QQuickProfiler::SceneGraphWindowsPolishFrame: ds << subtime_4; break;
+ default:break;
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
+ }
+ messages << data;
+ data.clear();
+ }
+ }
+}
+
+qint64 QQuickProfiler::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ QMutexLocker lock(&m_dataMutex);
+ while (next < m_data.size() && m_data[next].time <= until) {
+ m_data[next++].toByteArrays(messages);
+ }
+ return next < m_data.size() ? m_data[next].time : -1;
+}
+
+void QQuickProfiler::initialize()
+{
+ Q_ASSERT(s_instance == 0);
+ QQmlProfilerService *service = QQmlProfilerService::instance();
+ s_instance = new QQuickProfiler(service);
+ QQmlProfilerService::instance()->addGlobalProfiler(s_instance);
+}
+
+void animationTimerCallback(qint64 delta)
+{
+ Q_QUICK_PROFILE(animationFrame(delta));
+}
+
+QQuickProfiler::QQuickProfiler(QQmlProfilerService *service) :
+ QQmlAbstractProfilerAdapter(service), next(0)
+{
+ // This is safe because at this point the m_instance isn't initialized, yet.
+ m_timer.start();
+
+ // We can always do DirectConnection here as all methods are protected by mutexes
+ connect(this, SIGNAL(profilingEnabled()), this, SLOT(startProfilingImpl()),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(profilingEnabledWhileWaiting()), this, SLOT(startProfilingImpl()),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), this, SLOT(setTimer(QElapsedTimer)),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfilingImpl()),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()), this, SLOT(stopProfilingImpl()),
+ Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), this, SLOT(reportDataImpl()),
+ Qt::DirectConnection);
+
+ QUnifiedTimer::instance()->registerProfilerCallback(&animationTimerCallback);
+}
+
+QQuickProfiler::~QQuickProfiler()
+{
+ QMutexLocker lock(&m_dataMutex);
+ enabled = false;
+ s_instance = 0;
+}
+
+void QQuickProfiler::startProfilingImpl()
+{
+ QMutexLocker lock(&m_dataMutex);
+ next = 0;
+ m_data.clear();
+ enabled = true;
+}
+
+void QQuickProfiler::stopProfilingImpl()
+{
+ {
+ QMutexLocker lock(&m_dataMutex);
+ enabled = false;
+ next = 0;
+ }
+ service->dataReady(this);
+}
+
+void QQuickProfiler::reportDataImpl()
+{
+ {
+ QMutexLocker lock(&m_dataMutex);
+ next = 0;
+ }
+ service->dataReady(this);
+}
+
+void QQuickProfiler::setTimer(const QElapsedTimer &t)
+{
+ QMutexLocker lock(&m_dataMutex);
+ m_timer = t;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
new file mode 100644
index 0000000000..721560b9e5
--- /dev/null
+++ b/src/quick/util/qquickprofiler_p.h
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPROFILER_P_H
+#define QQUICKPROFILER_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/qtquickglobal_p.h>
+#include <QtCore/private/qabstractanimation_p.h>
+#include <QtQml/private/qqmlabstractprofileradapter_p.h>
+#include <QUrl>
+#include <QSize>
+#include <QMutex>
+
+QT_BEGIN_NAMESPACE
+
+#define Q_QUICK_PROFILE_IF_ENABLED(Code)\
+ if (QQuickProfiler::enabled) {\
+ Code;\
+ } else\
+ (void)0
+
+#define Q_QUICK_PROFILE(Method)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::Method)
+
+#define Q_QUICK_SG_PROFILE2(Type1, Type2, Params)\
+ Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::sceneGraphFrame<Type1, Type2> Params))
+
+#define Q_QUICK_SG_PROFILE1(Type, Params) Q_QUICK_SG_PROFILE2(Type, Type, Params)
+
+
+// This struct is somewhat dangerous to use:
+// You can save values either with 32 or 64 bit precision. toByteArrays will
+// guess the precision from messageType. If you state the wrong messageType
+// you will get undefined results.
+// The messageType is itself a bit field. You can pack multiple messages into
+// one object, e.g. RangeStart and RangeLocation. Each one will be read
+// independently by toByteArrays. Thus you can only pack messages if their data
+// doesn't overlap. Again, it's up to you to figure that out.
+struct Q_AUTOTEST_EXPORT QQuickProfilerData
+{
+ QQuickProfilerData() {}
+
+ QQuickProfilerData(qint64 time, int messageType, int detailType, const QUrl &url, int x = 0,
+ int y = 0, int framerate = 0, int count = 0) :
+ time(time), messageType(messageType), detailType(detailType), detailUrl(url), x(x), y(y),
+ framerate(framerate), count(count) {}
+
+ QQuickProfilerData(qint64 time, int messageType, int detailType, int framerate = 0,
+ int count = 0) :
+ time(time), messageType(messageType), detailType(detailType), framerate(framerate),
+ count(count) {}
+
+ // Special ctor for scenegraph frames. Note that it's missing the QString/QUrl params.
+ // This is slightly ugly, but makes it easier to disambiguate between int and qint64 params.
+ QQuickProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2,
+ qint64 d3, qint64 d4, qint64 d5) :
+ time(time), messageType(messageType), detailType(detailType), subtime_1(d1), subtime_2(d2),
+ subtime_3(d3), subtime_4(d4), subtime_5(d5) {}
+
+
+ qint64 time;
+ int messageType; //bit field of Message
+ int detailType;
+
+ QUrl detailUrl;
+
+ union {
+ qint64 subtime_1;
+ int x; //used for pixmaps
+ };
+
+ union {
+ qint64 subtime_2;
+ int y; //used for pixmaps
+ };
+
+ union {
+ qint64 subtime_3;
+ int framerate; //used by animation events
+ };
+
+ union {
+ qint64 subtime_4;
+ int count; //used by animation events and for pixmaps
+ };
+
+ qint64 subtime_5;
+
+ void toByteArrays(QList<QByteArray> &messages) const;
+};
+
+Q_DECLARE_TYPEINFO(QQuickProfilerData, Q_MOVABLE_TYPE);
+
+class Q_QUICK_PRIVATE_EXPORT QQuickProfiler : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
+public:
+
+ template<EventType DetailType>
+ static void addEvent()
+ {
+ s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
+ 1 << DetailType));
+ }
+
+ static void animationFrame(qint64 delta)
+ {
+ int animCount = QUnifiedTimer::instance()->runningAnimationCount();
+
+ if (animCount > 0 && delta > 0) {
+ s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
+ 1 << AnimationFrame, 1000 / (int)delta /* trim fps to integer */, animCount));
+ }
+ }
+
+ template<SceneGraphFrameType FrameType1, SceneGraphFrameType FrameType2>
+ static void sceneGraphFrame(qint64 value1, qint64 value2 = -1, qint64 value3 = -1,
+ qint64 value4 = -1, qint64 value5 = -1)
+ {
+ s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << SceneGraphFrame,
+ 1 << FrameType1 | 1 << FrameType2, value1, value2, value3, value4, value5));
+ }
+
+ template<PixmapEventType PixmapState>
+ static void pixmapStateChanged(const QUrl &url)
+ {
+ s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
+ 1 << PixmapCacheEvent, 1 << PixmapState, url));
+ }
+
+ static void pixmapLoadingFinished(const QUrl &url, const QSize &size)
+ {
+ s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
+ 1 << PixmapCacheEvent,
+ (1 << PixmapLoadingFinished) | ((size.width() > 0 && size.height() > 0) ? (1 << PixmapSizeKnown) : 0),
+ url, size.width(), size.height()));
+ }
+
+ template<PixmapEventType CountType>
+ static void pixmapCountChanged(const QUrl &url, int count)
+ {
+ s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
+ 1 << PixmapCacheEvent, 1 << CountType, url, 0, 0, 0, count));
+ }
+
+ qint64 timestamp() { return m_timer.nsecsElapsed(); }
+
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+ static bool enabled;
+
+ static void initialize();
+
+ virtual ~QQuickProfiler();
+
+protected:
+ int next;
+ static QQuickProfiler *s_instance;
+ QMutex m_dataMutex;
+ QElapsedTimer m_timer;
+ QVarLengthArray<QQuickProfilerData> m_data;
+
+ QQuickProfiler(QQmlProfilerService *service);
+
+ void processMessage(const QQuickProfilerData &message)
+ {
+ QMutexLocker lock(&m_dataMutex);
+ m_data.append(message);
+ }
+
+protected slots:
+ void startProfilingImpl();
+ void stopProfilingImpl();
+ void reportDataImpl();
+ void setTimer(const QElapsedTimer &t);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 9eb6ec70c3..7bb318fd79 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -264,6 +264,29 @@ QQuickPropertyChangesParser::compileList(QList<QPair<QString, QVariant> > &list,
}
}
+void QQuickPropertyChangesParser::compileList(QList<QPair<QString, const QV4::CompiledData::Binding*> > &list, const QString &pre, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding)
+{
+ QString propName = pre + qmlUnit->header.stringAt(binding->propertyNameIndex);
+
+ if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ error(qmlUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects."));
+ return;
+ }
+
+ if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty
+ || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ QString pre = propName + QLatin1Char('.');
+ const QV4::CompiledData::Object *subObj = qmlUnit->objectAt(binding->value.objectIndex);
+ const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
+ for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) {
+ compileList(list, pre, qmlUnit, subBinding);
+ }
+ return;
+ }
+
+ list << qMakePair(propName, binding);
+}
+
QByteArray
QQuickPropertyChangesParser::compile(const QList<QQmlCustomParserProperty> &props)
{
@@ -308,6 +331,44 @@ QQuickPropertyChangesParser::compile(const QList<QQmlCustomParserProperty> &prop
return rv;
}
+QByteArray QQuickPropertyChangesParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props)
+{
+ QList<QPair<QString, const QV4::CompiledData::Binding *> > data;
+ for (int ii = 0; ii < props.count(); ++ii)
+ compileList(data, QString(), qmlUnit, props.at(ii));
+
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ ds << data.count();
+ for (int ii = 0; ii < data.count(); ++ii) {
+ const QV4::CompiledData::Binding *binding = data.at(ii).second;
+ QVariant var;
+ bool isScript = binding->type == QV4::CompiledData::Binding::Type_Script;
+ QQmlBinding::Identifier id = QQmlBinding::Invalid;
+ switch (binding->type) {
+ case QV4::CompiledData::Binding::Type_Script:
+ // ### pre-compile binding
+ case QV4::CompiledData::Binding::Type_String:
+ var = binding->valueAsString(&qmlUnit->header);
+ break;
+ case QV4::CompiledData::Binding::Type_Number:
+ var = binding->valueAsNumber();
+ break;
+ case QV4::CompiledData::Binding::Type_Boolean:
+ var = binding->valueAsBoolean();
+ break;
+ default:
+ break;
+ }
+ ds << data.at(ii).first << isScript << var;
+ if (isScript)
+ ds << id;
+ }
+
+ return rv;
+}
+
void QQuickPropertyChangesPrivate::decode()
{
Q_Q(QQuickPropertyChanges);
diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h
index 0236e4529b..081ea72862 100644
--- a/src/quick/util/qquickpropertychanges_p.h
+++ b/src/quick/util/qquickpropertychanges_p.h
@@ -93,8 +93,10 @@ public:
: QQmlCustomParser(AcceptsAttachedProperties) {}
void compileList(QList<QPair<QString, QVariant> > &list, const QString &pre, const QQmlCustomParserProperty &prop);
+ void compileList(QList<QPair<QString, const QV4::CompiledData::Binding *> > &list, const QString &pre, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding);
virtual QByteArray compile(const QList<QQmlCustomParserProperty> &);
+ virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
virtual void setCustomData(QObject *, const QByteArray &);
};
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index 9e9e6cb419..a0e6c36830 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -43,6 +43,7 @@
#include "qquicksmoothedanimation_p_p.h"
#include "qquickanimation_p_p.h"
+#include "private/qcontinuinganimationgroupjob_p.h"
#include <qqmlproperty.h>
#include <private/qqmlproperty_p.h>
@@ -78,7 +79,7 @@ QSmoothedAnimation::QSmoothedAnimation(QQuickSmoothedAnimationPrivate *priv)
: QAbstractAnimationJob(), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1),
reversingMode(QQuickSmoothedAnimation::Eased), initialVelocity(0),
trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0),
- useDelta(false), delayedStopTimer(new QSmoothedAnimationTimer(this)), animationTemplate(priv)
+ skipUpdate(false), delayedStopTimer(new QSmoothedAnimationTimer(this)), animationTemplate(priv)
{
delayedStopTimer->setInterval(DELAY_STOP_TIMER_INTERVAL);
delayedStopTimer->setSingleShot(true);
@@ -120,11 +121,11 @@ void QSmoothedAnimation::prepareForRestart()
initialVelocity = trackVelocity;
if (isRunning()) {
//we are joining a new wrapper group while running, our times need to be restarted
- useDelta = true;
+ skipUpdate = true;
init();
lastTime = 0;
} else {
- useDelta = false;
+ skipUpdate = false;
//we'll be started when the group starts, which will force an init()
}
}
@@ -242,12 +243,15 @@ qreal QSmoothedAnimation::easeFollow(qreal time_seconds)
void QSmoothedAnimation::updateCurrentTime(int t)
{
+ if (skipUpdate) {
+ skipUpdate = false;
+ return;
+ }
+
if (!isRunning() && !isPaused()) // This can happen if init() stops the animation in some cases
return;
- qreal time_seconds = useDelta ? qreal(QQmlAnimationTimer::instance()->currentDelta()) / 1000. : qreal(t - lastTime) / 1000.;
- if (useDelta)
- useDelta = false;
+ qreal time_seconds = qreal(t - lastTime) / 1000.;
qreal value = easeFollow(time_seconds);
value *= (invert? -1.0: 1.0);
@@ -403,7 +407,7 @@ QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &a
QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
- QParallelAnimationGroupJob *wrapperGroup = new QParallelAnimationGroupJob();
+ QContinuingAnimationGroupJob *wrapperGroup = new QContinuingAnimationGroupJob();
if (!dataActions.isEmpty()) {
QSet<QAbstractAnimationJob*> anims;
diff --git a/src/quick/util/qquicksmoothedanimation_p_p.h b/src/quick/util/qquicksmoothedanimation_p_p.h
index 4391ea81ac..7835d0328b 100644
--- a/src/quick/util/qquicksmoothedanimation_p_p.h
+++ b/src/quick/util/qquicksmoothedanimation_p_p.h
@@ -58,8 +58,6 @@
#include "qquickanimation_p_p.h"
-#include "private/qparallelanimationgroupjob_p.h"
-
#include <private/qobject_p.h>
#include <QBasicTimer>
@@ -129,7 +127,7 @@ private:
qreal s; // Total s
int lastTime;
- bool useDelta;
+ bool skipUpdate;
bool recalc();
void delayedStop();
diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp
index 36aae36459..f237c09bf9 100644
--- a/src/quick/util/qquickspringanimation.cpp
+++ b/src/quick/util/qquickspringanimation.cpp
@@ -43,7 +43,7 @@
#include "qquickanimation_p_p.h"
#include <private/qqmlproperty_p.h>
-#include "private/qparallelanimationgroupjob_p.h"
+#include "private/qcontinuinganimationgroupjob_p.h"
#include <QtCore/qdebug.h>
@@ -93,7 +93,7 @@ public:
bool useMass : 1;
bool haveModulus : 1;
- bool useDelta : 1;
+ bool skipUpdate : 1;
typedef QHash<QQmlProperty, QSpringAnimation*> ActiveAnimationHash;
void clearTemplate() { animationTemplate = 0; }
@@ -160,7 +160,7 @@ QSpringAnimation::QSpringAnimation(QQuickSpringAnimationPrivate *priv)
, modulus(0.0)
, useMass(false)
, haveModulus(false)
- , useDelta(false)
+ , skipUpdate(false)
, animationTemplate(priv)
{
}
@@ -194,11 +194,10 @@ int QSpringAnimation::duration() const
void QSpringAnimation::restart()
{
if (isRunning() || (stopTime != -1 && (animationTemplate->elapsed.elapsed() - stopTime) < DELAY_STOP_TIMER_INTERVAL)) {
- useDelta = true;
+ skipUpdate = true;
init();
- lastTime = 0;
} else {
- useDelta = false;
+ skipUpdate = false;
//init() will be triggered when group starts
}
}
@@ -211,16 +210,17 @@ void QSpringAnimation::init()
void QSpringAnimation::updateCurrentTime(int time)
{
+ if (skipUpdate) {
+ skipUpdate = false;
+ return;
+ }
+
if (mode == Track) {
stop();
return;
}
- int elapsed = useDelta ? QQmlAnimationTimer::instance()->currentDelta() : time - lastTime;
- if (useDelta) {
- startTime = time - elapsed;
- useDelta = false;
- }
+ int elapsed = time - lastTime;
if (!elapsed)
return;
@@ -534,7 +534,7 @@ QAbstractAnimationJob* QQuickSpringAnimation::transition(QQuickStateActions &act
Q_D(QQuickSpringAnimation);
Q_UNUSED(direction);
- QParallelAnimationGroupJob *wrapperGroup = new QParallelAnimationGroupJob();
+ QContinuingAnimationGroupJob *wrapperGroup = new QContinuingAnimationGroupJob();
QQuickStateActions dataActions = QQuickNumberAnimation::createTransitionActions(actions, modified, defaultTarget);
if (!dataActions.isEmpty()) {
diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h
index c559c8163c..82e456ed65 100644
--- a/src/quick/util/qquickstate_p_p.h
+++ b/src/quick/util/qquickstate_p_p.h
@@ -215,7 +215,7 @@ public:
struct OperationGuard : public QQmlGuard<QQuickStateOperation>
{
- OperationGuard(QObject *obj, QList<OperationGuard> *l) : list(l) {
+ OperationGuard(QObject *obj, QList<OperationGuard> *l) : list(l) {
setObject(static_cast<QQuickStateOperation *>(obj));
}
QList<OperationGuard> *list;
diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp
index d8cf9bd877..94e1f30215 100644
--- a/src/quick/util/qquicktimeline.cpp
+++ b/src/quick/util/qquicktimeline.cpp
@@ -81,7 +81,7 @@ struct QQuickTimeLinePrivate
Execute
};
Op() {}
- Op(Type t, int l, qreal v, qreal v2, int o,
+ Op(Type t, int l, qreal v, qreal v2, int o,
const QQuickTimeLineCallback &ev = QQuickTimeLineCallback(), const QEasingCurve &es = QEasingCurve())
: type(t), length(l), value(v), value2(v2), order(o), event(ev),
easing(es) {}
@@ -89,8 +89,8 @@ struct QQuickTimeLinePrivate
: type(o.type), length(o.length), value(o.value), value2(o.value2),
order(o.order), event(o.event), easing(o.easing) {}
Op &operator=(const Op &o) {
- type = o.type; length = o.length; value = o.value;
- value2 = o.value2; order = o.order; event = o.event;
+ type = o.type; length = o.length; value = o.value;
+ value2 = o.value2; order = o.order; event = o.event;
easing = o.easing;
return *this;
}
@@ -396,6 +396,7 @@ int QQuickTimeLine::accel(QQuickTimeLineValue &timeLineValue, qreal velocity, qr
acceleration = acceleration * -1.0f;
int time = static_cast<int>(-1000 * velocity / acceleration);
+ if (time <= 0) return -1;
QQuickTimeLinePrivate::Op op(QQuickTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
d->add(timeLineValue, op);
@@ -428,6 +429,7 @@ int QQuickTimeLine::accel(QQuickTimeLineValue &timeLineValue, qreal velocity, qr
acceleration = acceleration * -1.0f;
int time = static_cast<int>(-1000 * velocity / acceleration);
+ if (time <= 0) return -1;
QQuickTimeLinePrivate::Op op(QQuickTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
d->add(timeLineValue, op);
@@ -450,6 +452,7 @@ int QQuickTimeLine::accelDistance(QQuickTimeLineValue &timeLineValue, qreal velo
Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
+ if (time <= 0) return -1;
QQuickTimeLinePrivate::Op op(QQuickTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
d->add(timeLineValue, op);
@@ -604,8 +607,8 @@ void QQuickTimeLine::sync(QQuickTimeLineValue &timeLineValue)
d->syncPoint = d->length;
}*/
-/*!
- \internal
+/*!
+ \internal
Temporary hack.
*/
@@ -614,9 +617,9 @@ void QQuickTimeLine::setSyncPoint(int sp)
d->syncPoint = sp;
}
-/*!
- \internal
-
+/*!
+ \internal
+
Temporary hack.
*/
int QQuickTimeLine::syncPoint() const
@@ -739,7 +742,7 @@ int QQuickTimeLinePrivate::advance(int t)
TimeLine &tl = *iter;
Op &op = tl.ops.first();
int length = op.length - tl.consumedOpLength;
-
+
if (length < advanceTime) {
advanceTime = length;
if (advanceTime == 0)
@@ -748,7 +751,7 @@ int QQuickTimeLinePrivate::advance(int t)
}
t -= advanceTime;
- // Process until then. A zero length advance time will only process
+ // Process until then. A zero length advance time will only process
// sets.
QList<QPair<int, Update> > updates;
@@ -762,8 +765,8 @@ int QQuickTimeLinePrivate::advance(int t)
if (advanceTime == 0 && op.length != 0)
continue;
- if (tl.consumedOpLength == 0 &&
- op.type != Op::Pause &&
+ if (tl.consumedOpLength == 0 &&
+ op.type != Op::Pause &&
op.type != Op::Execute)
tl.base = v->value();
diff --git a/src/quick/util/qquicktransitionmanager.cpp b/src/quick/util/qquicktransitionmanager.cpp
index 769dadc4fc..2821d7628c 100644
--- a/src/quick/util/qquicktransitionmanager.cpp
+++ b/src/quick/util/qquicktransitionmanager.cpp
@@ -89,7 +89,7 @@ bool QQuickTransitionManager::isRunning() const
return d->transitionInstance && d->transitionInstance->isRunning();
}
-void QQuickTransitionManager::complete()
+void QQuickTransitionManager::complete()
{
d->applyBindings();
@@ -100,7 +100,7 @@ void QQuickTransitionManager::complete()
d->completeList.clear();
- if (d->state)
+ if (d->state)
static_cast<QQuickStatePrivate*>(QObjectPrivate::get(d->state))->complete();
finished();
@@ -228,8 +228,8 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
} else {
if (touched.contains(action.property)) {
- if (action.toValue != action.fromValue)
- d->completeList <<
+ if (action.toValue != action.fromValue)
+ d->completeList <<
QQuickSimpleAction(action, QQuickSimpleAction::EndState);
applyList.removeAt(ii);
@@ -242,7 +242,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
// Any actions remaining have not been handled by the transition and should
// be applied immediately. We skip applying bindings, as they are all
- // applied at the end in applyBindings() to avoid any nastiness mid
+ // applied at the end in applyBindings() to avoid any nastiness mid
// transition
foreach(const QQuickStateAction &action, applyList) {
if (action.event && !action.event->changesBindings()) {
@@ -261,7 +261,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
qWarning() << " No transition for event:" << action.event->type();
else
qWarning() << " No transition for:" << action.property.object()
- << action.property.name() << "From:" << action.fromValue
+ << action.property.name() << "From:" << action.fromValue
<< "To:" << action.toValue;
}
}
diff --git a/src/quick/util/qquicktransitionmanager_p_p.h b/src/quick/util/qquicktransitionmanager_p_p.h
index 6211b5488c..bf203feaf4 100644
--- a/src/quick/util/qquicktransitionmanager_p_p.h
+++ b/src/quick/util/qquicktransitionmanager_p_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
class QQuickStatePrivate;
class QQuickTransitionManagerPrivate;
-class Q_AUTOTEST_EXPORT QQuickTransitionManager
+class Q_AUTOTEST_EXPORT QQuickTransitionManager
{
public:
QQuickTransitionManager();
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index fae1103d47..ce409bd10d 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -25,7 +25,8 @@ SOURCES += \
$$PWD/qquickglobal.cpp \
$$PWD/qquickanimator.cpp \
$$PWD/qquickanimatorjob.cpp \
- $$PWD/qquickanimatorcontroller.cpp
+ $$PWD/qquickanimatorcontroller.cpp \
+ $$PWD/qquickprofiler.cpp
HEADERS += \
$$PWD/qquickapplication_p.h\
@@ -58,4 +59,5 @@ HEADERS += \
$$PWD/qquickanimator_p.h \
$$PWD/qquickanimator_p_p.h \
$$PWD/qquickanimatorjob_p.h \
- $$PWD/qquickanimatorcontroller_p.h
+ $$PWD/qquickanimatorcontroller_p.h \
+ $$PWD/qquickprofiler_p.h
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
new file mode 100644
index 0000000000..7458d2de01
--- /dev/null
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -0,0 +1,846 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwidget.h"
+#include "qquickwidget_p.h"
+
+#include "private/qquickwindow_p.h"
+#include "private/qquickitem_p.h"
+#include "private/qquickitemchangelistener_p.h"
+#include "private/qquickrendercontrol_p.h"
+
+#include <private/qquickprofiler_p.h>
+#include <private/qqmlinspectorservice_p.h>
+#include <private/qqmlmemoryprofiler_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <private/qqmlengine_p.h>
+#include <QtCore/qbasictimer.h>
+
+QT_BEGIN_NAMESPACE
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+void QQuickWidgetPrivate::init(QQmlEngine* e)
+{
+ Q_Q(QQuickWidget);
+
+ setRenderToTexture();
+ engine = e;
+
+ if (engine.isNull())
+ engine = new QQmlEngine(q);
+
+ if (!engine.data()->incubationController())
+ engine.data()->setIncubationController(offscreenWindow->incubationController());
+
+ if (QQmlDebugService::isDebuggingEnabled())
+ QQmlInspectorService::instance()->addView(q);
+
+ QWidget::connect(offscreenWindow, SIGNAL(sceneGraphInitialized()), q, SLOT(createFramebufferObject()));
+ QWidget::connect(offscreenWindow, SIGNAL(sceneGraphInvalidated()), q, SLOT(destroyFramebufferObject()));
+ QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate()));
+ QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
+}
+
+QQuickWidgetPrivate::QQuickWidgetPrivate()
+ : root(0)
+ , component(0)
+ , fbo(0)
+ , context(0)
+ , resizeMode(QQuickWidget::SizeViewToRootObject)
+ , initialSize(0,0)
+ , updateTimer(0)
+ , eventPending(false)
+ , updatePending(false)
+{
+ renderControl = new QQuickRenderControl;
+ offscreenWindow = new QQuickWindow(renderControl);
+ offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
+ // Do not call create() on offscreenWindow.
+}
+
+QQuickWidgetPrivate::~QQuickWidgetPrivate()
+{
+ if (QQmlDebugService::isDebuggingEnabled())
+ QQmlInspectorService::instance()->removeView(q_func());
+ delete offscreenWindow;
+ delete renderControl;
+ delete fbo;
+}
+
+void QQuickWidgetPrivate::execute()
+{
+ Q_Q(QQuickWidget);
+ if (!engine) {
+ qWarning() << "QQuickWidget: invalid qml engine.";
+ return;
+ }
+
+ if (root) {
+ delete root;
+ root = 0;
+ }
+ if (component) {
+ delete component;
+ component = 0;
+ }
+ if (!source.isEmpty()) {
+ QML_MEMORY_SCOPE_URL(engine.data()->baseUrl().resolved(source));
+ component = new QQmlComponent(engine.data(), source, q);
+ if (!component->isLoading()) {
+ q->continueExecute();
+ } else {
+ QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
+ q, SLOT(continueExecute()));
+ }
+ }
+}
+
+void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QQuickWidget);
+ if (resizeItem == root && resizeMode == QQuickWidget::SizeViewToRootObject) {
+ // wait for both width and height to be changed
+ resizetimer.start(0,q);
+ }
+ QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
+}
+
+void QQuickWidgetPrivate::renderSceneGraph()
+{
+ Q_Q(QQuickWidget);
+ updatePending = false;
+
+ QOpenGLContext *context = offscreenWindow->openglContext();
+ if (!context) {
+ qWarning("QQuickWidget: render scenegraph with no context");
+ return;
+ }
+
+ Q_ASSERT(q->window()->windowHandle()->handle());
+ context->makeCurrent(q->window()->windowHandle());
+ renderControl->polishItems();
+ renderControl->sync();
+ renderControl->render();
+ glFlush();
+ context->doneCurrent();
+ q->update();
+}
+
+/*!
+ \class QQuickWidget
+ \since 5.3
+ \brief The QQuickWidget class provides a widget for displaying a Qt Quick user interface.
+
+ \inmodule QtQuick
+
+ This is a convenience wrapper for QQuickWindow which will automatically load and display a QML
+ scene when given the URL of the main source file. Alternatively, you can instantiate your own
+ objects using QQmlComponent and place them in a manually setup QQuickWidget.
+
+ Typical usage:
+
+ \code
+ QQuickWidget *view = new QQuickWidget;
+ view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
+ view->show();
+ \endcode
+
+ To receive errors related to loading and executing QML with QQuickWidget,
+ you can connect to the statusChanged() signal and monitor for QQuickWidget::Error.
+ The errors are available via QQuickWidget::errors().
+
+ QQuickWidget also manages sizing of the view and root object. By default, the \l resizeMode
+ is SizeViewToRootObject, which will load the component and resize it to the
+ size of the view. Alternatively the resizeMode may be set to SizeRootObjectToView which
+ will resize the view to the size of the root object.
+
+ \note QQuickWidget is an alternative to using QQuickView and QWidget::createWindowContainer().
+ The restrictions on stacking order do not apply, making QQuickWidget the more flexible
+ alternative behaving more like an ordinary widget. This comes at the expense of
+ performance. Unlike QQuickWindow and QQuickView, QQuickWidget involves rendering into OpenGL
+ framebuffer objects. This will naturally carry a minor performance hit.
+
+ \note Using QQuickWidget disables the threaded render loop on all platforms. This means that
+ some of the benefits of threaded rendering, for example Animator classes and vsync driven
+ animations, will not be available.
+
+ \sa {qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++ Types to QML}
+*/
+
+
+/*! \fn void QQuickWidget::statusChanged(QQuickWidget::Status status)
+ This signal is emitted when the component's current \a status changes.
+*/
+
+/*!
+ Constructs a QQuickWidget with the given \a parent.
+ The default value of \a parent is 0.
+
+*/
+QQuickWidget::QQuickWidget(QWidget *parent)
+: QWidget(*(new QQuickWidgetPrivate), parent, 0)
+{
+ setMouseTracking(true);
+ d_func()->init();
+}
+
+/*!
+ Constructs a QQuickWidget with the given QML \a source and \a parent.
+ The default value of \a parent is 0.
+
+*/
+QQuickWidget::QQuickWidget(const QUrl &source, QWidget *parent)
+: QWidget(*(new QQuickWidgetPrivate), parent, 0)
+{
+ setMouseTracking(true);
+ d_func()->init();
+ setSource(source);
+}
+
+/*!
+ Constructs a QQuickWidget with the given QML \a engine and \a parent.
+
+ Note: In this case, the QQuickWidget does not own the given \a engine object;
+ it is the caller's responsibility to destroy the engine. If the \a engine is deleted
+ before the view, status() will return QQuickWidget::Error.
+
+ \sa Status, status(), errors()
+*/
+QQuickWidget::QQuickWidget(QQmlEngine* engine, QWidget *parent)
+ : QWidget(*(new QQuickWidgetPrivate), parent, 0)
+{
+ setMouseTracking(true);
+ Q_ASSERT(engine);
+ d_func()->init(engine);
+}
+
+/*!
+ Destroys the QQuickWidget.
+*/
+QQuickWidget::~QQuickWidget()
+{
+ // Ensure that the component is destroyed before the engine; the engine may
+ // be a child of the QQuickWidgetPrivate, and will be destroyed by its dtor
+ Q_D(QQuickWidget);
+ delete d->root;
+ d->root = 0;
+}
+
+/*!
+ \property QQuickWidget::source
+ \brief The URL of the source of the QML component.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+ Note that setting a source URL will result in the QML component being
+ instantiated, even if the URL is unchanged from the current value.
+*/
+
+/*!
+ Sets the source to the \a url, loads the QML component and instantiates it.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+ Calling this method multiple times with the same url will result
+ in the QML component being reinstantiated.
+ */
+void QQuickWidget::setSource(const QUrl& url)
+{
+ Q_D(QQuickWidget);
+ d->source = url;
+ d->execute();
+}
+
+/*!
+ \internal
+
+ Set the source \a url, \a component and content \a item (root of the QML object hierarchy) directly.
+ */
+void QQuickWidget::setContent(const QUrl& url, QQmlComponent *component, QObject* item)
+{
+ Q_D(QQuickWidget);
+ d->source = url;
+ d->component = component;
+
+ if (d->component && d->component->isError()) {
+ QList<QQmlError> errorList = d->component->errors();
+ foreach (const QQmlError &error, errorList) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ d->setRootObject(item);
+ emit statusChanged(status());
+}
+
+/*!
+ Returns the source URL, if set.
+
+ \sa setSource()
+ */
+QUrl QQuickWidget::source() const
+{
+ Q_D(const QQuickWidget);
+ return d->source;
+}
+
+/*!
+ Returns a pointer to the QQmlEngine used for instantiating
+ QML Components.
+ */
+QQmlEngine* QQuickWidget::engine() const
+{
+ Q_D(const QQuickWidget);
+ return d->engine ? const_cast<QQmlEngine *>(d->engine.data()) : 0;
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QQmlContext. QQmlContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QQmlEngine.
+ */
+QQmlContext* QQuickWidget::rootContext() const
+{
+ Q_D(const QQuickWidget);
+ return d->engine ? d->engine.data()->rootContext() : 0;
+}
+
+/*!
+ \enum QQuickWidget::Status
+ Specifies the loading status of the QQuickWidget.
+
+ \value Null This QQuickWidget has no source set.
+ \value Ready This QQuickWidget has loaded and created the QML component.
+ \value Loading This QQuickWidget is loading network data.
+ \value Error One or more errors has occurred. Call errors() to retrieve a list
+ of errors.
+*/
+
+/*! \enum QQuickWidget::ResizeMode
+
+ This enum specifies how to resize the view.
+
+ \value SizeViewToRootObject The view resizes with the root item in the QML.
+ \value SizeRootObjectToView The view will automatically resize the root item to the size of the view.
+*/
+
+/*!
+ \property QQuickWidget::status
+ The component's current \l{QQuickWidget::Status} {status}.
+*/
+
+QQuickWidget::Status QQuickWidget::status() const
+{
+ Q_D(const QQuickWidget);
+ if (!d->engine)
+ return QQuickWidget::Error;
+
+ if (!d->component)
+ return QQuickWidget::Null;
+
+ return QQuickWidget::Status(d->component->status());
+}
+
+/*!
+ Return the list of errors that occurred during the last compile or create
+ operation. When the status is not Error, an empty list is returned.
+*/
+QList<QQmlError> QQuickWidget::errors() const
+{
+ Q_D(const QQuickWidget);
+ QList<QQmlError> errs;
+
+ if (d->component)
+ errs = d->component->errors();
+
+ if (!d->engine) {
+ QQmlError error;
+ error.setDescription(QLatin1String("QQuickWidget: invalid qml engine."));
+ errs << error;
+ }
+
+ return errs;
+}
+
+/*!
+ \property QQuickWidget::resizeMode
+ \brief whether the view should resize the window contents
+
+ If this property is set to SizeViewToRootObject (the default), the view
+ resizes to the size of the root item in the QML.
+
+ If this property is set to SizeRootObjectToView, the view will
+ automatically resize the root item to the size of the view.
+
+ Regardless of this property, the sizeHint of the view
+ is the initial size of the root item. Note though that
+ since QML may load dynamically, that size may change.
+
+ \sa initialSize()
+*/
+
+void QQuickWidget::setResizeMode(ResizeMode mode)
+{
+ Q_D(QQuickWidget);
+ if (d->resizeMode == mode)
+ return;
+
+ if (d->root) {
+ if (d->resizeMode == SizeViewToRootObject) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(d->root);
+ p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ }
+ }
+
+ d->resizeMode = mode;
+ if (d->root) {
+ d->initResize();
+ }
+}
+
+void QQuickWidgetPrivate::initResize()
+{
+ if (root) {
+ if (resizeMode == QQuickWidget::SizeViewToRootObject) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(root);
+ p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+ }
+ updateSize();
+}
+
+void QQuickWidgetPrivate::updateSize()
+{
+ Q_Q(QQuickWidget);
+ if (!root)
+ return;
+
+ if (resizeMode == QQuickWidget::SizeViewToRootObject) {
+ QSize newSize = QSize(root->width(), root->height());
+ if (newSize.isValid() && newSize != q->size()) {
+ q->resize(newSize);
+ }
+ } else if (resizeMode == QQuickWidget::SizeRootObjectToView) {
+ if (!qFuzzyCompare(q->width(), root->width()))
+ root->setWidth(q->width());
+ if (!qFuzzyCompare(q->height(), root->height()))
+ root->setHeight(q->height());
+ }
+}
+
+QSize QQuickWidgetPrivate::rootObjectSize() const
+{
+ QSize rootObjectSize(0,0);
+ int widthCandidate = -1;
+ int heightCandidate = -1;
+ if (root) {
+ widthCandidate = root->width();
+ heightCandidate = root->height();
+ }
+ if (widthCandidate > 0) {
+ rootObjectSize.setWidth(widthCandidate);
+ }
+ if (heightCandidate > 0) {
+ rootObjectSize.setHeight(heightCandidate);
+ }
+ return rootObjectSize;
+}
+
+void QQuickWidgetPrivate::createContext()
+{
+ Q_Q(QQuickWidget);
+ if (context)
+ return;
+
+ context = new QOpenGLContext;
+
+ QSurfaceFormat format = q->window()->windowHandle()->requestedFormat();
+ QSGRenderContext *renderContext = QQuickWindowPrivate::get(offscreenWindow)->context;
+ // Depth, stencil, etc. must be set like a QQuickWindow would do.
+ QSurfaceFormat sgFormat = renderContext->sceneGraphContext()->defaultSurfaceFormat();
+ format.setDepthBufferSize(qMax(format.depthBufferSize(), sgFormat.depthBufferSize()));
+ format.setStencilBufferSize(qMax(format.stencilBufferSize(), sgFormat.stencilBufferSize()));
+ format.setAlphaBufferSize(qMax(format.alphaBufferSize(), sgFormat.alphaBufferSize()));
+ format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ context->setFormat(format);
+
+ if (QSGContext::sharedOpenGLContext())
+ context->setShareContext(QSGContext::sharedOpenGLContext()); // ??? is this correct
+ if (!context->create()) {
+ qWarning("QQuickWidget: failed to create OpenGL context");
+ delete context;
+ context = 0;
+ }
+
+ Q_ASSERT(q->window()->windowHandle()->handle());
+ if (context->makeCurrent(q->window()->windowHandle()))
+ renderControl->initialize(context);
+ else
+ qWarning("QQuickWidget: failed to make window surface current");
+}
+
+void QQuickWidget::createFramebufferObject()
+{
+ Q_D(QQuickWidget);
+
+ if (d->fbo)
+ delete d->fbo;
+ QOpenGLContext *context = d->offscreenWindow->openglContext();
+
+ if (!context) {
+ qWarning("QQuickWidget: Attempted to create FBO with no context");
+ return;
+ }
+
+ if (context->shareContext() != QWidgetPrivate::get(window())->shareContext()) {
+ context->setShareContext(QWidgetPrivate::get(window())->shareContext());
+ context->create();
+ }
+
+ Q_ASSERT(window()->windowHandle()->handle());
+ context->makeCurrent(window()->windowHandle());
+ d->fbo = new QOpenGLFramebufferObject(size());
+ d->fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ d->offscreenWindow->setRenderTarget(d->fbo);
+
+ // Sanity check: The window must not have an underlying platform window.
+ // Having one would mean create() was called and platforms that only support
+ // a single native window were in trouble.
+ Q_ASSERT(!d->offscreenWindow->handle());
+}
+
+void QQuickWidget::destroyFramebufferObject()
+{
+ Q_D(QQuickWidget);
+ if (d->fbo)
+ delete d->fbo;
+ d->fbo = 0;
+}
+
+QQuickWidget::ResizeMode QQuickWidget::resizeMode() const
+{
+ Q_D(const QQuickWidget);
+ return d->resizeMode;
+}
+
+/*!
+ \internal
+ */
+void QQuickWidget::continueExecute()
+{
+ Q_D(QQuickWidget);
+ disconnect(d->component, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(continueExecute()));
+
+ if (d->component->isError()) {
+ QList<QQmlError> errorList = d->component->errors();
+ foreach (const QQmlError &error, errorList) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if (d->component->isError()) {
+ QList<QQmlError> errorList = d->component->errors();
+ foreach (const QQmlError &error, errorList) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ d->setRootObject(obj);
+ emit statusChanged(status());
+}
+
+
+/*!
+ \internal
+*/
+void QQuickWidgetPrivate::setRootObject(QObject *obj)
+{
+ Q_Q(QQuickWidget);
+ if (root == obj)
+ return;
+ if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
+ root = sgItem;
+ sgItem->setParentItem(offscreenWindow->contentItem());
+ } else {
+ qWarning() << "QQuickWidget only supports loading of root objects that derive from QQuickItem." << endl
+ << endl
+ << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
+ << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
+ << endl
+ << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
+ << "QDeclarativeView class in the Qt Quick 1 module." << endl;
+ delete obj;
+ root = 0;
+ }
+ if (root) {
+ initialSize = rootObjectSize();
+ if ((resizeMode == QQuickWidget::SizeViewToRootObject || q->width() <= 1 || q->height() <= 1) &&
+ initialSize != q->size()) {
+ q->resize(initialSize);
+ }
+ initResize();
+ }
+}
+
+GLuint QQuickWidgetPrivate::textureId() const
+{
+ return fbo ? fbo->texture() : 0;
+}
+
+/*!
+ \internal
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QQuickWidget::timerEvent(QTimerEvent* e)
+{
+ Q_D(QQuickWidget);
+ if (!e || e->timerId() == d->resizetimer.timerId()) {
+ d->updateSize();
+ d->resizetimer.stop();
+ }
+}
+
+/*!
+ \internal
+ Preferred size follows the root object geometry.
+*/
+QSize QQuickWidget::sizeHint() const
+{
+ Q_D(const QQuickWidget);
+ QSize rootObjectSize = d->rootObjectSize();
+ if (rootObjectSize.isEmpty()) {
+ return size();
+ } else {
+ return rootObjectSize;
+ }
+}
+
+/*!
+ Returns the initial size of the root object.
+
+ If \l resizeMode is QQuickItem::SizeRootObjectToView the root object will be
+ resized to the size of the view. initialSize contains the size of the
+ root object before it was resized.
+*/
+QSize QQuickWidget::initialSize() const
+{
+ Q_D(const QQuickWidget);
+ return d->initialSize;
+}
+
+/*!
+ Returns the view's root \l {QQuickItem} {item}.
+ */
+QQuickItem *QQuickWidget::rootObject() const
+{
+ Q_D(const QQuickWidget);
+ return d->root;
+}
+
+/*!
+ \internal
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QQuickWidget::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QQuickWidget);
+ if (d->resizeMode == SizeRootObjectToView)
+ d->updateSize();
+
+ d->createContext();
+ createFramebufferObject();
+ d->offscreenWindow->resizeEvent(e);
+ d->offscreenWindow->setGeometry(0, 0, e->size().width(), e->size().height());
+
+ QOpenGLContext *context = d->offscreenWindow->openglContext();
+ if (!context) {
+ qWarning("QQuickWidget::resizeEvent() no OpenGL context");
+ return;
+ }
+
+ Q_ASSERT(window()->windowHandle()->handle());
+ context->makeCurrent(window()->windowHandle());
+ d->renderControl->render();
+ glFlush();
+ context->doneCurrent();
+}
+
+/*! \reimp */
+void QQuickWidget::keyPressEvent(QKeyEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+
+ d->offscreenWindow->keyPressEvent(e);
+}
+
+/*! \reimp */
+void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+
+ d->offscreenWindow->keyReleaseEvent(e);
+}
+
+/*! \reimp */
+void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ // Use the constructor taking localPos and screenPos. That puts localPos into the
+ // event's localPos and windowPos, and screenPos into the event's screenPos. This way
+ // the windowPos in e is ignored and is replaced by localPos. This is necessary
+ // because QQuickWindow thinks of itself as a top-level window always.
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ d->offscreenWindow->mouseMoveEvent(&mappedEvent);
+}
+
+void QQuickWidget::showEvent(QShowEvent *e)
+{
+ Q_D(QQuickWidget);
+ QQuickWindowPrivate::get(d->offscreenWindow)->forceRendering = true;
+ d->offscreenWindow->showEvent(e);
+}
+
+void QQuickWidget::hideEvent(QHideEvent *e)
+{
+ Q_D(QQuickWidget);
+ QQuickWindowPrivate::get(d->offscreenWindow)->forceRendering = false;
+ d->offscreenWindow->hideEvent(e);
+}
+
+/*! \reimp */
+void QQuickWidget::mousePressEvent(QMouseEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ d->offscreenWindow->mousePressEvent(&mappedEvent);
+}
+
+/*! \reimp */
+void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ d->offscreenWindow->mouseReleaseEvent(&mappedEvent);
+}
+
+#ifndef QT_NO_WHEELEVENT
+/*! \reimp */
+void QQuickWidget::wheelEvent(QWheelEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ // Wheel events only have local and global positions, no need to map.
+ d->offscreenWindow->wheelEvent(e);
+}
+#endif
+
+/*! \reimp */
+bool QQuickWidget::event(QEvent *e)
+{
+ Q_D(QQuickWidget);
+
+ switch (e->type()) {
+ case QEvent::Timer:
+ d->eventPending = false;
+ killTimer(d->updateTimer);
+ d->updateTimer = 0;
+ if (d->updatePending)
+ d->renderSceneGraph();
+ return true;
+
+ case QEvent::TouchBegin:
+ case QEvent::TouchEnd:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchCancel:
+ // Touch events only have local and global positions, no need to map.
+ return d->offscreenWindow->event(e);
+
+ default:
+ break;
+ }
+
+ return QWidget::event(e);
+}
+
+
+// TODO: try to separate the two cases of
+// 1. render() unconditionally without sync
+// 2. sync() and then render if necessary
+void QQuickWidget::triggerUpdate()
+{
+ Q_D(QQuickWidget);
+ d->updatePending = true;
+ if (!d->eventPending) {
+ const int exhaustDelay = 5;
+ d->updateTimer = startTimer(exhaustDelay, Qt::PreciseTimer);
+ d->eventPending = true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h
new file mode 100644
index 0000000000..92b060647f
--- /dev/null
+++ b/src/quickwidgets/qquickwidget.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWIDGET_H
+#define QQUICKWIDGET_H
+
+#include <QtWidgets/qwidget.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtCore/qurl.h>
+#include <QtQml/qqmldebug.h>
+#include <QtQuickWidgets/qtquickwidgetsglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngine;
+class QQmlContext;
+class QQmlError;
+class QQuickItem;
+class QQmlComponent;
+
+class QQuickWidgetPrivate;
+class Q_QUICKWIDGETS_EXPORT QQuickWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
+ Q_ENUMS(ResizeMode Status)
+public:
+ explicit QQuickWidget(QWidget *parent = 0);
+ QQuickWidget(QQmlEngine* engine, QWidget *parent);
+ QQuickWidget(const QUrl &source, QWidget *parent = 0);
+ virtual ~QQuickWidget();
+
+ QUrl source() const;
+
+ QQmlEngine* engine() const;
+ QQmlContext* rootContext() const;
+
+ QQuickItem *rootObject() const;
+
+ enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ ResizeMode resizeMode() const;
+ void setResizeMode(ResizeMode);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ QList<QQmlError> errors() const;
+
+ QSize sizeHint() const;
+ QSize initialSize() const;
+
+public Q_SLOTS:
+ void setSource(const QUrl&);
+ void setContent(const QUrl& url, QQmlComponent *component, QObject *item);
+
+Q_SIGNALS:
+ void statusChanged(QQuickWidget::Status);
+
+private Q_SLOTS:
+ void continueExecute();
+ void createFramebufferObject();
+ void destroyFramebufferObject();
+ void triggerUpdate();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void timerEvent(QTimerEvent*);
+
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+
+ virtual void showEvent(QShowEvent *);
+ virtual void hideEvent(QHideEvent *);
+
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelEvent(QWheelEvent *);
+#endif
+
+ bool event(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QQuickWidget)
+ Q_DECLARE_PRIVATE(QQuickWidget)
+};
+
+QT_END_NAMESPACE
+
+#endif // QQuickWidget_H
diff --git a/src/imports/dialogs-private/qquickwritingsystemlistmodel_p.h b/src/quickwidgets/qquickwidget_p.h
index 31058bbf78..01f7c3ac91 100644
--- a/src/imports/dialogs-private/qquickwritingsystemlistmodel_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,62 +39,79 @@
**
****************************************************************************/
-#ifndef QQUICKWRITINGSYSTEMLISTMODEL_P_H
-#define QQUICKWRITINGSYSTEMLISTMODEL_P_H
+#ifndef QQUICKWIDGET_P_H
+#define QQUICKWIDGET_P_H
-#include <QtCore/qstringlist.h>
-#include <QtCore/qabstractitemmodel.h>
-#include <QtQml/qqmlparserstatus.h>
-#include <private/qv8engine_p.h>
+#include "qquickwidget.h"
+#include <private/qwidget_p.h>
-QT_BEGIN_NAMESPACE
+#include <QtCore/qurl.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/QWeakPointer>
-class QModelIndex;
+#include <QtQml/qqmlengine.h>
-class QQuickWritingSystemListModelPrivate;
+#include "private/qquickitemchangelistener_p.h"
-class QQuickWritingSystemListModel : public QAbstractListModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
- Q_PROPERTY(QStringList writingSystems READ writingSystems NOTIFY writingSystemsChanged)
+QT_BEGIN_NAMESPACE
- Q_PROPERTY(int count READ count NOTIFY rowCountChanged)
+class QQmlContext;
+class QQmlError;
+class QQuickItem;
+class QQmlComponent;
+class QQuickRenderControl;
+class QOpenGLContext;
+class QQuickWidgetPrivate
+ : public QWidgetPrivate,
+ public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickWidget)
public:
- QQuickWritingSystemListModel(QObject *parent = 0);
- ~QQuickWritingSystemListModel();
+ static QQuickWidgetPrivate* get(QQuickWidget *view) { return view->d_func(); }
+ static const QQuickWidgetPrivate* get(const QQuickWidget *view) { return view->d_func(); }
+
+ QQuickWidgetPrivate();
+ ~QQuickWidgetPrivate();
- enum Roles {
- WritingSystemNameRole = Qt::UserRole + 1,
- WritingSystemSampleRole = Qt::UserRole + 2
- };
+ void execute();
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void initResize();
+ void updateSize();
+ void updateFrambufferObjectSize();
+ void setRootObject(QObject *);
+ void renderSceneGraph();
+ void createContext();
- virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
- virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
- virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- virtual QHash<int, QByteArray> roleNames() const;
+ GLuint textureId() const;
- int count() const { return rowCount(QModelIndex()); }
+ void init(QQmlEngine* e = 0);
- QStringList writingSystems() const;
+ QSize rootObjectSize() const;
- Q_INVOKABLE QQmlV4Handle get(int index) const;
+ QPointer<QQuickItem> root;
- virtual void classBegin();
- virtual void componentComplete();
+ QUrl source;
-Q_SIGNALS:
- void writingSystemsChanged();
- void rowCountChanged() const;
+ QPointer<QQmlEngine> engine;
+ QQmlComponent *component;
+ QBasicTimer resizetimer;
+ QQuickWindow *offscreenWindow;
+ QQuickRenderControl *renderControl;
+ QOpenGLFramebufferObject *fbo;
+ QOpenGLContext *context;
-private:
- Q_DISABLE_COPY(QQuickWritingSystemListModel)
- Q_DECLARE_PRIVATE(QQuickWritingSystemListModel)
- QScopedPointer<QQuickWritingSystemListModelPrivate> d_ptr;
+ QQuickWidget::ResizeMode resizeMode;
+ QSize initialSize;
+ QElapsedTimer frameTimer;
+ int updateTimer;
+ bool eventPending;
+ bool updatePending;
};
QT_END_NAMESPACE
-#endif // QQUICKWRITINGSYSTEMLISTMODEL_P_H
+#endif // QQuickWidget_P_H
diff --git a/src/qml/qml/v8/qv8profiler_p.h b/src/quickwidgets/qtquickwidgetsglobal.h
index 39a87f2156..2524150ed1 100644
--- a/src/qml/qml/v8/qv8profiler_p.h
+++ b/src/quickwidgets/qtquickwidgetsglobal.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,4 +39,23 @@
**
****************************************************************************/
-//#include <private/v8-profiler.h>
+#ifndef QTQUICKWIDGETSGLOBAL_H
+#define QTQUICKWIDGETSGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_STATIC
+# if defined(QT_BUILD_QUICKWIDGETS_LIB)
+# define Q_QUICKWIDGETS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QUICKWIDGETS_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define Q_QUICKWIDGETS_EXPORT
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QTQUICKWIDGETSGLOBAL_H
diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro
new file mode 100644
index 0000000000..ab388ff9d3
--- /dev/null
+++ b/src/quickwidgets/quickwidgets.pro
@@ -0,0 +1,19 @@
+TARGET = QtQuickWidgets
+
+QT = core-private gui-private qml-private quick-private widgets-private
+
+DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
+
+
+load(qt_module)
+
+HEADERS += \
+ qquickwidget.h \
+ qquickwidget_p.h \
+ qtquickwidgetsglobal.h
+
+SOURCES += \
+ qquickwidget.cpp
+
+
+
diff --git a/src/src.pro b/src/src.pro
index fb61d49ed9..0cffc9abc0 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -15,4 +15,6 @@ SUBDIRS += \
imports \
qmldevtools
+qtHaveModule(widgets):SUBDIRS += quickwidgets
+
qmldevtools.CONFIG = host_build
diff --git a/sync.profile b/sync.profile
index 7c905801a1..4f4e767129 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,6 +1,7 @@
%modules = ( # path to module name map
"QtQml" => "$basedir/src/qml",
"QtQuick" => "$basedir/src/quick",
+ "QtQuickWidgets" => "$basedir/src/quickwidgets",
"QtQuickParticles" => "$basedir/src/particles",
"QtQuickTest" => "$basedir/src/qmltest",
"QtQmlDevTools" => "$basedir/src/qmldevtools",
diff --git a/tests/auto/particles/qquickgroupgoal/data/basic.qml b/tests/auto/particles/qquickgroupgoal/data/basic.qml
index 8e25a4dc3f..8e3833916f 100644
--- a/tests/auto/particles/qquickgroupgoal/data/basic.qml
+++ b/tests/auto/particles/qquickgroupgoal/data/basic.qml
@@ -61,7 +61,7 @@ Rectangle {
goalState: ""
jump: true
}
-
+
Emitter {
//0,0 position
group: "notdefault"
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
index 149f034903..45960c9e97 100644
--- a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
@@ -868,6 +868,9 @@ void tst_QParallelAnimationGroupJob::addAndRemoveDuration()
void tst_QParallelAnimationGroupJob::pauseResume()
{
+#ifdef Q_CC_MINGW
+ QSKIP("QTBUG-36290 - MinGW Animation tests are flaky.");
+#endif
QParallelAnimationGroupJob group;
TestAnimation *anim = new TestAnimation(250); // 0, duration = 250;
group.appendAnimation(anim);
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro
index 98e41411ee..4c4342a6a5 100644
--- a/tests/auto/qml/debugger/debugger.pro
+++ b/tests/auto/qml/debugger/debugger.pro
@@ -6,11 +6,12 @@ PUBLICTESTS += \
qqmlinspector \
qqmlprofilerservice \
qpacketprotocol \
-# qv8profilerservice \
+# qv4profilerservice \
# qdebugmessageservice \
qqmlenginedebuginspectorintegrationtest \
qqmlinspector \
- qqmlprofilerservice
+ qqmlprofilerservice \
+ qqmlenginecontrol
PRIVATETESTS += \
qqmldebugclient \
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index 7fd1f47838..26919af1b6 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -82,10 +82,10 @@ void tst_QPacketProtocol::init()
m_server = new QTcpServer(this);
m_serverConn = 0;
QVERIFY(m_server->listen(QHostAddress("127.0.0.1")));
-
+
m_client = new QTcpSocket(this);
m_client->connectToHost(m_server->serverAddress(), m_server->serverPort());
-
+
QVERIFY(m_client->waitForConnected());
QVERIFY(m_server->waitForNewConnection(10000));
m_serverConn = m_server->nextPendingConnection();
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index bca40e9acd..4a8025c254 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -124,7 +124,7 @@ void tst_QQmlDebugClient::state()
QTRY_COMPARE(client.state(), QQmlDebugClient::Unavailable);
// duplicate plugin name
- QTest::ignoreMessage(QtWarningMsg, "QQmlDebugClient: Conflicting plugin name \"tst_QQmlDebugClient::state()\" ");
+ QTest::ignoreMessage(QtWarningMsg, "QQmlDebugClient: Conflicting plugin name \"tst_QQmlDebugClient::state()\"");
QQmlDebugClient client2("tst_QQmlDebugClient::state()", m_conn);
QCOMPARE(client2.state(), QQmlDebugClient::NotConnected);
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index 2cf6ee958a..fef020704f 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -984,7 +984,8 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
QVERIFY(init(TIMER_QMLFILE));
client->connect();
-
+ //We can set the breakpoint after connect() here because the timer is repeating and if we miss
+ //its first iteration we can still catch the second one.
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine, -1, true);
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
@@ -1004,8 +1005,8 @@ void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
int sourceLine = 43;
QVERIFY(init(LOADJSFILE_QMLFILE));
- client->connect();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TEST_JSFILE), sourceLine, -1, true);
+ client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
QString jsonString(client->response);
@@ -1025,8 +1026,8 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
int actualLine = 49;
QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
- client->connect();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
+ client->connect();
QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
@@ -1047,8 +1048,8 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
int actualLine = 49;
QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE));
- client->connect();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
+ client->connect();
QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort);
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1));
@@ -1093,6 +1094,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
QVERIFY(init(CONDITION_QMLFILE));
client->connect();
+ //The breakpoint is in a timer loop so we can set it after connect().
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10"));
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
@@ -1148,31 +1150,12 @@ void tst_QQmlDebugJS::setBreakpointWhenAttaching()
QVERIFY(init(QLatin1String(TIMER_QMLFILE), false));
client->connect();
+ //The breakpoint is in a timer loop so we can set it after connect().
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(TIMER_QMLFILE), sourceLine);
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
}
*/
-//void tst_QQmlDebugJS::setBreakpointInFunction()
-//{
-// //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
-
-// int actualLine = 31;
-
-// client->connect();
-// client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
-
-// QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
-
-// QString jsonString(client->response);
-// QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
-
-// QVariantMap body = value.value("body").toMap();
-
-// QCOMPARE(body.value("sourceLine").toInt(), actualLine);
-// QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
-//}
-
#if 0
void tst_QQmlDebugJS::setBreakpointOnEvent()
{
@@ -1182,9 +1165,8 @@ void tst_QQmlDebugJS::setBreakpointOnEvent()
QVERIFY(init(TIMER_QMLFILE));
- client->connect();
-
client->setBreakpoint(QLatin1String(EVENT), QLatin1String("triggered"), -1, -1, true);
+ client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
QString jsonString(client->response);
@@ -1205,6 +1187,9 @@ void tst_QQmlDebugJS::clearBreakpoint()
QVERIFY(init(CHANGEBREAKPOINT_QMLFILE));
client->connect();
+ //The breakpoints are in a timer loop so we can set them after connect().
+ //Furthermore the breakpoints should be hit in the right order because setting of breakpoints
+ //can only occur in the QML event loop. (see QCOMPARE for sourceLine2 below)
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine1, -1, true);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine2, -1, true);
@@ -1281,8 +1266,8 @@ void tst_QQmlDebugJS::stepIn()
int actualLine = 50;
QVERIFY(init(STEPACTION_QMLFILE));
- client->connect();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
+ client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
client->continueDebugging(QJSDebugClient::In);
@@ -1305,8 +1290,8 @@ void tst_QQmlDebugJS::stepOut()
int actualLine = 54;
QVERIFY(init(STEPACTION_QMLFILE));
- client->connect();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
+ client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
client->continueDebugging(QJSDebugClient::Out);
@@ -1329,9 +1314,9 @@ void tst_QQmlDebugJS::continueDebugging()
int sourceLine2 = 51;
QVERIFY(init(STEPACTION_QMLFILE));
- client->connect();
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
+ client->connect();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
client->continueDebugging(QJSDebugClient::Continue);
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index 1c1d84f37b..c50bb10035 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -164,7 +164,7 @@ void tst_QQmlDebugService::state()
QTRY_COMPARE(service.state(), QQmlDebugService::Unavailable);
- QTest::ignoreMessage(QtWarningMsg, "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService::state()\" ");
+ QTest::ignoreMessage(QtWarningMsg, "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService::state()\"");
QQmlDebugTestService duplicate("tst_QQmlDebugService::state()");
QCOMPARE(duplicate.state(), QQmlDebugService::NotConnected);
}
@@ -183,7 +183,7 @@ void tst_QQmlDebugService::sendMessage()
QByteArray resp = client.waitForResponse();
QCOMPARE(resp, msg);
- QTest::ignoreMessage(QtWarningMsg, "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService::sendMessage()\" ");
+ QTest::ignoreMessage(QtWarningMsg, "QQmlDebugService: Conflicting plugin name \"tst_QQmlDebugService::sendMessage()\"");
QQmlDebugTestService duplicate("tst_QQmlDebugService::sendMessage()");
duplicate.sendMessage("msg");
}
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/data/exit.qml b/tests/auto/qml/debugger/qqmlenginecontrol/data/exit.qml
new file mode 100644
index 0000000000..b250524caa
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/data/exit.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+Item {
+ Timer {
+ running: true
+ interval: 1
+ onTriggered: Qt.quit();
+ }
+}
diff --git a/tests/auto/qml/debugger/qv8profilerservice/data/test.qml b/tests/auto/qml/debugger/qqmlenginecontrol/data/test.qml
index 9c36e13c5b..9c36e13c5b 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/data/test.qml
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro b/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro
new file mode 100644
index 0000000000..09332cc302
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro
@@ -0,0 +1,18 @@
+CONFIG += testcase
+TARGET = tst_qqmlenginecontrol
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qqmlenginecontrol.cpp
+
+INCLUDEPATH += ../shared
+include(../../../shared/util.pri)
+include(../shared/debugutil.pri)
+
+TESTDATA = data/*
+
+QT += core qml testlib gui-private
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+OTHER_FILES += \
+ data/test.qml \
+ data/exit.qml
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
new file mode 100644
index 0000000000..3a88091165
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QLibraryInfo>
+
+#include "debugutil_p.h"
+#include "qqmldebugclient.h"
+#include "../../../shared/util.h"
+
+#define STR_PORT_FROM "13773"
+#define STR_PORT_TO "13783"
+
+class QQmlEngineControlClient : public QQmlDebugClient
+{
+ Q_OBJECT
+public:
+ enum MessageType {
+ EngineAboutToBeAdded,
+ EngineAdded,
+ EngineAboutToBeRemoved,
+ EngineRemoved,
+
+ MaximumMessageType
+ };
+
+ enum CommandType {
+ StartWaitingEngine,
+ StopWaitingEngine,
+
+ MaximumCommandType
+ };
+
+ QQmlEngineControlClient(QQmlDebugConnection *connection)
+ : QQmlDebugClient(QLatin1String("EngineControl"), connection)
+ {}
+
+
+ void command(CommandType command, int engine) {
+ QByteArray message;
+ QDataStream stream(&message, QIODevice::WriteOnly);
+ stream << (int)command << engine;
+ sendMessage(message);
+ }
+
+ QList<int> startingEngines;
+ QList<int> stoppingEngines;
+
+signals:
+ void engineAboutToBeAdded();
+ void engineAdded();
+ void engineAboutToBeRemoved();
+ void engineRemoved();
+
+protected:
+ void messageReceived(const QByteArray &message);
+};
+
+class tst_QQmlEngineControl : public QQmlDataTest
+{
+ Q_OBJECT
+
+public:
+ tst_QQmlEngineControl()
+ : m_process(0)
+ , m_connection(0)
+ , m_client(0)
+ {}
+
+
+private:
+ QQmlDebugProcess *m_process;
+ QQmlDebugConnection *m_connection;
+ QQmlEngineControlClient *m_client;
+
+ void connect(const QString &testFile);
+
+private slots:
+ void cleanup();
+
+ void startEngine();
+ void stopEngine();
+};
+
+void QQmlEngineControlClient::messageReceived(const QByteArray &message)
+{
+ QByteArray msg = message;
+ QDataStream stream(&msg, QIODevice::ReadOnly);
+
+ int messageType;
+ int engineId;
+ stream >> messageType >> engineId;
+
+ switch (messageType) {
+ case EngineAboutToBeAdded:
+ startingEngines.append(engineId);
+ emit engineAboutToBeAdded();
+ break;
+ case EngineAdded:
+ QVERIFY(startingEngines.contains(engineId));
+ startingEngines.removeOne(engineId);
+ emit engineAdded();
+ break;
+ case EngineAboutToBeRemoved:
+ stoppingEngines.append(engineId);
+ emit engineAboutToBeRemoved();
+ break;
+ case EngineRemoved:
+ QVERIFY(stoppingEngines.contains(engineId));
+ stoppingEngines.removeOne(engineId);
+ emit engineRemoved();
+ break;
+ default:
+ QString failMsg = QString("Unknown message type:") + messageType;
+ QFAIL(qPrintable(failMsg));
+ break;
+ }
+ QVERIFY(stream.atEnd());
+}
+
+void tst_QQmlEngineControl::connect(const QString &testFile)
+{
+ const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
+ QStringList arguments;
+ arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block");
+
+ arguments << QQmlDataTest::instance()->testFile(testFile);
+
+ m_process = new QQmlDebugProcess(executable, this);
+ m_process->start(QStringList() << arguments);
+ QVERIFY2(m_process->waitForSessionStart(), "Could not launch application, or did not get 'Waiting for connection'.");
+
+ m_connection = new QQmlDebugConnection();
+ m_client = new QQmlEngineControlClient(m_connection);
+
+ const int port = m_process->debugPort();
+ m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
+}
+
+void tst_QQmlEngineControl::cleanup()
+{
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Process State:" << (m_process ? m_process->state() : QLatin1String("null"));
+ qDebug() << "Application Output:" << (m_process ? m_process->output() : QLatin1String("null"));
+ qDebug() << "Connection State:" << (m_connection ? m_connection->stateString() : QLatin1String("null"));
+ qDebug() << "Client State:" << (m_client ? m_client->stateString() : QLatin1String("null"));
+ }
+ delete m_process;
+ m_process = 0;
+ delete m_client;
+ m_client = 0;
+ delete m_connection;
+ m_connection = 0;
+}
+
+void tst_QQmlEngineControl::startEngine()
+{
+ connect("test.qml");
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+
+ QTRY_VERIFY(!m_client->startingEngines.empty());
+ m_client->command(QQmlEngineControlClient::StartWaitingEngine, m_client->startingEngines.last());
+
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAdded())),
+ "No engine start message received in time.");
+}
+
+void tst_QQmlEngineControl::stopEngine()
+{
+ connect("exit.qml");
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+
+ QTRY_VERIFY(!m_client->startingEngines.empty());
+ m_client->command(QQmlEngineControlClient::StartWaitingEngine, m_client->startingEngines.last());
+
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAdded())),
+ "No engine start message received in time.");
+
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAboutToBeRemoved())),
+ "No engine about to stop message received in time.");
+ m_client->command(QQmlEngineControlClient::StopWaitingEngine, m_client->stoppingEngines.last());
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineRemoved())),
+ "No engine stop message received in time.");
+}
+
+QTEST_MAIN(tst_QQmlEngineControl)
+
+#include "tst_qqmlenginecontrol.moc"
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
new file mode 100644
index 0000000000..0555d49652
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+Rectangle {
+ function something(i) {
+ if (i > 10) {
+ something(i / 4);
+ } else {
+ console.log("done");
+ }
+ }
+
+ width: 400
+ height: 400
+
+ onWidthChanged: something(width);
+ Component.onCompleted: width = 500;
+}
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
index d08ed31e8b..1bab614b63 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
@@ -16,4 +16,9 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
OTHER_FILES += \
data/pixmapCacheTest.qml \
data/controlFromJS.qml \
- data/signalSourceLocation.qml
+ data/test.qml \
+ data/exit.qml \
+ data/scenegraphTest.qml \
+ data/TestImage_2x2.png \
+ data/signalSourceLocation.qml \
+ data/javascript.qml
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 276dcf5d29..6dbdc83b08 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -100,6 +100,7 @@ public:
Creating,
Binding, //running a binding
HandlingSignal, //running a signal handler
+ Javascript,
MaximumRangeType
};
@@ -182,6 +183,7 @@ private slots:
void profileOnExit();
void controlFromJS();
void signalSourceLocation();
+ void javascript();
};
void QQmlProfilerClient::messageReceived(const QByteArray &message)
@@ -214,9 +216,16 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
case QQmlProfilerClient::FramePaint:
case QQmlProfilerClient::Mouse:
case QQmlProfilerClient::Key:
- case QQmlProfilerClient::StartTrace:
+ break;
case QQmlProfilerClient::EndTrace:
+ case QQmlProfilerClient::StartTrace: {
+ int engineId = -1;
+ if (!stream.atEnd()) {
+ stream >> engineId;
+ QVERIFY(engineId >= 0);
+ }
break;
+ }
default: {
QString failMsg = QString("Unknown event type:") + data.detailType;
QFAIL(qPrintable(failMsg));
@@ -406,14 +415,14 @@ void tst_QQmlProfilerService::pixmapCacheData()
m_client->setTraceState(true);
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
- QVERIFY(m_process->output().indexOf(QLatin1String("image loaded")) != -1 ||
- m_process->output().indexOf(QLatin1String("image error")) != -1 );
-
+ while (m_process->output().indexOf(QLatin1String("image loaded")) == -1 &&
+ m_process->output().indexOf(QLatin1String("image error")) == -1)
+ QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
- QVERIFY(m_client->traceMessages.count());
+ QVERIFY(m_client->traceMessages.count() >= 20);
// must start with "StartTrace"
QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
@@ -423,15 +432,15 @@ void tst_QQmlProfilerService::pixmapCacheData()
QCOMPARE(m_client->traceMessages[16].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
QCOMPARE(m_client->traceMessages[16].detailType, (int)QQmlProfilerClient::PixmapLoadingStarted);
- // image loaded
+ // image size
QCOMPARE(m_client->traceMessages[17].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
- QCOMPARE(m_client->traceMessages[17].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished);
+ QCOMPARE(m_client->traceMessages[17].detailType, (int)QQmlProfilerClient::PixmapSizeKnown);
+ QCOMPARE(m_client->traceMessages[17].line, 2); // width
+ QCOMPARE(m_client->traceMessages[17].column, 2); // height
- // image size
+ // image loaded
QCOMPARE(m_client->traceMessages[18].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
- QCOMPARE(m_client->traceMessages[18].detailType, (int)QQmlProfilerClient::PixmapSizeKnown);
- QCOMPARE(m_client->traceMessages[18].line, 2); // width
- QCOMPARE(m_client->traceMessages[18].column, 2); // height
+ QCOMPARE(m_client->traceMessages[18].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished);
// cache size
QCOMPARE(m_client->traceMessages[19].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
@@ -486,6 +495,7 @@ void tst_QQmlProfilerService::profileOnExit()
m_client->setTraceState(true);
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+ QVERIFY(m_client->traceMessages.count() >= 2);
// must start with "StartTrace"
QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
@@ -504,6 +514,7 @@ void tst_QQmlProfilerService::controlFromJS()
m_client->setTraceState(false);
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+ QVERIFY(m_client->traceMessages.count() >= 2);
// must start with "StartTrace"
QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
@@ -526,17 +537,60 @@ void tst_QQmlProfilerService::signalSourceLocation()
m_client->setTraceState(false);
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+ QVERIFY(m_client->traceMessages.count() >= 20);
// must start with "StartTrace"
QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
+ QVERIFY(m_client->traceMessages[14].messageType == QQmlProfilerClient::RangeLocation);
+ QVERIFY(m_client->traceMessages[14].detailType == QQmlProfilerClient::HandlingSignal);
QVERIFY(m_client->traceMessages[14].detailData.endsWith("signalSourceLocation.qml"));
QVERIFY(m_client->traceMessages[14].line == 8);
QVERIFY(m_client->traceMessages[14].column == 28);
- QVERIFY(m_client->traceMessages[16].detailData.endsWith("signalSourceLocation.qml"));
- QVERIFY(m_client->traceMessages[16].line == 7);
- QVERIFY(m_client->traceMessages[16].column == 21);
+ QVERIFY(m_client->traceMessages[19].messageType == QQmlProfilerClient::RangeLocation);
+ QVERIFY(m_client->traceMessages[19].detailType == QQmlProfilerClient::HandlingSignal);
+ QVERIFY(m_client->traceMessages[19].detailData.endsWith("signalSourceLocation.qml"));
+ QVERIFY(m_client->traceMessages[19].line == 7);
+ QVERIFY(m_client->traceMessages[19].column == 21);
+
+ // must end with "EndTrace"
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+}
+
+void tst_QQmlProfilerService::javascript()
+{
+ connect(true, "javascript.qml");
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+
+ m_client->setTraceState(true);
+ while (!(m_process->output().contains(QLatin1String("done"))))
+ QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
+ m_client->setTraceState(false);
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+
+ QVERIFY(m_client->traceMessages.count() >= 36);
+ // must start with "StartTrace"
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
+
+ QVERIFY(m_client->traceMessages[32].messageType == QQmlProfilerClient::RangeStart);
+ QVERIFY(m_client->traceMessages[32].detailType == QQmlProfilerClient::Javascript);
+
+ QVERIFY(m_client->traceMessages[33].messageType == QQmlProfilerClient::RangeLocation);
+ QVERIFY(m_client->traceMessages[33].detailType == QQmlProfilerClient::Javascript);
+ QVERIFY(m_client->traceMessages[33].detailData.endsWith("javascript.qml"));
+ QVERIFY(m_client->traceMessages[33].line == 4);
+ QVERIFY(m_client->traceMessages[33].column == 5);
+
+ QVERIFY(m_client->traceMessages[34].messageType == QQmlProfilerClient::RangeData);
+ QVERIFY(m_client->traceMessages[34].detailType == QQmlProfilerClient::Javascript);
+ QVERIFY(m_client->traceMessages[34].detailData == "something");
+
+ QVERIFY(m_client->traceMessages[35].messageType == QQmlProfilerClient::RangeEnd);
+ QVERIFY(m_client->traceMessages[35].detailType == QQmlProfilerClient::Javascript);
// must end with "EndTrace"
QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
diff --git a/tests/auto/qml/debugger/qv8profilerservice/data/console.qml b/tests/auto/qml/debugger/qv4profilerservice/data/console.qml
index c23c820216..c23c820216 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/data/console.qml
+++ b/tests/auto/qml/debugger/qv4profilerservice/data/console.qml
diff --git a/tests/auto/qml/debugger/qv8profilerservice/data/exit.qml b/tests/auto/qml/debugger/qv4profilerservice/data/exit.qml
index 604265354c..604265354c 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/data/exit.qml
+++ b/tests/auto/qml/debugger/qv4profilerservice/data/exit.qml
diff --git a/tests/auto/qml/debugger/qv4profilerservice/data/test.qml b/tests/auto/qml/debugger/qv4profilerservice/data/test.qml
new file mode 100644
index 0000000000..9c36e13c5b
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4profilerservice/data/test.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+
+}
diff --git a/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro b/tests/auto/qml/debugger/qv4profilerservice/qv4profilerservice.pro
index dc6f4c5038..459f931f94 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro
+++ b/tests/auto/qml/debugger/qv4profilerservice/qv4profilerservice.pro
@@ -1,8 +1,8 @@
CONFIG += testcase
-TARGET = tst_qv8profilerservice
+TARGET = tst_qv4profilerservice
macx:CONFIG -= app_bundle
-SOURCES += tst_qv8profilerservice.cpp
+SOURCES += tst_qv4profilerservice.cpp
INCLUDEPATH += ../shared
include(../../../shared/util.pri)
diff --git a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/qml/debugger/qv4profilerservice/tst_qv4profilerservice.cpp
index a461519c75..23dfb3c75f 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
+++ b/tests/auto/qml/debugger/qv4profilerservice/tst_qv4profilerservice.cpp
@@ -49,7 +49,7 @@
#define STR_PORT_FROM "13774"
#define STR_PORT_TO "13790"
-struct QV8ProfilerData
+struct QV4ProfilerData
{
int messageType;
QString filename;
@@ -62,24 +62,24 @@ struct QV8ProfilerData
QByteArray toByteArray() const;
};
-class QV8ProfilerClient : public QQmlDebugClient
+class QV4ProfilerClient : public QQmlDebugClient
{
Q_OBJECT
public:
enum MessageType {
- V8Entry,
- V8Complete,
- V8SnapshotChunk,
- V8SnapshotComplete,
- V8Started,
+ V4Entry,
+ V4Complete,
+ V4SnapshotChunk,
+ V4SnapshotComplete,
+ V4Started,
- V8MaximumMessage
+ V4MaximumMessage
};
enum ServiceState { NotRunning, Running } serviceState;
- QV8ProfilerClient(QQmlDebugConnection *connection)
+ QV4ProfilerClient(QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("V8Profiler"), connection)
, serviceState(NotRunning)
{
@@ -113,7 +113,7 @@ public:
sendMessage(message);
}
- QList<QV8ProfilerData> traceMessages;
+ QList<QV4ProfilerData> traceMessages;
QList<QByteArray> snapshotMessages;
signals:
@@ -125,12 +125,12 @@ protected:
void messageReceived(const QByteArray &message);
};
-class tst_QV8ProfilerService : public QQmlDataTest
+class tst_QV4ProfilerService : public QQmlDataTest
{
Q_OBJECT
public:
- tst_QV8ProfilerService()
+ tst_QV4ProfilerService()
: m_process(0)
, m_connection(0)
, m_client(0)
@@ -140,7 +140,7 @@ public:
private:
QQmlDebugProcess *m_process;
QQmlDebugConnection *m_connection;
- QV8ProfilerClient *m_client;
+ QV4ProfilerClient *m_client;
bool connect(bool block, const QString &testFile, QString *error);
@@ -155,7 +155,7 @@ private slots:
void console();
};
-void QV8ProfilerClient::messageReceived(const QByteArray &message)
+void QV4ProfilerClient::messageReceived(const QByteArray &message)
{
QByteArray msg = message;
QDataStream stream(&msg, QIODevice::ReadOnly);
@@ -164,31 +164,31 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message)
stream >> messageType;
QVERIFY(messageType >= 0);
- QVERIFY(messageType < QV8ProfilerClient::V8MaximumMessage);
+ QVERIFY(messageType < QV4ProfilerClient::V4MaximumMessage);
switch (messageType) {
- case QV8ProfilerClient::V8Entry: {
+ case QV4ProfilerClient::V4Entry: {
QCOMPARE(serviceState, Running);
- QV8ProfilerData entry;
+ QV4ProfilerData entry;
stream >> entry.filename >> entry.functionname >> entry.lineNumber >> entry.totalTime >> entry.selfTime >> entry.treeLevel;
traceMessages.append(entry);
break;
}
- case QV8ProfilerClient::V8Complete:
+ case QV4ProfilerClient::V4Complete:
QCOMPARE(serviceState, Running);
serviceState = NotRunning;
emit complete();
break;
- case QV8ProfilerClient::V8SnapshotChunk: {
+ case QV4ProfilerClient::V4SnapshotChunk: {
QByteArray json;
stream >> json;
snapshotMessages.append(json);
break;
}
- case QV8ProfilerClient::V8SnapshotComplete:
+ case QV4ProfilerClient::V4SnapshotComplete:
emit snapshot();
break;
- case QV8ProfilerClient::V8Started:
+ case QV4ProfilerClient::V4Started:
QCOMPARE(serviceState, NotRunning);
serviceState = Running;
emit started();
@@ -201,7 +201,7 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message)
QVERIFY(stream.atEnd());
}
-bool tst_QV8ProfilerService::connect(bool block, const QString &testFile,
+bool tst_QV4ProfilerService::connect(bool block, const QString &testFile,
QString *error)
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml";
@@ -215,7 +215,7 @@ bool tst_QV8ProfilerService::connect(bool block, const QString &testFile,
arguments << QQmlDataTest::instance()->testFile(testFile);
m_connection = new QQmlDebugConnection();
- m_client = new QV8ProfilerClient(m_connection);
+ m_client = new QV4ProfilerClient(m_connection);
m_process = new QQmlDebugProcess(executable);
m_process->start(QStringList() << arguments);
@@ -232,7 +232,7 @@ bool tst_QV8ProfilerService::connect(bool block, const QString &testFile,
return true;
}
-void tst_QV8ProfilerService::cleanup()
+void tst_QV4ProfilerService::cleanup()
{
if (QTest::currentTestFailed()) {
qDebug() << "Process State:" << m_process->state();
@@ -243,7 +243,7 @@ void tst_QV8ProfilerService::cleanup()
delete m_connection;
}
-void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
+void tst_QV4ProfilerService::blockingConnectWithTraceEnabled()
{
QString error;
if (!connect(true, "test.qml", &error))
@@ -257,7 +257,7 @@ void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
"No trace received in time.");
}
-void tst_QV8ProfilerService::blockingConnectWithTraceDisabled()
+void tst_QV4ProfilerService::blockingConnectWithTraceDisabled()
{
QString error;
if (!connect(true, "test.qml", &error))
@@ -274,7 +274,7 @@ void tst_QV8ProfilerService::blockingConnectWithTraceDisabled()
"No trace received in time.");
}
-void tst_QV8ProfilerService::nonBlockingConnect()
+void tst_QV4ProfilerService::nonBlockingConnect()
{
QString error;
if (!connect(false, "test.qml", &error))
@@ -288,7 +288,7 @@ void tst_QV8ProfilerService::nonBlockingConnect()
"No trace received in time.");
}
-void tst_QV8ProfilerService::snapshot()
+void tst_QV4ProfilerService::snapshot()
{
QString error;
if (!connect(false, "test.qml", &error))
@@ -301,7 +301,7 @@ void tst_QV8ProfilerService::snapshot()
"No trace received in time.");
}
-void tst_QV8ProfilerService::profileOnExit()
+void tst_QV4ProfilerService::profileOnExit()
{
QString error;
if (!connect(true, "exit.qml", &error))
@@ -314,7 +314,7 @@ void tst_QV8ProfilerService::profileOnExit()
"No trace received in time.");
}
-void tst_QV8ProfilerService::console()
+void tst_QV4ProfilerService::console()
{
QString error;
if (!connect(true, "console.qml", &error))
@@ -329,6 +329,6 @@ void tst_QV8ProfilerService::console()
QVERIFY(!m_client->traceMessages.isEmpty());
}
-QTEST_MAIN(tst_QV8ProfilerService)
+QTEST_MAIN(tst_QV4ProfilerService)
-#include "tst_qv8profilerservice.moc"
+#include "tst_qv4profilerservice.moc"
diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
index 6474a04796..80322dc841 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp
@@ -388,7 +388,7 @@ QQmlDebugClientPrivate::QQmlDebugClientPrivate()
{
}
-QQmlDebugClient::QQmlDebugClient(const QString &name,
+QQmlDebugClient::QQmlDebugClient(const QString &name,
QQmlDebugConnection *parent)
: QObject(parent),
d(new QQmlDebugClientPrivate)
diff --git a/tests/auto/qml/parserstress/tests/shell.js b/tests/auto/qml/parserstress/tests/shell.js
index 40af0f3799..b3a84cc2ed 100644
--- a/tests/auto/qml/parserstress/tests/shell.js
+++ b/tests/auto/qml/parserstress/tests/shell.js
@@ -191,7 +191,7 @@ function reportFailure (msg)
var l;
var funcName = currentFunc();
var prefix = (funcName) ? "[reported from " + funcName + "] ": "";
-
+
for (var i=0; i<lines.length; i++)
print (FAILED + prefix + lines[i]);
}
@@ -224,11 +224,11 @@ function printBugNumber (num)
function toPrinted(value)
{
- if (typeof value == "xml")
+ if (typeof value == "xml")
{
value = value.toXMLString();
- }
- else
+ }
+ else
{
value = String(value);
}
@@ -406,7 +406,7 @@ function enterFunc (funcName)
function exitFunc (funcName)
{
var lastFunc = callStack.pop();
-
+
if (funcName)
{
if (!funcName.match(/\(\)$/))
@@ -516,7 +516,7 @@ function BigO(data)
{
var Ydiff = Y[i] - this.Yavg;
var Xdiff = X[i] - this.Xavg;
-
+
SUM_Ydiff2 += Ydiff * Ydiff;
SUM_Xdiff2 += Xdiff * Xdiff;
SUM_XdiffYdiff += Xdiff * Ydiff;
@@ -552,7 +552,7 @@ function BigO(data)
{
deriv.X[i] = (X[i] + X[i+1])/2;
deriv.Y[i] = (Y[i+1] - Y[i])/(X[i+1] - X[i]);
- }
+ }
return deriv;
}
@@ -628,7 +628,7 @@ function optionsInit() {
}
function optionsClear() {
-
+
// turn off current settings
var optionNames = options().split(',');
for (var i = 0; i < optionNames.length; i++)
@@ -696,27 +696,27 @@ function getTestCaseResult(expected, actual)
var expected_t = typeof expected;
var actual_t = typeof actual;
var passed = true;
-
+
// because ( NaN == NaN ) always returns false, need to do
// a special compare to see if we got the right result.
- if ( actual != actual )
+ if ( actual != actual )
{
- if ( actual_t == "object" )
+ if ( actual_t == "object" )
{
actual = "NaN object";
- }
- else
+ }
+ else
{
actual = "NaN number";
}
}
- if ( expected != expected )
+ if ( expected != expected )
{
- if ( expected_t == "object" )
+ if ( expected_t == "object" )
{
expected = "NaN object";
- }
- else
+ }
+ else
{
expected = "NaN number";
}
@@ -733,7 +733,7 @@ function getTestCaseResult(expected, actual)
passed = false;
}
}
-
+
return passed;
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 44c113ba13..bb5f83bed1 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -49,6 +49,7 @@
#include <QtCore/qnumeric.h>
#include <qqmlengine.h>
#include <stdlib.h>
+#include <private/qv4alloca_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -56,12 +57,6 @@
#define NO_INLINE __attribute__((noinline))
#endif
-#if defined(Q_OS_WIN)
-#include <malloc.h>
-#else
-#include <alloca.h>
-#endif
-
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QObjectList)
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index 489972716d..7811ce5e5b 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -129,11 +129,10 @@ void tst_qqmlapplicationengine::application()
void tst_qqmlapplicationengine::applicationProperties()
{
- QCoreApplication* coreApp = QCoreApplication::instance();
- QString originalName = coreApp->applicationName();
- QString originalVersion = coreApp->applicationVersion();
- QString originalOrganization = coreApp->organizationName();
- QString originalDomain = coreApp->organizationDomain();
+ const QString originalName = QCoreApplication::applicationName();
+ const QString originalVersion = QCoreApplication::applicationVersion();
+ const QString originalOrganization = QCoreApplication::organizationName();
+ const QString originalDomain = QCoreApplication::organizationDomain();
QString firstName = QLatin1String("Test A");
QString firstVersion = QLatin1String("0.0A");
QString firstOrganization = QLatin1String("Org A");
@@ -143,10 +142,10 @@ void tst_qqmlapplicationengine::applicationProperties()
QString secondOrganization = QLatin1String("Org B");
QString secondDomain = QLatin1String("b.org");
- coreApp->setApplicationName(firstName);
- coreApp->setApplicationVersion(firstVersion);
- coreApp->setOrganizationName(firstOrganization);
- coreApp->setOrganizationDomain(firstDomain);
+ QCoreApplication::setApplicationName(firstName);
+ QCoreApplication::setApplicationVersion(firstVersion);
+ QCoreApplication::setOrganizationName(firstOrganization);
+ QCoreApplication::setOrganizationDomain(firstDomain);
QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("applicationTest.qml"));
QObject* root = test->rootObjects().at(0);
@@ -159,10 +158,10 @@ void tst_qqmlapplicationengine::applicationProperties()
QCOMPARE(root->property("currentVersion").toString(), secondVersion);
QCOMPARE(root->property("currentOrganization").toString(), secondOrganization);
QCOMPARE(root->property("currentDomain").toString(), secondDomain);
- QCOMPARE(coreApp->applicationName(), secondName);
- QCOMPARE(coreApp->applicationVersion(), secondVersion);
- QCOMPARE(coreApp->organizationName(), secondOrganization);
- QCOMPARE(coreApp->organizationDomain(), secondDomain);
+ QCOMPARE(QCoreApplication::applicationName(), secondName);
+ QCOMPARE(QCoreApplication::applicationVersion(), secondVersion);
+ QCOMPARE(QCoreApplication::organizationName(), secondOrganization);
+ QCOMPARE(QCoreApplication::organizationDomain(), secondDomain);
QObject* application = root->property("applicationInstance").value<QObject*>();
QVERIFY(application);
@@ -171,10 +170,10 @@ void tst_qqmlapplicationengine::applicationProperties()
QSignalSpy organizationChanged(application, SIGNAL(organizationChanged()));
QSignalSpy domainChanged(application, SIGNAL(domainChanged()));
- coreApp->setApplicationName(originalName);
- coreApp->setApplicationVersion(originalVersion);
- coreApp->setOrganizationName(originalOrganization);
- coreApp->setOrganizationDomain(originalDomain);
+ QCoreApplication::setApplicationName(originalName);
+ QCoreApplication::setApplicationVersion(originalVersion);
+ QCoreApplication::setOrganizationName(originalOrganization);
+ QCoreApplication::setOrganizationDomain(originalDomain);
QCOMPARE(nameChanged.count(), 1);
QCOMPARE(versionChanged.count(), 1);
diff --git a/tests/auto/qml/qqmlcomponent/data/incubateObject.qml b/tests/auto/qml/qqmlcomponent/data/incubateObject.qml
index c11319db30..fcc88a7647 100644
--- a/tests/auto/qml/qqmlcomponent/data/incubateObject.qml
+++ b/tests/auto/qml/qqmlcomponent/data/incubateObject.qml
@@ -8,12 +8,12 @@ Item{
property var i
- Component{
+ Component{
id: component
Item {
property int dummy: 13
property int dummy2: 26
- }
+ }
}
Component.onCompleted: {
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index a37d705284..43aa82e1e4 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -116,7 +116,7 @@ void tst_qqmlconsole::profiling()
// profiling()
QTest::ignoreMessage(QtWarningMsg, "Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
- QTest::ignoreMessage(QtWarningMsg, "Profiling was not started.");
+ QTest::ignoreMessage(QtWarningMsg, "Ignoring console.profileEnd(): the debug service is disabled.");
QQmlComponent component(&engine, testUrl);
QObject *object = component.create();
diff --git a/tests/auto/qml/qqmlecmascript/data/aliasBindingsAssignCorrectly.qml b/tests/auto/qml/qqmlecmascript/data/aliasBindingsAssignCorrectly.qml
index ff6c553c31..113b9f111b 100644
--- a/tests/auto/qml/qqmlecmascript/data/aliasBindingsAssignCorrectly.qml
+++ b/tests/auto/qml/qqmlecmascript/data/aliasBindingsAssignCorrectly.qml
@@ -2,7 +2,7 @@ import QtQuick 2.0
Item {
id: root
-
+
property bool test: false
property real testData: 9
diff --git a/tests/auto/qml/qqmlecmascript/data/aliasBindingsOverrideTarget.3.qml b/tests/auto/qml/qqmlecmascript/data/aliasBindingsOverrideTarget.3.qml
index 3e4cda6ba3..c68dfcd60d 100644
--- a/tests/auto/qml/qqmlecmascript/data/aliasBindingsOverrideTarget.3.qml
+++ b/tests/auto/qml/qqmlecmascript/data/aliasBindingsOverrideTarget.3.qml
@@ -11,7 +11,7 @@ Item {
id: obj
testProperty: root.value1 * 9
- aliasProperty: root.value2 * 10
+ aliasProperty: root.value2 * 10
}
Component.onCompleted: {
diff --git a/tests/auto/qml/qqmlecmascript/data/aliasPropertyAndBinding.qml b/tests/auto/qml/qqmlecmascript/data/aliasPropertyAndBinding.qml
index f228b2c19f..7c871875b2 100644
--- a/tests/auto/qml/qqmlecmascript/data/aliasPropertyAndBinding.qml
+++ b/tests/auto/qml/qqmlecmascript/data/aliasPropertyAndBinding.qml
@@ -4,9 +4,9 @@ import Qt.test 1.0
MyQmlObject {
property alias c1: myObject.c1
property int c2: 3
- property int c3: c2
- objectProperty: QtObject {
- id: myObject
+ property int c3: c2
+ objectProperty: QtObject {
+ id: myObject
property int c1
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml
index ff6d7311a1..821e1b2356 100644
--- a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.2.qml
@@ -12,7 +12,7 @@ MyTypeObject {
floatProperty: if(1) 8.5
colorProperty: if(1) "red"
dateProperty: if(1) "1982-11-25"
- timeProperty: if(1) "11:11:32"
+ timeProperty: if(1) "11:11:32"
dateTimeProperty: if(1) "2009-05-12T13:22:01"
pointProperty: if(1) "99,13"
pointFProperty: if(1) "-10.1,12.3"
diff --git a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml
index ce3511f72a..b7c1e1cc39 100644
--- a/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml
+++ b/tests/auto/qml/qqmlecmascript/data/assignBasicTypes.qml
@@ -14,7 +14,7 @@ MyTypeObject {
floatProperty = 8.5
colorProperty = "red"
dateProperty = "1982-11-25"
- timeProperty = "11:11:32"
+ timeProperty = "11:11:32"
dateTimeProperty = "2009-05-12T13:22:01"
pointProperty = "99,13"
pointFProperty = "-10.1,12.3"
diff --git a/tests/auto/qml/qqmlecmascript/data/bindingLoop.qml b/tests/auto/qml/qqmlecmascript/data/bindingLoop.qml
index 80545cf72b..e49a26d909 100644
--- a/tests/auto/qml/qqmlecmascript/data/bindingLoop.qml
+++ b/tests/auto/qml/qqmlecmascript/data/bindingLoop.qml
@@ -1,14 +1,14 @@
import Qt.test 1.0
-MyQmlContainer {
- children : [
- MyQmlObject {
- id: object1
- stringProperty: "hello" + object2.stringProperty
+MyQmlContainer {
+ children : [
+ MyQmlObject {
+ id: object1
+ stringProperty: "hello" + object2.stringProperty
},
- MyQmlObject {
- id: object2
- stringProperty: "hello" + object1.stringProperty
- }
- ]
+ MyQmlObject {
+ id: object2
+ stringProperty: "hello" + object1.stringProperty
+ }
+ ]
}
diff --git a/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml b/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml
index 3147f63989..054ecb98f6 100644
--- a/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml
+++ b/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.1.qml
@@ -1,5 +1,5 @@
import Qt.test 1.0
-MyQmlObject {
- stringProperty: trueProperty?'pass':'fail'
+MyQmlObject {
+ stringProperty: trueProperty?'pass':'fail'
}
diff --git a/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml b/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml
index c89bb49b45..37c747b3a0 100644
--- a/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/boolPropertiesEvaluateAsBool.2.qml
@@ -1,5 +1,5 @@
import Qt.test 1.0
-MyQmlObject {
- stringProperty: falseProperty?'fail':'pass'
+MyQmlObject {
+ stringProperty: falseProperty?'fail':'pass'
}
diff --git a/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.2.qml b/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.2.qml
index 207a06b700..7a0b0d6e3c 100644
--- a/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.2.qml
@@ -4,8 +4,8 @@ MyQmlObject {
property alias c1: myConstants.c1
property alias c2: myConstants.c2
- objectProperty: ConstantsOverrideBindings {
+ objectProperty: ConstantsOverrideBindings {
id: myConstants
- c2: 10
+ c2: 10
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.4.qml b/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.4.qml
index 5a2091f71c..0c900d78a4 100644
--- a/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/constantsOverrideBindings.4.qml
@@ -4,7 +4,7 @@ MyQmlObject {
property alias c1: myConstants.c1
property alias c3: myConstants.c3
- objectProperty: ConstantsOverrideBindings {
+ objectProperty: ConstantsOverrideBindings {
id: myConstants
c3: 10
}
diff --git a/tests/auto/qml/qqmlecmascript/data/deletedEngine.qml b/tests/auto/qml/qqmlecmascript/data/deletedEngine.qml
index 97acddf5fc..b3adaac20e 100644
--- a/tests/auto/qml/qqmlecmascript/data/deletedEngine.qml
+++ b/tests/auto/qml/qqmlecmascript/data/deletedEngine.qml
@@ -2,7 +2,7 @@ import QtQuick 2.0
QtObject {
function calculate() {
- return b * 13;
+ return b * 13;
}
property int a: calculate()
diff --git a/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.2.qml b/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.2.qml
index 9a5732c194..af995150f1 100644
--- a/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.2.qml
@@ -14,7 +14,7 @@ QtObject {
function create() {
objectProperty = c.createObject(root);
}
-
+
function destroy() {
objectProperty.destroy();
}
diff --git a/tests/auto/qml/qqmlecmascript/data/eval.qml b/tests/auto/qml/qqmlecmascript/data/eval.qml
index a752b8c0d3..87e52d383a 100644
--- a/tests/auto/qml/qqmlecmascript/data/eval.qml
+++ b/tests/auto/qml/qqmlecmascript/data/eval.qml
@@ -1,11 +1,11 @@
import QtQuick 2.0
QtObject {
- property bool test1: false;
- property bool test2: false;
- property bool test3: false;
- property bool test4: false;
- property bool test5: false;
+ property bool test1: false;
+ property bool test2: false;
+ property bool test3: false;
+ property bool test4: false;
+ property bool test5: false;
property int a: 7
diff --git a/tests/auto/qml/qqmlecmascript/data/include.qml b/tests/auto/qml/qqmlecmascript/data/include.qml
index 5ce2ed78ec..7a8c69d3f7 100644
--- a/tests/auto/qml/qqmlecmascript/data/include.qml
+++ b/tests/auto/qml/qqmlecmascript/data/include.qml
@@ -11,8 +11,8 @@ QtObject {
property int testValue: 99
- Component.onCompleted: {
- IncludeTest.go();
+ Component.onCompleted: {
+ IncludeTest.go();
test0 = IncludeTest.value
test1 = IncludeTest.test1
test2 = IncludeTest.test2
diff --git a/tests/auto/qml/qqmlecmascript/data/include_callback.qml b/tests/auto/qml/qqmlecmascript/data/include_callback.qml
index fbebcdcd58..2f8ae28696 100644
--- a/tests/auto/qml/qqmlecmascript/data/include_callback.qml
+++ b/tests/auto/qml/qqmlecmascript/data/include_callback.qml
@@ -9,7 +9,7 @@ QtObject {
property bool test5: false
property bool test6: false
- Component.onCompleted: {
- IncludeTest.go();
+ Component.onCompleted: {
+ IncludeTest.go();
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/include_remote.js b/tests/auto/qml/qqmlecmascript/data/include_remote.js
index e6a4676819..4331cb79d0 100644
--- a/tests/auto/qml/qqmlecmascript/data/include_remote.js
+++ b/tests/auto/qml/qqmlecmascript/data/include_remote.js
@@ -2,8 +2,8 @@ var myvar = 10;
function go()
{
- var a = Qt.include("http://127.0.0.1:8111/remote_file.js",
- function(o) {
+ var a = Qt.include("http://127.0.0.1:8111/remote_file.js",
+ function(o) {
test2 = o.status == o.OK
test3 = a.status == a.OK
test4 = myvar == 13
@@ -13,8 +13,8 @@ function go()
test1 = a.status == a.LOADING
- var b = Qt.include("http://127.0.0.1:8111/exception.js",
- function(o) {
+ var b = Qt.include("http://127.0.0.1:8111/exception.js",
+ function(o) {
test7 = o.status == o.EXCEPTION
test8 = b.status == a.EXCEPTION
test9 = b.exception.toString() == "Whoops!";
diff --git a/tests/auto/qml/qqmlecmascript/data/include_remote_missing.js b/tests/auto/qml/qqmlecmascript/data/include_remote_missing.js
index cc90860cc9..27dd63badf 100644
--- a/tests/auto/qml/qqmlecmascript/data/include_remote_missing.js
+++ b/tests/auto/qml/qqmlecmascript/data/include_remote_missing.js
@@ -1,7 +1,7 @@
function go()
{
- var a = Qt.include("http://127.0.0.1:8111/missing.js",
- function(o) {
+ var a = Qt.include("http://127.0.0.1:8111/missing.js",
+ function(o) {
test2 = o.status == o.NETWORK_ERROR
test3 = a.status == a.NETWORK_ERROR
diff --git a/tests/auto/qml/qqmlecmascript/data/include_shared.qml b/tests/auto/qml/qqmlecmascript/data/include_shared.qml
index 28b1003fd4..66c07e871b 100644
--- a/tests/auto/qml/qqmlecmascript/data/include_shared.qml
+++ b/tests/auto/qml/qqmlecmascript/data/include_shared.qml
@@ -9,8 +9,8 @@ QtObject {
property bool test3: false
property bool test3_1: false
- Component.onCompleted: {
- IncludeTest.go();
+ Component.onCompleted: {
+ IncludeTest.go();
test0 = IncludeTest.value
test1 = IncludeTest.test1
test2 = IncludeTest.test2
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/creationContext.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/creationContext.qml
new file mode 100644
index 0000000000..c4d0c7284c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/creationContext.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+import "importFour.js" as SomeScript
+
+Item {
+ id: root
+ property bool success: false;
+ Component {
+ id: testComponent
+ Item {
+ property string valueFromScript: SomeScript.greetingString()
+ }
+ }
+ property Loader loader;
+ signal loaded
+ onLoaded: {
+ success = (loader.item.valueFromScript === SomeScript.greetingString())
+ }
+ Component.onCompleted: {
+ loader = Qt.createQmlObject("import QtQuick 2.0; Loader {}", this, "dynamic loader")
+ loader.onLoaded.connect(loaded)
+ loader.sourceComponent = testComponent
+ }
+}
+
diff --git a/tests/auto/qml/qqmlecmascript/data/methods.1.qml b/tests/auto/qml/qqmlecmascript/data/methods.1.qml
index 0bbee16df8..5c5b3412a5 100644
--- a/tests/auto/qml/qqmlecmascript/data/methods.1.qml
+++ b/tests/auto/qml/qqmlecmascript/data/methods.1.qml
@@ -1,6 +1,6 @@
import Qt.test 1.0
-MyQmlObject {
+MyQmlObject {
id: myObject
- onBasicSignal: myObject.methodNoArgs()
+ onBasicSignal: myObject.methodNoArgs()
}
diff --git a/tests/auto/qml/qqmlecmascript/data/methods.2.qml b/tests/auto/qml/qqmlecmascript/data/methods.2.qml
index 9f0c6b15fe..b2adaf65cb 100644
--- a/tests/auto/qml/qqmlecmascript/data/methods.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/methods.2.qml
@@ -1,6 +1,6 @@
import Qt.test 1.0
-MyQmlObject {
+MyQmlObject {
id: myObject
- onBasicSignal: myObject.method(163)
+ onBasicSignal: myObject.method(163)
}
diff --git a/tests/auto/qml/qqmlecmascript/data/outerBindingOverridesInnerBinding.qml b/tests/auto/qml/qqmlecmascript/data/outerBindingOverridesInnerBinding.qml
index 090c948f26..a57b09fe6a 100644
--- a/tests/auto/qml/qqmlecmascript/data/outerBindingOverridesInnerBinding.qml
+++ b/tests/auto/qml/qqmlecmascript/data/outerBindingOverridesInnerBinding.qml
@@ -6,8 +6,8 @@ MyQmlObject {
property alias c2: myConstants.c2
property int c3: 0
- objectProperty: ConstantsOverrideBindings {
- id: myConstants
+ objectProperty: ConstantsOverrideBindings {
+ id: myConstants
c2: obj.c3
}
diff --git a/tests/auto/qml/qqmlecmascript/data/propertySplicing.qml b/tests/auto/qml/qqmlecmascript/data/propertySplicing.qml
index 53711db3f4..d079d5ce99 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertySplicing.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertySplicing.qml
@@ -3,7 +3,7 @@ import QtQuick 2.0
MyDerivedObject {
property bool test: false
-
+
Component.onCompleted: {
test = intProperty()
}
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.2.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.2.qml
index 2ac4807ec5..4a715b7a4f 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVar.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.2.qml
@@ -15,7 +15,7 @@ Item {
if (wheelCount != 8) return;
// not bindable, but wheelCount will update because truck itself changed.
- truck = new vehicle(12);
+ truck = new vehicle(12);
if (wheelCount != 12) return;
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.2.qml b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.2.qml
index 14d4f9fd27..4693202240 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.2.qml
@@ -18,7 +18,7 @@ Item {
if (varProperty.a != 10) return;
test = true;
- }
+ }
}
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.3.qml b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.3.qml
index d5b449c938..5b0236505f 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.3.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.3.qml
@@ -16,7 +16,7 @@ Item {
test1 = true;
}
- // Run gc() from C++
+ // Run gc() from C++
function runTest2() {
if (object.dummy != 10) return;
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.qml b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.qml
index 7b99c4b6ad..935485bb81 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.qml
@@ -17,6 +17,6 @@ Item {
if (varProperty.a != 10) return;
test = true;
- }
+ }
}
diff --git a/tests/auto/qml/qqmlecmascript/data/scope.2.qml b/tests/auto/qml/qqmlecmascript/data/scope.2.qml
index fe1c4c7931..3a2d653e2c 100644
--- a/tests/auto/qml/qqmlecmascript/data/scope.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scope.2.qml
@@ -27,7 +27,7 @@ Item {
// id takes precedence over local, and root properties
- property int test1: a.value
+ property int test1: a.value
property alias test2: nested.test
// properties takes precedence over local, and root methods
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.1.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.1.qml
index ace473756e..2e15f4327b 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptConnect.1.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.1.qml
@@ -1,10 +1,10 @@
import Qt.test 1.0
import QtQuick 2.0
import "scriptConnect.1.js" as Script
-MyQmlObject {
+MyQmlObject {
property bool test: false
id: root
-
+
Component.onCompleted: root.argumentSignal.connect(Script.testFunction);
}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.2.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.2.qml
index cdf2d6ad98..9f91c5d1f7 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptConnect.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.2.qml
@@ -2,11 +2,11 @@ import Qt.test 1.0
import QtQuick 2.0
import "scriptConnect.2.js" as Script
-MyQmlObject {
+MyQmlObject {
property bool test: false
id: root
-
+
Component.onCompleted: {
var a = new Object;
a.b = 12;
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.3.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.3.qml
index b0e40565c0..e41b1c1f23 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptConnect.3.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.3.qml
@@ -1,11 +1,11 @@
import Qt.test 1.0
import QtQuick 2.0
-MyQmlObject {
+MyQmlObject {
property bool test: false
id: root
-
+
function testFunction() {
test = true;
}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.4.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.4.qml
index ef5331c94a..05155bf11d 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptConnect.4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.4.qml
@@ -1,7 +1,7 @@
import Qt.test 1.0
import QtQuick 2.0
-MyQmlObject {
+MyQmlObject {
property bool test: false
id: root
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.5.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.5.qml
index 8dcacbcbb7..16b085e109 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptConnect.5.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.5.qml
@@ -1,7 +1,7 @@
import Qt.test 1.0
import QtQuick 2.0
-MyQmlObject {
+MyQmlObject {
property bool test: false
id: root
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.6.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.6.qml
index 06b6f0fa62..0a3510fb9d 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptConnect.6.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.6.qml
@@ -2,12 +2,12 @@ import Qt.test 1.0
import QtQuick 2.0
import "scriptConnect.6.js" as Script
-MyQmlObject {
+MyQmlObject {
property int test: 0
id: root
- Component.onCompleted: {
+ Component.onCompleted: {
root.argumentSignal.connect(Script.testFunction);
root.argumentSignal.connect(Script.testFunction);
}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.1.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.1.qml
index e546ee44d8..7057437c33 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.1.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.1.qml
@@ -2,11 +2,11 @@ import Qt.test 1.0
import QtQuick 2.0
import "scriptDisconnect.1.js" as Script
-MyQmlObject {
+MyQmlObject {
property int test: 0
id: root
-
+
Component.onCompleted: root.argumentSignal.connect(Script.testFunction);
onBasicSignal: root.argumentSignal.disconnect(Script.testFunction);
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.2.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.2.qml
index e70cd8b900..70a9243835 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.2.qml
@@ -2,11 +2,11 @@ import Qt.test 1.0
import QtQuick 2.0
import "scriptDisconnect.1.js" as Script
-MyQmlObject {
+MyQmlObject {
property int test: 0
id: root
-
+
Component.onCompleted: root.argumentSignal.connect(root, Script.testFunction);
onBasicSignal: root.argumentSignal.disconnect(root, Script.testFunction);
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.3.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.3.qml
index 6f47776ea5..bb9abbd2c4 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.3.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.3.qml
@@ -2,11 +2,11 @@ import Qt.test 1.0
import QtQuick 2.0
import "scriptDisconnect.1.js" as Script
-MyQmlObject {
+MyQmlObject {
property int test: 0
id: root
-
+
Component.onCompleted: root.argumentSignal.connect(root, Script.testFunction);
onBasicSignal: root.argumentSignal.disconnect(Script.testFunction);
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.4.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.4.qml
index b3887545fb..d289d17eeb 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.4.qml
@@ -2,11 +2,11 @@ import Qt.test 1.0
import QtQuick 2.0
import "scriptDisconnect.1.js" as Script
-MyQmlObject {
+MyQmlObject {
property int test: 0
id: root
-
+
Component.onCompleted: root.argumentSignal.connect(Script.testFunction);
onBasicSignal: root.argumentSignal.disconnect(Script.otherFunction);
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptErrors.js b/tests/auto/qml/qqmlecmascript/data/scriptErrors.js
index d22f623edb..4f16ef4e82 100644
--- a/tests/auto/qml/qqmlecmascript/data/scriptErrors.js
+++ b/tests/auto/qml/qqmlecmascript/data/scriptErrors.js
@@ -1,4 +1,4 @@
// Comment
a = 10
-function getValue() { a = 10; return 0; }
+function getValue() { a = 10; return 0; }
diff --git a/tests/auto/qml/qqmlecmascript/data/selfDeletingBinding.2.qml b/tests/auto/qml/qqmlecmascript/data/selfDeletingBinding.2.qml
index 58cf8051f0..d1bddb435c 100644
--- a/tests/auto/qml/qqmlecmascript/data/selfDeletingBinding.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/selfDeletingBinding.2.qml
@@ -11,7 +11,7 @@ MyQmlContainer {
MyQmlObject {
// Will trigger deletion on binding assignment, but after component creation
- deleteOnSet: if (triggerDelete) 1; else 0;
+ deleteOnSet: if (triggerDelete) 1; else 0;
}
]
}
diff --git a/tests/auto/qml/qqmlecmascript/data/signalAssignment.1.qml b/tests/auto/qml/qqmlecmascript/data/signalAssignment.1.qml
index fbd09142f7..fbafd843da 100644
--- a/tests/auto/qml/qqmlecmascript/data/signalAssignment.1.qml
+++ b/tests/auto/qml/qqmlecmascript/data/signalAssignment.1.qml
@@ -1,5 +1,5 @@
import Qt.test 1.0
-MyQmlObject {
- onBasicSignal: setString('pass')
+MyQmlObject {
+ onBasicSignal: setString('pass')
}
diff --git a/tests/auto/qml/qqmlecmascript/data/signalAssignment.2.qml b/tests/auto/qml/qqmlecmascript/data/signalAssignment.2.qml
index 6467c42bb9..8406566848 100644
--- a/tests/auto/qml/qqmlecmascript/data/signalAssignment.2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/signalAssignment.2.qml
@@ -1,5 +1,5 @@
import Qt.test 1.0
-MyQmlObject {
+MyQmlObject {
onArgumentSignal: setString('pass ' + a + ' ' + b + ' ' + c + ' ' + d + ' ' + e)
}
diff --git a/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml b/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml
index 7e85312692..cd68fb9b82 100644
--- a/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml
+++ b/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml
@@ -91,4 +91,15 @@ QtObject {
testObjectWithAliasHandler.count++
return testObjectWithAliasHandler.testSuccess
}
+
+ signal signalWithClosureArgument(var f)
+ onSignalWithClosureArgument: f()
+
+ function testSignalWithClosureArgument() {
+ var testSuccess = false
+ signalWithClosureArgument(function() {
+ testSuccess = true
+ })
+ return testSuccess
+ }
}
diff --git a/tests/auto/qml/qqmlecmascript/data/signalTriggeredBindings.qml b/tests/auto/qml/qqmlecmascript/data/signalTriggeredBindings.qml
index d98d7e9c81..1def3d0307 100644
--- a/tests/auto/qml/qqmlecmascript/data/signalTriggeredBindings.qml
+++ b/tests/auto/qml/qqmlecmascript/data/signalTriggeredBindings.qml
@@ -11,7 +11,7 @@ MyQmlObject {
property real test1: base
property real test2: Math.max(0, base)
}
-
+
// Signal with no args
onBasicSignal: base = 200
// Signal with args
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 2aef1d644d..928d594f62 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -152,7 +152,7 @@ public:
}
QObject *objectProperty() const { return m_object; }
- void setObjectProperty(QObject *obj) {
+ void setObjectProperty(QObject *obj) {
if (obj == m_object)
return;
m_object = obj;
@@ -206,7 +206,7 @@ public:
int intProperty() const { return m_intProperty; }
void setIntProperty(int i) { m_intProperty = i; emit intChanged(); }
-
+
Q_INVOKABLE MyEnum2 getEnumValue() const { return EnumValue4; }
MyEnum enumPropertyValue;
@@ -803,7 +803,7 @@ public:
Q_INVOKABLE void method_QObject(QObject *a) { invoke(13); m_actuals << qVariantFromValue(a); }
Q_INVOKABLE void method_QScriptValue(QJSValue a) { invoke(14); m_actuals << qVariantFromValue(a); }
Q_INVOKABLE void method_intQScriptValue(int a, QJSValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); }
-
+
Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; }
Q_INVOKABLE void method_overload(QString a) { invoke(18); m_actuals << a; }
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 3f412ee6d4..a39564bd19 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -55,6 +55,7 @@
#include "../../shared/util.h"
#include <private/qv4functionobject_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4alloca_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -62,12 +63,6 @@
#define NO_INLINE __attribute__((noinline))
#endif
-#if defined(Q_OS_WIN)
-#include <malloc.h>
-#else
-#include <alloca.h>
-#endif
-
/*
This test covers evaluation of ECMAScript expressions and bindings from within
QML. This does not include static QML language issues.
@@ -174,6 +169,7 @@ private slots:
void singletonTypeResolution();
void importScripts_data();
void importScripts();
+ void importCreationContext();
void scarceResources();
void scarceResources_data();
void scarceResources_other();
@@ -385,7 +381,7 @@ void tst_qqmlecmascript::assignBasicTypes()
QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
QCOMPARE(object->boolProperty(), true);
QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
- QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
+ QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2f));
QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
delete object;
}
@@ -414,7 +410,7 @@ void tst_qqmlecmascript::assignBasicTypes()
QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
QCOMPARE(object->boolProperty(), true);
QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
- QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
+ QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2f));
QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
delete object;
}
@@ -771,7 +767,7 @@ void tst_qqmlecmascript::contextPropertiesTriggerReeval()
context.setContextProperty("testObj", &object1);
context.setContextProperty("testObj2", object3);
- {
+ {
MyExpression expr(&context, "testProp + 1");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant(2));
@@ -781,7 +777,7 @@ void tst_qqmlecmascript::contextPropertiesTriggerReeval()
QCOMPARE(expr.evaluate(), QVariant(3));
}
- {
+ {
MyExpression expr(&context, "testProp + testProp + testProp");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant(6));
@@ -791,7 +787,7 @@ void tst_qqmlecmascript::contextPropertiesTriggerReeval()
QCOMPARE(expr.evaluate(), QVariant(12));
}
- {
+ {
MyExpression expr(&context, "testObj.stringProperty");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant("Hello"));
@@ -801,7 +797,7 @@ void tst_qqmlecmascript::contextPropertiesTriggerReeval()
QCOMPARE(expr.evaluate(), QVariant("World"));
}
- {
+ {
MyExpression expr(&context, "testObj.stringProperty /**/");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant("World"));
@@ -811,7 +807,7 @@ void tst_qqmlecmascript::contextPropertiesTriggerReeval()
QCOMPARE(expr.evaluate(), QVariant("Hello"));
}
- {
+ {
MyExpression expr(&context, "testObj2");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
@@ -832,7 +828,7 @@ void tst_qqmlecmascript::objectPropertiesTriggerReeval()
object2.setStringProperty(QLatin1String("Dog"));
object3.setStringProperty(QLatin1String("Cat"));
- {
+ {
MyExpression expr(&context, "testObj.stringProperty");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant("Hello"));
@@ -842,7 +838,7 @@ void tst_qqmlecmascript::objectPropertiesTriggerReeval()
QCOMPARE(expr.evaluate(), QVariant("World"));
}
- {
+ {
MyExpression expr(&context, "testObj.objectProperty.stringProperty");
QCOMPARE(expr.changed, false);
QCOMPARE(expr.evaluate(), QVariant());
@@ -877,7 +873,7 @@ void tst_qqmlecmascript::objectPropertiesTriggerReeval()
void tst_qqmlecmascript::deferredProperties()
{
QQmlComponent component(&engine, testFileUrl("deferredProperties.qml"));
- MyDeferredObject *object =
+ MyDeferredObject *object =
qobject_cast<MyDeferredObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->value(), 0);
@@ -886,7 +882,7 @@ void tst_qqmlecmascript::deferredProperties()
qmlExecuteDeferred(object);
QCOMPARE(object->value(), 10);
QVERIFY(object->objectProperty() != 0);
- MyQmlObject *qmlObject =
+ MyQmlObject *qmlObject =
qobject_cast<MyQmlObject *>(object->objectProperty());
QVERIFY(qmlObject != 0);
QCOMPARE(qmlObject->value(), 10);
@@ -900,7 +896,7 @@ void tst_qqmlecmascript::deferredProperties()
void tst_qqmlecmascript::deferredPropertiesErrors()
{
QQmlComponent component(&engine, testFileUrl("deferredPropertiesErrors.qml"));
- MyDeferredObject *object =
+ MyDeferredObject *object =
qobject_cast<MyDeferredObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->value(), 0);
@@ -962,7 +958,7 @@ void tst_qqmlecmascript::deferredPropertiesInDestruction()
void tst_qqmlecmascript::extensionObjects()
{
QQmlComponent component(&engine, testFileUrl("extensionObjects.qml"));
- MyExtendedObject *object =
+ MyExtendedObject *object =
qobject_cast<MyExtendedObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->baseProperty(), 13);
@@ -1154,7 +1150,7 @@ void tst_qqmlecmascript::valueTypeFunctions()
delete obj;
}
-/*
+/*
Tests that writing a constant to a property with a binding on it disables the
binding.
*/
@@ -1237,7 +1233,7 @@ the original binding to be disabled.
*/
void tst_qqmlecmascript::outerBindingOverridesInnerBinding()
{
- QQmlComponent component(&engine,
+ QQmlComponent component(&engine,
testFileUrl("outerBindingOverridesInnerBinding.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(object != 0);
@@ -1260,7 +1256,7 @@ void tst_qqmlecmascript::outerBindingOverridesInnerBinding()
}
/*
-Access a non-existent attached object.
+Access a non-existent attached object.
Tests for a regression where this used to crash.
*/
@@ -1917,7 +1913,7 @@ void tst_qqmlecmascript::propertyAssignmentErrors()
delete object;
}
-
+
/*
Test bindings still work when the reeval is triggered from within
a signal script.
@@ -2264,7 +2260,7 @@ void tst_qqmlecmascript::regExpBug()
static inline bool evaluate_error(QV8Engine *engine, const QV4::ValueRef o, const char *source)
{
- QString functionSource = QLatin1String("(function(object) { return ") +
+ QString functionSource = QLatin1String("(function(object) { return ") +
QLatin1String(source) + QLatin1String(" })");
QV4::Script program(QV8Engine::getV4(engine)->rootContext, functionSource);
@@ -2292,7 +2288,7 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::ValueRef o, cons
static inline bool evaluate_value(QV8Engine *engine, const QV4::ValueRef o,
const char *source, const QV4::ValueRef result)
{
- QString functionSource = QLatin1String("(function(object) { return ") +
+ QString functionSource = QLatin1String("(function(object) { return ") +
QLatin1String(source) + QLatin1String(" })");
QV4::Script program(QV8Engine::getV4(engine)->rootContext, functionSource);
@@ -2324,7 +2320,7 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::ValueRef o,
static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::ValueRef o,
const char *source)
{
- QString functionSource = QLatin1String("(function(object) { return ") +
+ QString functionSource = QLatin1String("(function(object) { return ") +
QLatin1String(source) + QLatin1String(" })");
QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->currentContext();
@@ -2363,7 +2359,7 @@ void tst_qqmlecmascript::callQtInvokables()
QQmlEngine qmlengine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&qmlengine);
-
+
QV8Engine *engine = ep->v8engine();
QV4::Scope scope(QV8Engine::getV4(engine));
@@ -3027,7 +3023,7 @@ void tst_qqmlecmascript::attachedPropertyScope()
QObject *object = component.create();
QVERIFY(object != 0);
- MyQmlAttachedObject *attached =
+ MyQmlAttachedObject *attached =
qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
QVERIFY(attached != 0);
@@ -3242,7 +3238,7 @@ void tst_qqmlecmascript::ownership()
QVERIFY(own.object != 0);
QObject *object = component.create(context);
-
+
engine.collectGarbage();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
@@ -3278,7 +3274,7 @@ public:
QPointer<QObject> value;
};
-// QTBUG-15695.
+// QTBUG-15695.
// Test setObjectOwnership(CppOwnership) works even when there is no QQmlData
void tst_qqmlecmascript::cppOwnershipReturnValue()
{
@@ -3911,7 +3907,7 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
QV4::Scope scope(v4);
QV4::ScopedArrayObject scripts(scope, ctxt->importedScripts);
QV4::ScopedValue qml(scope);
- for (quint32 i = 0; i < scripts->arrayLength(); ++i) {
+ for (quint32 i = 0; i < scripts->getLength(); ++i) {
QQmlContextData *scriptContext, *newContext;
qml = scripts->getIndexed(i);
@@ -4216,6 +4212,20 @@ void tst_qqmlecmascript::importScripts()
engine.setImportPathList(importPathList);
}
+void tst_qqmlecmascript::importCreationContext()
+{
+ QQmlComponent component(&engine, testFileUrl("jsimport/creationContext.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ bool success = object->property("success").toBool();
+ if (!success) {
+ QSignalSpy readySpy(object.data(), SIGNAL(loaded()));
+ readySpy.wait();
+ }
+ success = object->property("success").toBool();
+ QVERIFY(success);
+}
+
void tst_qqmlecmascript::scarceResources_other()
{
/* These tests require knowledge of state, since we test values after
@@ -5628,7 +5638,7 @@ void tst_qqmlecmascript::assignSequenceTypes()
}
}
-// Test that assigning a null object works
+// Test that assigning a null object works
// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
void tst_qqmlecmascript::nullObjectBinding()
{
@@ -6070,6 +6080,9 @@ void tst_qqmlecmascript::signalHandlers()
QMetaObject::invokeMethod(o, "testAliasSignalHandler", Q_RETURN_ARG(QVariant, result));
QCOMPARE(result.toBool(), true);
+ QMetaObject::invokeMethod(o, "testSignalWithClosureArgument", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+
delete o;
}
@@ -6276,7 +6289,7 @@ void tst_qqmlecmascript::aliasBindingsAssignCorrectly()
// Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
void tst_qqmlecmascript::aliasBindingsOverrideTarget()
{
- {
+ {
QQmlComponent component(&engine, testFileUrl("aliasBindingsOverrideTarget.qml"));
QObject *o = component.create();
QVERIFY(o != 0);
diff --git a/tests/auto/qml/qqmlengine/qqmlengine.pro b/tests/auto/qml/qqmlengine/qqmlengine.pro
index fd8c463742..e84512fae3 100644
--- a/tests/auto/qml/qqmlengine/qqmlengine.pro
+++ b/tests/auto/qml/qqmlengine/qqmlengine.pro
@@ -4,7 +4,7 @@ macx:CONFIG -= app_bundle
include (../../shared/util.pri)
-SOURCES += tst_qqmlengine.cpp
+SOURCES += tst_qqmlengine.cpp
QT += core-private gui-private qml-private network testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
index 44fbb0a982..c3d8a1502c 100644
--- a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
+++ b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
@@ -203,7 +203,7 @@ void tst_qqmlerror::debug()
error.setLine(92);
error.setColumn(13);
- QTest::ignoreMessage(QtWarningMsg, "http://www.qt-project.org/main.qml:92:13: An Error ");
+ QTest::ignoreMessage(QtWarningMsg, "http://www.qt-project.org/main.qml:92:13: An Error");
qWarning() << error;
}
diff --git a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
index 793da64734..2d7e0a8594 100644
--- a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
+++ b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
@@ -63,7 +63,7 @@ void tst_qqmlglobal::initTestCase()
void tst_qqmlglobal::colorProviderWarning()
{
- const QLatin1String expected("Warning: QQml_colorProvider: no color provider has been set! ");
+ const QLatin1String expected("Warning: QQml_colorProvider: no color provider has been set!");
QTest::ignoreMessage(QtWarningMsg, expected.data());
QQml_colorProvider();
}
diff --git a/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp b/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
index 0cd4360e67..0c8424aaba 100644
--- a/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
+++ b/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
@@ -486,7 +486,7 @@ void tst_qqmlinstruction::dump()
}
QStringList expect;
- expect
+ expect
<< "Index\tOperation\t\tData1\tData2\tData3\tComments"
<< "-------------------------------------------------------------------------------"
<< "0\t\tINIT\t\t\t0\t3\t-1\t-1"
@@ -500,7 +500,7 @@ void tst_qqmlinstruction::dump()
<< "8\t\tSTORE_INTEGER\t\t5\t9"
<< "9\t\tSTORE_BOOL\t\t6\ttrue"
<< "10\t\tSTORE_STRING\t\t7\t1\t\t\"Test String\""
- << "11\t\tSTORE_URL\t\t8\t0\t\tQUrl(\"http://www.qt-project.org\") "
+ << "11\t\tSTORE_URL\t\t8\t0\t\tQUrl(\"http://www.qt-project.org\")"
<< "12\t\tSTORE_COLOR\t\t9\t\t\t\"ff00ff00\""
<< "13\t\tSTORE_DATE\t\t10\t9"
<< "14\t\tSTORE_TIME\t\t11"
diff --git a/tests/auto/qml/qqmllanguage/data/NestedAlias.qml b/tests/auto/qml/qqmllanguage/data/NestedAlias.qml
index 7d49b0ac98..3606836e96 100644
--- a/tests/auto/qml/qqmllanguage/data/NestedAlias.qml
+++ b/tests/auto/qml/qqmllanguage/data/NestedAlias.qml
@@ -7,8 +7,8 @@ QtObject {
property alias a: object2.a
o1: QtObject { id: object1 }
- o2: QtObject {
- id: object2
+ o2: QtObject {
+ id: object2
property int a: 1923
}
}
diff --git a/tests/auto/qml/qqmllanguage/data/OnCompletedType.qml b/tests/auto/qml/qqmllanguage/data/OnCompletedType.qml
index 947f14811f..6b589fb612 100644
--- a/tests/auto/qml/qqmllanguage/data/OnCompletedType.qml
+++ b/tests/auto/qml/qqmllanguage/data/OnCompletedType.qml
@@ -3,6 +3,6 @@ import QtQuick 2.0
MyQmlObject {
property int a: Math.max(10, 9)
- property int b: 11
+ property int b: 11
Component.onCompleted: console.log("Completed " + a + " " + b);
}
diff --git a/tests/auto/qml/qqmllanguage/data/OnDestructionType.qml b/tests/auto/qml/qqmllanguage/data/OnDestructionType.qml
index 11fb9d9578..a172d94a9e 100644
--- a/tests/auto/qml/qqmllanguage/data/OnDestructionType.qml
+++ b/tests/auto/qml/qqmllanguage/data/OnDestructionType.qml
@@ -3,6 +3,6 @@ import QtQuick 2.0
MyQmlObject {
property int a: Math.max(10, 9)
- property int b: 11
+ property int b: 11
Component.onDestruction: console.log("Destruction " + a + " " + b);
}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.4.qml b/tests/auto/qml/qqmllanguage/data/alias.4.qml
index bd6a769367..da6c6e7898 100644
--- a/tests/auto/qml/qqmllanguage/data/alias.4.qml
+++ b/tests/auto/qml/qqmllanguage/data/alias.4.qml
@@ -1,6 +1,6 @@
import Test 1.0
Alias2 {
- enumAlias: MyTypeObject.EnumVal2
+ enumAlias: MyTypeObject.EnumVal2
}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.5.qml b/tests/auto/qml/qqmllanguage/data/alias.5.qml
index cee2a88cf7..ccd47658e0 100644
--- a/tests/auto/qml/qqmllanguage/data/alias.5.qml
+++ b/tests/auto/qml/qqmllanguage/data/alias.5.qml
@@ -4,7 +4,7 @@ import Test 1.0
QtObject {
property alias otherAlias: otherObject
- property variant other
+ property variant other
other: MyQmlObject {
id: otherObject
value: 10
diff --git a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
index 4d54bc83c1..c91cf581b3 100644
--- a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
+++ b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
@@ -15,7 +15,7 @@ MyTypeObject {
floatProperty: 8.5
colorProperty: "red"
dateProperty: "1982-11-25"
- timeProperty: "11:11:32"
+ timeProperty: "11:11:32"
dateTimeProperty: "2009-05-12T13:22:01"
pointProperty: "99,13"
pointFProperty: "-10.1,12.3"
diff --git a/tests/auto/qml/qqmllanguage/data/defaultPropertyListOrder.qml b/tests/auto/qml/qqmllanguage/data/defaultPropertyListOrder.qml
index 31d17fd55f..fc878170cf 100644
--- a/tests/auto/qml/qqmllanguage/data/defaultPropertyListOrder.qml
+++ b/tests/auto/qml/qqmllanguage/data/defaultPropertyListOrder.qml
@@ -13,10 +13,10 @@ MyContainer {
children: [
QtObject {
property int index: 2
- },
+ },
QtObject {
property int index: 3
- }
+ }
]
QtObject {
diff --git a/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.2.qml b/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.2.qml
index 6f822ba157..319e1f5bc5 100644
--- a/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.2.qml
+++ b/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.2.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.0
import QtQuick 2.0 as Qt47
Qt.QtObject {
diff --git a/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.qml b/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.qml
index 5d072b160a..d4c77f1432 100644
--- a/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.qml
+++ b/tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.qml
@@ -8,6 +8,6 @@ QtObject {
objectProperty2: QtObject {}
property MyComponent myComponentProperty
- property MyComponent myComponentProperty2
+ property MyComponent myComponentProperty2
myComponentProperty2: MyComponent {}
}
diff --git a/tests/auto/qml/qqmllanguage/data/interfaceQList.qml b/tests/auto/qml/qqmllanguage/data/interfaceQList.qml
index c87dfae785..2e968e4fea 100644
--- a/tests/auto/qml/qqmllanguage/data/interfaceQList.qml
+++ b/tests/auto/qml/qqmllanguage/data/interfaceQList.qml
@@ -1,6 +1,6 @@
import Test 1.0
MyContainer {
- qlistInterfaces: [
+ qlistInterfaces: [
MyQmlObject {},
MyQmlObject {}
]
diff --git a/tests/auto/qml/qqmllanguage/data/invalidAttachedProperty.11.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidAttachedProperty.11.errors.txt
index fee5050743..d5e26cd48f 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidAttachedProperty.11.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidAttachedProperty.11.errors.txt
@@ -1 +1 @@
-5:15:Not an attached property name
+5:15:Expected type name
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.qml b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.qml
index fa46b8242a..d61dbd76d0 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.qml
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.0
QtObject {
property variant o;
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.qml b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.qml
index 3e516738d6..23f6c6353b 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.qml
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.2.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.0
QtObject {
property int o;
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.7.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.7.errors.txt
index 4a7e3830a8..0f42a4b39d 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.7.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.7.errors.txt
@@ -1 +1 @@
-4:-1:Cannot set properties on nullGrouped as it is null
+4:5:Cannot set properties on nullGrouped as it is null
diff --git a/tests/auto/qml/qqmllanguage/data/nonexistantProperty.3.qml b/tests/auto/qml/qqmllanguage/data/nonexistantProperty.3.qml
index 5b08608862..b1610f7b4f 100644
--- a/tests/auto/qml/qqmllanguage/data/nonexistantProperty.3.qml
+++ b/tests/auto/qml/qqmllanguage/data/nonexistantProperty.3.qml
@@ -1,4 +1,4 @@
import Test 1.0
-MyQmlObject {
- something: 1 + 1
+MyQmlObject {
+ something: 1 + 1
}
diff --git a/tests/auto/qml/qqmllanguage/data/nullDotProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/nullDotProperty.errors.txt
index 07a40949cd..581d34e0c3 100644
--- a/tests/auto/qml/qqmllanguage/data/nullDotProperty.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/nullDotProperty.errors.txt
@@ -1 +1 @@
-3:-1:Cannot set properties on obj as it is null
+3:5:Cannot set properties on obj as it is null
diff --git a/tests/auto/qml/qqmllanguage/data/onCompleted.qml b/tests/auto/qml/qqmllanguage/data/onCompleted.qml
index 89e6777f8a..6de38d7aab 100644
--- a/tests/auto/qml/qqmllanguage/data/onCompleted.qml
+++ b/tests/auto/qml/qqmllanguage/data/onCompleted.qml
@@ -10,7 +10,7 @@ MyTypeObject {
objectProperty: OnCompletedType {
qmlobjectProperty: MyQmlObject {
id: nestedObject
- property int b: 10
+ property int b: 10
Component.onCompleted: console.log("Completed " + a + " " + nestedObject.b)
}
}
diff --git a/tests/auto/qml/qqmllanguage/data/onDestruction.qml b/tests/auto/qml/qqmllanguage/data/onDestruction.qml
index 7d6da260b4..4eb5771943 100644
--- a/tests/auto/qml/qqmllanguage/data/onDestruction.qml
+++ b/tests/auto/qml/qqmllanguage/data/onDestruction.qml
@@ -10,7 +10,7 @@ MyTypeObject {
objectProperty: OnDestructionType {
qmlobjectProperty: MyQmlObject {
id: nestedObject
- property int b: 10
+ property int b: 10
Component.onDestruction: console.log("Destruction " + a + " " + nestedObject.b)
}
}
diff --git a/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt b/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt
index d857a0440e..b8c34042be 100644
--- a/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt
@@ -1 +1 @@
-3:5:Invalid property assignment: "readOnlyString" is a read-only property
+3:21:Invalid property assignment: "readOnlyString" is a read-only property
diff --git a/tests/auto/qml/qqmllanguage/data/scriptString.2.errors.txt b/tests/auto/qml/qqmllanguage/data/scriptString.2.errors.txt
index f8a776f9a0..0197f30142 100644
--- a/tests/auto/qml/qqmllanguage/data/scriptString.2.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/scriptString.2.errors.txt
@@ -1 +1 @@
-4:40:Cannot assign multiple values to a script property
+4:23:Cannot assign multiple values to a script property
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 4a4ab3b81a..98a803a594 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -126,6 +126,26 @@ QByteArray CustomBindingParser::compile(const QList<QQmlCustomParserProperty> &p
return result;
}
+QByteArray CustomBindingParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+{
+ QByteArray result;
+ QDataStream ds(&result, QIODevice::WriteOnly);
+
+ ds << bindings.count();
+ for (int i = 0; i < bindings.count(); ++i) {
+ const QV4::CompiledData::Binding *binding = bindings.at(i);
+ ds << qmlUnit->header.stringAt(binding->propertyNameIndex);
+
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
+ int bindingId = bindingIdentifier(binding);
+ ds << bindingId;
+
+ ds << binding->location.line;
+ }
+
+ return result;
+}
+
void CustomBindingParser::setCustomData(QObject *object, const QByteArray &data)
{
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index a968d9a25a..0416258075 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -59,7 +59,7 @@
QVariant myCustomVariantTypeConverter(const QString &data);
-class MyInterface
+class MyInterface
{
public:
MyInterface() : id(913) {}
@@ -719,6 +719,7 @@ class MyCustomParserTypeParser : public QQmlCustomParser
{
public:
QByteArray compile(const QList<QQmlCustomParserProperty> &) { return QByteArray(); }
+ QByteArray compile(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) { return QByteArray(); }
void setCustomData(QObject *, const QByteArray &) {}
};
@@ -1090,6 +1091,7 @@ public:
class CustomBindingParser : public QQmlCustomParser
{
virtual QByteArray compile(const QList<QQmlCustomParserProperty> &properties);
+ virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
virtual void setCustomData(QObject *object, const QByteArray &data);
};
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 6a577ec91c..0a40e2cde2 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -487,11 +487,11 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false;
QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
- QTest::newRow("incorrectCase") << "incorrectCase.qml"
+ QTest::newRow("incorrectCase") << "incorrectCase.qml"
#if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
- << "incorrectCase.errors.insensitive.txt"
+ << "incorrectCase.errors.insensitive.txt"
#else
- << "incorrectCase.errors.sensitive.txt"
+ << "incorrectCase.errors.sensitive.txt"
#endif
<< false;
@@ -524,7 +524,7 @@ void tst_qqmllanguage::errors()
QQmlComponent component(&engine, testFileUrl(file));
- if(create) {
+ if (create) {
QObject *object = component.create();
QVERIFY(object == 0);
}
@@ -612,7 +612,7 @@ void tst_qqmllanguage::assignQmlComponent()
QCOMPARE(child->property("y"), QVariant(11));
}
-// Test literal assignment to all the basic types
+// Test literal assignment to all the basic types
void tst_qqmllanguage::assignBasicTypes()
{
QQmlComponent component(&engine, testFileUrl("assignBasicTypes.qml"));
@@ -1170,7 +1170,7 @@ void tst_qqmllanguage::idProperty()
MyContainer *object = qobject_cast<MyContainer *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->getChildren()->count(), 1);
- MyTypeObject *child =
+ MyTypeObject *child =
qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
QVERIFY(child != 0);
QCOMPARE(child->id(), QString("myObjectId"));
@@ -1361,12 +1361,12 @@ void tst_qqmllanguage::propertyValueSource()
QList<QObject *> valueSources;
QObjectList allChildren = object->findChildren<QObject*>();
foreach (QObject *child, allChildren) {
- if (qobject_cast<QQmlPropertyValueSource *>(child))
+ if (qobject_cast<QQmlPropertyValueSource *>(child))
valueSources.append(child);
}
QCOMPARE(valueSources.count(), 1);
- MyPropertyValueSource *valueSource =
+ MyPropertyValueSource *valueSource =
qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
QVERIFY(valueSource != 0);
QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
@@ -1382,12 +1382,12 @@ void tst_qqmllanguage::propertyValueSource()
QList<QObject *> valueSources;
QObjectList allChildren = object->findChildren<QObject*>();
foreach (QObject *child, allChildren) {
- if (qobject_cast<QQmlPropertyValueSource *>(child))
+ if (qobject_cast<QQmlPropertyValueSource *>(child))
valueSources.append(child);
}
QCOMPARE(valueSources.count(), 1);
- MyPropertyValueSource *valueSource =
+ MyPropertyValueSource *valueSource =
qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
QVERIFY(valueSource != 0);
QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
@@ -1510,7 +1510,7 @@ void tst_qqmllanguage::aliasProperties()
QVERIFY(object != 0);
// Read through alias
- MyQmlObject *v =
+ MyQmlObject *v =
qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
QVERIFY(v != 0);
QCOMPARE(v->value(), 10);
@@ -1519,7 +1519,7 @@ void tst_qqmllanguage::aliasProperties()
MyQmlObject *v2 = new MyQmlObject();
v2->setParent(object);
object->setProperty("aliasObject", qVariantFromValue(v2));
- MyQmlObject *v3 =
+ MyQmlObject *v3 =
qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
QVERIFY(v3 != 0);
QCOMPARE(v3, v2);
@@ -1592,7 +1592,7 @@ void tst_qqmllanguage::aliasProperties()
QCOMPARE(object->property("a").toInt(), 1923);
}
- // Ptr Alias Cleanup - check that aliases to ptr types return 0
+ // Ptr Alias Cleanup - check that aliases to ptr types return 0
// if the object aliased to is removed
{
QQmlComponent component(&engine, testFileUrl("alias.7.qml"));
@@ -1846,7 +1846,7 @@ void tst_qqmllanguage::scriptString()
}
}
-// Check that default property assignments are correctly spliced into explicit
+// Check that default property assignments are correctly spliced into explicit
// property assignments
void tst_qqmllanguage::defaultPropertyListOrder()
{
@@ -2993,7 +2993,7 @@ void tst_qqmllanguage::remoteLoadCrash()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; Text {}", QUrl("http://127.0.0.1:14448/remoteLoadCrash.qml"));
- while (component.isLoading())
+ while (component.isLoading())
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50);
QObject *o = component.create();
diff --git a/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp b/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
index d5e85f478d..143164841f 100644
--- a/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
+++ b/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
@@ -1725,11 +1725,11 @@ void tst_qqmllistcompositor::changeDebug()
void tst_qqmllistcompositor::groupDebug()
{
- QTest::ignoreMessage(QtDebugMsg, "Default ");
+ QTest::ignoreMessage(QtDebugMsg, "Default");
qDebug() << C::Default;
- QTest::ignoreMessage(QtDebugMsg, "Cache ");
+ QTest::ignoreMessage(QtDebugMsg, "Cache");
qDebug() << C::Cache;
- QTest::ignoreMessage(QtDebugMsg, "Group3 ");
+ QTest::ignoreMessage(QtDebugMsg, "Group3");
qDebug() << Selection;
}
diff --git a/tests/auto/qml/qqmllistmodel/data/multipleroles.qml b/tests/auto/qml/qqmllistmodel/data/multipleroles.qml
index 4a331e2b3e..cd4f1aca40 100644
--- a/tests/auto/qml/qqmllistmodel/data/multipleroles.qml
+++ b/tests/auto/qml/qqmllistmodel/data/multipleroles.qml
@@ -2,12 +2,12 @@ import QtQuick 2.0
ListView {
width: 100
height: 250
- delegate: Rectangle {
+ delegate: Rectangle {
width: 100
height: 50
- color: black ? "black": "white"
+ color: black ? "black": "white"
}
- model: ListModel {
+ model: ListModel {
objectName: "listModel"
ListElement {
black: false
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 4d4eb93149..bdc0646b8e 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -1232,6 +1232,7 @@ void tst_qqmllistmodel::datetime_data()
QTest::newRow("dt1") << "{append({'date':dt0});get(0).date=dt1;get(0).date}" << dt1;
QTest::newRow("dt2") << "{append({'date':dt0});set(0,{'date':dt1});get(0).date}" << dt1;
QTest::newRow("dt3") << "{append({'date':dt0});get(0).date=undefined;get(0).date}" << dt;
+ QTest::newRow("dt4") << "{append({'date':dt0});setProperty(0,'date',dt1);get(0).date}" << dt1;
}
void tst_qqmllistmodel::datetime()
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index d565ad557c..0eb38d92e6 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -117,6 +117,7 @@ private slots:
void stringLocaleCompare_data();
void stringLocaleCompare();
+ void localeAsCppProperty();
private:
void addPropertyData(const QString &l);
QVariant getProperty(QObject *obj, const QString &locale, const QString &property);
@@ -1223,6 +1224,41 @@ void tst_qqmllocale::stringLocaleCompare()
QCOMPARE(obj->property("comparison").toInt(), QString::localeAwareCompare(string1, string2));
}
+class Calendar : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale)
+public:
+ Calendar() {
+ }
+
+ QLocale locale() const {
+ return mLocale;
+ }
+
+ void setLocale(const QLocale &locale) {
+ mLocale = locale;
+ }
+private:
+ QLocale mLocale;
+};
+
+void tst_qqmllocale::localeAsCppProperty()
+{
+ QQmlComponent component(&engine);
+ qmlRegisterType<Calendar>("Test", 1, 0, "Calendar");
+ component.setData("import QtQml 2.2\nimport Test 1.0\nCalendar { locale: Qt.locale('en_GB'); property var testLocale }", QUrl());
+ QVERIFY(!component.isError());
+ QTRY_VERIFY(component.isReady());
+
+ Calendar *item = qobject_cast<Calendar*>(component.create());
+ QCOMPARE(item->property("locale").toLocale().name(), QLatin1String("en_GB"));
+
+ QVariant localeVariant(QLocale("nb_NO"));
+ item->setProperty("testLocale", localeVariant);
+ QCOMPARE(item->property("testLocale").toLocale().name(), QLatin1String("nb_NO"));
+}
+
class DateFormatter : public QObject
{
Q_OBJECT
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index b1f83fcd6c..b0c7c5e81a 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -329,11 +329,11 @@ void tst_QQmlMetaObject::method_data()
<< (QList<QByteArray>() << "int" << "bool" << "double")
<< (QList<QByteArray>() << "foo" << "bar" << "baz");
QTest::newRow("testSignal(variant foo, var bar)") << "signal.4.qml"
- << "testSignal(QVariant,QVariant)"
+ << "testSignal(QVariant,QJSValue)"
<< QMetaMethod::Signal
<< int(QMetaType::Void) << "void"
- << (QList<int>() << QMetaType::QVariant << QMetaType::QVariant)
- << (QList<QByteArray>() << "QVariant" << "QVariant")
+ << (QList<int>() << QMetaType::QVariant << qMetaTypeId<QJSValue>())
+ << (QList<QByteArray>() << "QVariant" << "QJSValue")
<< (QList<QByteArray>() << "foo" << "bar");
QTest::newRow("testSignal(color foo, date bar, url baz)") << "signal.5.qml"
<< "testSignal(QColor,QDateTime,QUrl)"
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index 90023222d3..2c57129657 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -139,7 +139,7 @@ void tst_qqmlmetatype::qmlParserStatusCast()
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->parserStatusCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>())->parserStatusCast(), -1);
-
+
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
int cast = QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->parserStatusCast();
QVERIFY(cast != -1);
@@ -159,7 +159,7 @@ void tst_qqmlmetatype::qmlPropertyValueSourceCast()
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueSourceCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->propertyValueSourceCast(), -1);
-
+
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()) != 0);
int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>())->propertyValueSourceCast();
QVERIFY(cast != -1);
@@ -179,7 +179,7 @@ void tst_qqmlmetatype::qmlPropertyValueInterceptorCast()
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>())->propertyValueInterceptorCast(), -1);
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()) != 0);
QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>())->propertyValueInterceptorCast(), -1);
-
+
QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()) != 0);
int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>())->propertyValueInterceptorCast();
QVERIFY(cast != -1);
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.2.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.2.qml
index 97732d35d8..b13b2004c2 100644
--- a/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.2.qml
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.2.qml
@@ -5,7 +5,7 @@ Item {
property bool test: false
property bool test2: false
- Bar {
+ Bar {
id: bar
}
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.qml
index f09c29b5a8..563c0b28e3 100644
--- a/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.qml
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsMixedQmlCppPlugin.qml
@@ -3,7 +3,7 @@ import QtQuick 2.0
Item {
property bool test: false
- Bar {
+ Bar {
id: bar
}
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index a6d9fb5601..15be1fdbc0 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -44,6 +44,11 @@
#include <QtQml/qqmlcomponent.h>
#include <QDebug>
+#if defined(Q_OS_MAC)
+// For _PC_CASE_SENSITIVE
+#include <unistd.h>
+#endif
+
#include "../../shared/testhttpserver.h"
#include "../../shared/util.h"
@@ -145,7 +150,7 @@ void tst_qqmlmoduleplugin::importsPlugin()
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("works.qml")));
foreach (QQmlError err, component.errors())
- qWarning() << err;
+ qWarning() << err;
VERIFY_ERRORS(0);
QObject *object = component.create();
QVERIFY(object != 0);
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index 62b64a3ef1..669ae7d5ea 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -123,21 +123,21 @@ void tst_QQmlPropertyMap::insert()
//inserting property names same with existing method(signal, slot, method) names is not allowed
//QQmlPropertyMap has an invokable keys() method
- QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"keys\" is not permitted, conflicts with internal symbols. ");
+ QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"keys\" is not permitted, conflicts with internal symbols.");
map.insert(QLatin1String("keys"), 1);
QVERIFY(map.keys().count() == 2);
QVERIFY(!map.contains(QLatin1String("keys")));
QVERIFY(map.value(QLatin1String("keys")).isNull());
//QQmlPropertyMap has a deleteLater() slot
- QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"deleteLater\" is not permitted, conflicts with internal symbols. ");
+ QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"deleteLater\" is not permitted, conflicts with internal symbols.");
map.insert(QLatin1String("deleteLater"), 1);
QVERIFY(map.keys().count() == 2);
QVERIFY(!map.contains(QLatin1String("deleteLater")));
QVERIFY(map.value(QLatin1String("deleteLater")).isNull());
//QQmlPropertyMap has an valueChanged() signal
- QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"valueChanged\" is not permitted, conflicts with internal symbols. ");
+ QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"valueChanged\" is not permitted, conflicts with internal symbols.");
map.insert(QLatin1String("valueChanged"), 1);
QVERIFY(map.keys().count() == 2);
QVERIFY(!map.contains(QLatin1String("valueChanged")));
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
index 86ac04317f..3b0c83c000 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
@@ -91,10 +91,10 @@ public:
m_rect(2, 3, 109, 102),
m_rectf(103.8, 99.2, 88.1, 77.6),
m_rectfrect(2.0, 3.0, 109.0, 102.0),
- m_vector2(32.88, 1.3),
- m_vector(23.88, 3.1, 4.3),
- m_vector4(54.2, 23.88, 3.1, 4.3),
- m_quaternion(4.3, 54.2, 23.88, 3.1),
+ m_vector2(32.88f, 1.3f),
+ m_vector(23.88f, 3.1f, 4.3f),
+ m_vector4(54.2f, 23.88f, 3.1f, 4.3f),
+ m_quaternion(4.3f, 54.2f, 23.88f, 3.1f),
m_matrix(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
{
m_font.setFamily("Arial");
diff --git a/tests/auto/qml/qqmlvaluetypes/data/conflicting.1.qml b/tests/auto/qml/qqmlvaluetypes/data/conflicting.1.qml
index 923922c55a..78d3bc0fbd 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/conflicting.1.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/conflicting.1.qml
@@ -10,7 +10,7 @@ Rectangle {
property int myPixelSize: 12
property int myPixelSize2: 24
-
+
Text {
id: other
font.pixelSize: 6
diff --git a/tests/auto/qml/qqmlvaluetypes/data/conflicting.2.qml b/tests/auto/qml/qqmlvaluetypes/data/conflicting.2.qml
index 9804af4df6..725ba50a45 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/conflicting.2.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/conflicting.2.qml
@@ -10,7 +10,7 @@ Rectangle {
property int myPixelSize: 12
property int myPixelSize2: 24
-
+
Text {
id: other
font.pixelSize: 6
diff --git a/tests/auto/qml/qqmlvaluetypes/data/conflicting.3.qml b/tests/auto/qml/qqmlvaluetypes/data/conflicting.3.qml
index b5bb7f8ccc..509fb39562 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/conflicting.3.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/conflicting.3.qml
@@ -10,7 +10,7 @@ Rectangle {
property int myPixelSize: 12
property int myPixelSize2: 24
-
+
Text {
id: other
font.pixelSize: 6
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index 3e5952f64d..b32afcb53a 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -95,10 +95,10 @@ public:
m_rect(2, 3, 109, 102),
m_rectf(103.8, 99.2, 88.1, 77.6),
m_rectfrect(2.0, 3.0, 109.0, 102.0),
- m_vector2(32.88, 1.3),
- m_vector(23.88, 3.1, 4.3),
- m_vector4(54.2, 23.88, 3.1, 4.3),
- m_quaternion(4.3, 54.2, 23.88, 3.1),
+ m_vector2(32.88f, 1.3f),
+ m_vector(23.88f, 3.1f, 4.3f),
+ m_vector4(54.2f, 23.88f, 3.1f, 4.3f),
+ m_quaternion(4.3f, 54.2f, 23.88f, 3.1f),
m_matrix(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
{
m_font.setFamily("Arial");
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 7c0507dce3..f109fb1fc0 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -468,7 +468,7 @@ void tst_qqmlvaluetypes::vector2d()
QCOMPARE((float)object->property("v_x").toDouble(), (float)32.88);
QCOMPARE((float)object->property("v_y").toDouble(), (float)1.3);
- QCOMPARE(object->property("copy"), QVariant(QVector2D(32.88, 1.3)));
+ QCOMPARE(object->property("copy"), QVariant(QVector2D(32.88f, 1.3f)));
delete object;
}
@@ -478,7 +478,7 @@ void tst_qqmlvaluetypes::vector2d()
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QCOMPARE(object->vector2(), QVector2D(-0.3, -12.9));
+ QCOMPARE(object->vector2(), QVector2D(-0.3f, -12.9f));
delete object;
}
@@ -520,7 +520,7 @@ void tst_qqmlvaluetypes::vector3d()
QCOMPARE((float)object->property("v_x").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_y").toDouble(), (float)3.1);
QCOMPARE((float)object->property("v_z").toDouble(), (float)4.3);
- QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88, 3.1, 4.3)));
+ QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88f, 3.1f, 4.3f)));
delete object;
}
@@ -530,7 +530,7 @@ void tst_qqmlvaluetypes::vector3d()
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QCOMPARE(object->vector(), QVector3D(-0.3, -12.9, 907.4));
+ QCOMPARE(object->vector(), QVector3D(-0.3f, -12.9f, 907.4f));
delete object;
}
@@ -574,7 +574,7 @@ void tst_qqmlvaluetypes::vector4d()
QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
QCOMPARE((float)object->property("v_w").toDouble(), (float)4.3);
- QCOMPARE(object->property("copy"), QVariant(QVector4D(54.2, 23.88, 3.1, 4.3)));
+ QCOMPARE(object->property("copy"), QVariant(QVector4D(54.2f, 23.88f, 3.1f, 4.3f)));
delete object;
}
@@ -584,7 +584,7 @@ void tst_qqmlvaluetypes::vector4d()
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QCOMPARE(object->vector4(), QVector4D(-0.3, -12.9, 907.4, 88.5));
+ QCOMPARE(object->vector4(), QVector4D(-0.3f, -12.9f, 907.4f, 88.5f));
delete object;
}
@@ -627,7 +627,7 @@ void tst_qqmlvaluetypes::quaternion()
QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
- QCOMPARE(object->property("copy"), QVariant(QQuaternion(4.3, 54.2, 23.88, 3.1)));
+ QCOMPARE(object->property("copy"), QVariant(QQuaternion(4.3f, 54.2f, 23.88f, 3.1f)));
delete object;
}
@@ -637,7 +637,7 @@ void tst_qqmlvaluetypes::quaternion()
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
- QCOMPARE(object->quaternion(), QQuaternion(88.5, -0.3, -12.9, 907.4));
+ QCOMPARE(object->quaternion(), QQuaternion(88.5f, -0.3f, -12.9f, 907.4f));
delete object;
}
@@ -804,7 +804,7 @@ void tst_qqmlvaluetypes::font()
// Test pixelSize and pointSize
{
QQmlComponent component(&engine, testFileUrl("font_write.3.qml"));
- QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
+ QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size.");
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
@@ -814,7 +814,7 @@ void tst_qqmlvaluetypes::font()
}
{
QQmlComponent component(&engine, testFileUrl("font_write.4.qml"));
- QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
+ QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size.");
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
@@ -1184,10 +1184,10 @@ void tst_qqmlvaluetypes::cppClasses()
CPP_TEST(QQmlSizeFValueType, QSizeF(-100.7, 18.2));
CPP_TEST(QQmlRectValueType, QRect(13, 39, 10928, 88));
CPP_TEST(QQmlRectFValueType, QRectF(88.2, -90.1, 103.2, 118));
- CPP_TEST(QQuickVector2DValueType, QVector2D(19.7, 1002));
- CPP_TEST(QQuickVector3DValueType, QVector3D(18.2, 19.7, 1002));
- CPP_TEST(QQuickVector4DValueType, QVector4D(18.2, 19.7, 1002, 54));
- CPP_TEST(QQuickQuaternionValueType, QQuaternion(18.2, 19.7, 1002, 54));
+ CPP_TEST(QQuickVector2DValueType, QVector2D(19.7f, 1002));
+ CPP_TEST(QQuickVector3DValueType, QVector3D(18.2f, 19.7f, 1002));
+ CPP_TEST(QQuickVector4DValueType, QVector4D(18.2f, 19.7f, 1002, 54));
+ CPP_TEST(QQuickQuaternionValueType, QQuaternion(18.2f, 19.7f, 1002, 54));
CPP_TEST(QQuickMatrix4x4ValueType,
QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
CPP_TEST(QQuickFontValueType, QFont("Helvetica"));
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
index d5bb84ddc0..7fcbc9367a 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
@@ -15,7 +15,7 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
- x.abort();
+ x.abort();
if (x.readyState == XMLHttpRequest.UNSENT)
readyState = true;
@@ -23,7 +23,7 @@ QtObject {
x.open("PUT", url);
x.setRequestHeader("Accept-Language", "en-US");
- x.abort();
+ x.abort();
x.open("GET", url);
x.setRequestHeader("Accept-Language", "en-US");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
index 4f58062a26..0a85c6b16f 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
@@ -15,7 +15,7 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
- x.abort();
+ x.abort();
if (x.readyState == XMLHttpRequest.UNSENT)
readyState = true;
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/element.qml b/tests/auto/qml/qqmlxmlhttprequest/data/element.qml
index 9b190f3a43..e0701d511a 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/element.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/element.qml
@@ -115,8 +115,8 @@ QtObject {
function checkXML(document)
{
- checkElement(document.documentElement,
- document.documentElement.childNodes[0],
+ checkElement(document.documentElement,
+ document.documentElement.childNodes[0],
document.documentElement.childNodes[1]);
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml b/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
index 580688b835..a9066093d4 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
@@ -20,12 +20,12 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
- try {
- x.getResponseHeader("Test-Header");
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- unsentException = true;
- }
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
if (x.readyState == XMLHttpRequest.UNSENT)
readyState = true;
@@ -36,25 +36,25 @@ QtObject {
if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
- try {
- x.getResponseHeader("Test-Header");
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- openedException = true;
- }
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
var headers = "connection: close\r\ncontent-type: text/html; charset=UTF-8\r\ntest-header: TestValue\r\nmultitest-header: TestValue, SecondTestValue\r\ncontent-length: 11";
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
- headersReceivedState = true;
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ headersReceivedState = true;
- headersReceivedHeader = (x.getAllResponseHeaders() == headers);
- } else if (x.readyState == XMLHttpRequest.DONE) {
- doneState = headersReceivedState && true;
+ headersReceivedHeader = (x.getAllResponseHeaders() == headers);
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ doneState = headersReceivedState && true;
- doneHeader = (x.getAllResponseHeaders() == headers);
+ doneHeader = (x.getAllResponseHeaders() == headers);
dataOK = (x.responseText == "QML Rocks!\n");
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
index 203967e539..0219d7b2fc 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
@@ -26,12 +26,12 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
- try {
- x.getResponseHeader("Test-Header");
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- unsentException = true;
- }
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
if (x.readyState == XMLHttpRequest.UNSENT)
readyState = true;
@@ -42,29 +42,29 @@ QtObject {
if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
- try {
- x.getResponseHeader("Test-Header");
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- openedException = true;
- }
+ try {
+ x.getResponseHeader("Test-Header");
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
- headersReceivedState = true;
-
- headersReceivedNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
- headersReceivedValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
- headersReceivedMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
- headersReceivedCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
- } else if (x.readyState == XMLHttpRequest.DONE) {
- doneState = headersReceivedState && true;
-
- doneNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
- doneValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
- doneMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
- doneCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ headersReceivedState = true;
+
+ headersReceivedNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
+ headersReceivedValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
+ headersReceivedMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ headersReceivedCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ doneState = headersReceivedState && true;
+
+ doneNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
+ doneValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
+ doneMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ doneCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
dataOK = (x.responseText == "QML Rocks!\n");
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/invalidMethodUsage.qml b/tests/auto/qml/qqmlxmlhttprequest/data/invalidMethodUsage.qml
index 5a4093b9f1..88207c19ca 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/invalidMethodUsage.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/invalidMethodUsage.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.0
QtObject {
property bool readyState: false
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/redirectError.qml b/tests/auto/qml/qqmlxmlhttprequest/data/redirectError.qml
index e5c7b74553..5b01caad39 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/redirectError.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/redirectError.qml
@@ -5,7 +5,7 @@ QtObject {
property bool dataOK: false
property bool done: false
-
+
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", url);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/redirectRecur.qml b/tests/auto/qml/qqmlxmlhttprequest/data/redirectRecur.qml
index 0894573ecc..cd6e1f99ad 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/redirectRecur.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/redirectRecur.qml
@@ -5,7 +5,7 @@ QtObject {
property bool dataOK: false
property bool done: false
-
+
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", url);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/redirects.qml b/tests/auto/qml/qqmlxmlhttprequest/data/redirects.qml
index 003d1954e9..c658feb5aa 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/redirects.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/redirects.qml
@@ -5,7 +5,7 @@ QtObject {
property bool dataOK: false
property bool done: false
-
+
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", url);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
index 4e0caa7171..65ce90853d 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
@@ -19,7 +19,7 @@ QtObject {
x.send();
try {
- x.send()
+ x.send()
} catch (e) {
if (e.code == DOMException.INVALID_STATE_ERR)
test = true;
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/status.qml b/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
index 5feac17711..22c45c099d 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
@@ -19,22 +19,22 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
- try {
- var a = x.status;
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- unsentException = true;
- }
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
x.open("GET", url);
x.setRequestHeader("Accept-Language", "en-US");
- try {
- var a = x.status;
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- openedException = true;
- }
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
// Test to the end
x.onreadystatechange = function() {
@@ -65,11 +65,11 @@ QtObject {
x.send()
- try {
- var a = x.status;
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- sentException = true;
- }
+ try {
+ var a = x.status;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ sentException = true;
+ }
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml b/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
index 3c74efc091..bf59a1e9f9 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
@@ -19,22 +19,22 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
- try {
- var a = x.statusText;
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- unsentException = true;
- }
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ unsentException = true;
+ }
x.open("GET", url);
x.setRequestHeader("Accept-Language", "en-US");
- try {
- var a = x.statusText;
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- openedException = true;
- }
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ openedException = true;
+ }
// Test to the end
x.onreadystatechange = function() {
@@ -65,11 +65,11 @@ QtObject {
x.send()
- try {
- var a = x.statusText;
- } catch (e) {
- if (e.code == DOMException.INVALID_STATE_ERR)
- sentException = true;
- }
+ try {
+ var a = x.statusText;
+ } catch (e) {
+ if (e.code == DOMException.INVALID_STATE_ERR)
+ sentException = true;
+ }
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 9c67e6e2e9..17becb3714 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -208,7 +208,7 @@ void tst_qqmlxmlhttprequest::instanceStateValues()
QCOMPARE(object->property("done").toInt(), 4);
}
-// Test calling constructor
+// Test calling constructor
void tst_qqmlxmlhttprequest::constructor()
{
QQmlComponent component(&engine, testFileUrl("constructor.qml"));
@@ -436,7 +436,7 @@ void tst_qqmlxmlhttprequest::setRequestHeader_sent()
component.completeCreate();
QCOMPARE(object->property("test").toBool(), true);
-
+
QTRY_VERIFY(object->property("dataOK").toBool() == true);
}
@@ -796,7 +796,7 @@ void tst_qqmlxmlhttprequest::statusText()
TestHTTPServer server(SERVER_PORT);
QVERIFY(server.isValid());
QVERIFY(server.wait(testFileUrl("status.expect"),
- replyUrl,
+ replyUrl,
testFileUrl("testdocument.html")));
QQmlComponent component(&engine, testFileUrl("statusText.qml"));
@@ -836,7 +836,7 @@ void tst_qqmlxmlhttprequest::responseText()
TestHTTPServer server(SERVER_PORT);
QVERIFY(server.isValid());
QVERIFY(server.wait(testFileUrl("status.expect"),
- replyUrl,
+ replyUrl,
bodyUrl));
QQmlComponent component(&engine, testFileUrl("responseText.qml"));
@@ -883,7 +883,7 @@ void tst_qqmlxmlhttprequest::nonUtf8()
QMetaObject::invokeMethod(object.data(), "startRequest");
QTRY_VERIFY(object->property("dataOK").toBool() == true);
-
+
QCOMPARE(object->property("responseText").toString(), responseText);
if (!xmlRootNodeValue.isEmpty()) {
@@ -980,10 +980,10 @@ void tst_qqmlxmlhttprequest::redirects()
object->setProperty("expectedText", "");
component.completeCreate();
- for (int ii = 0; ii < 60; ++ii) {
- if (object->property("done").toBool()) break;
- QTest::qWait(50);
- }
+ for (int ii = 0; ii < 60; ++ii) {
+ if (object->property("done").toBool()) break;
+ QTest::qWait(50);
+ }
QVERIFY(object->property("done").toBool() == true);
QCOMPARE(object->property("dataOK").toBool(), true);
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index 53df72d75f..73e8a283c7 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -137,8 +137,8 @@ void tst_qquickfolderlistmodel::basicProperties()
QCOMPARE(flm->property("showDotAndDotDot").toBool(), false);
QCOMPARE(flm->property("showOnlyReadable").toBool(), false);
QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("basic.qml"));
- QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String("dummy.qml"));
-
+ QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String("dummy.qml"));
+
flm->setProperty("folder",QUrl::fromLocalFile(""));
QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(""));
}
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index 1530ce83e2..a799fc4fc4 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -187,7 +187,7 @@ void tst_QQuickWorkerScript::messaging_sendJsObject()
waitForEchoMessage(worker);
QVariant result = qVariantFromValue(false);
- QVERIFY(QMetaObject::invokeMethod(worker, "compareLiteralResponse", Qt::DirectConnection,
+ QVERIFY(QMetaObject::invokeMethod(worker, "compareLiteralResponse", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, jsObject)));
QVERIFY(result.toBool());
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index da2b793b71..79ccdc9a4b 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed; // from qhash.cpp
QT_END_NAMESPACE
-using namespace QT_PREPEND_NAMESPACE(QQmlJS::V4IR);
+using namespace QT_PREPEND_NAMESPACE(QV4::IR);
void tst_v4misc::initTestCase()
{
diff --git a/tests/auto/quick/qquickaccessible/data/checkbuttons.qml b/tests/auto/quick/qquickaccessible/data/checkbuttons.qml
index 22cdad1377..8769c04095 100644
--- a/tests/auto/quick/qquickaccessible/data/checkbuttons.qml
+++ b/tests/auto/quick/qquickaccessible/data/checkbuttons.qml
@@ -6,6 +6,7 @@ Item {
// button, not checkable
Rectangle {
+ objectName: "button1"
y: 20
width: 100; height: 20
Accessible.role : Accessible.Button
@@ -13,34 +14,44 @@ Item {
// button, checkable, not checked
Rectangle {
+ objectName: "button2"
y: 40
width: 100; height: 20
Accessible.role : Accessible.Button
+ Accessible.checkable: checkable
+ Accessible.checked: checked
property bool checkable: true
property bool checked: false
}
// button, checkable, checked
Rectangle {
+ objectName: "button3"
y: 60
width: 100; height: 20
Accessible.role : Accessible.Button
+ Accessible.checkable: checkable
+ Accessible.checked: checked
property bool checkable: true
property bool checked: true
}
// check box, checked
Rectangle {
+ objectName: "checkbox1"
y: 80
width: 100; height: 20
Accessible.role : Accessible.CheckBox
+ Accessible.checked: checked
property bool checked: true
}
// check box, not checked
Rectangle {
+ objectName: "checkbox2"
y: 100
width: 100; height: 20
Accessible.role : Accessible.CheckBox
+ Accessible.checked: checked
property bool checked: false
}
}
diff --git a/tests/auto/quick/qquickaccessible/qquickaccessible.pro b/tests/auto/quick/qquickaccessible/qquickaccessible.pro
index 6fc6011229..99c3834147 100644
--- a/tests/auto/quick/qquickaccessible/qquickaccessible.pro
+++ b/tests/auto/quick/qquickaccessible/qquickaccessible.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qquickaccessible
-QT += qml-private network quick-private testlib gui-private
+QT += qml-private network quick-private testlib gui-private core-private
macx:CONFIG -= app_bundle
SOURCES += tst_qquickaccessible.cpp
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index 4bf568745b..54eb3509bd 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -44,6 +44,10 @@
#include "QtTest/qtestaccessible.h"
#include <QtGui/qaccessible.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformaccessibility.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
@@ -96,6 +100,12 @@ public:
tst_QQuickAccessible();
virtual ~tst_QQuickAccessible();
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
private slots:
void commonTests_data();
void commonTests();
@@ -116,6 +126,37 @@ tst_QQuickAccessible::~tst_QQuickAccessible()
}
+void tst_QQuickAccessible::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ QTestAccessibility::initialize();
+ QPlatformIntegration *pfIntegration = QGuiApplicationPrivate::platformIntegration();
+ pfIntegration->accessibility()->setActive(true);
+}
+
+void tst_QQuickAccessible::cleanupTestCase()
+{
+ QTestAccessibility::cleanup();
+}
+
+void tst_QQuickAccessible::init()
+{
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QQuickAccessible::cleanup()
+{
+ const EventList list = QTestAccessibility::events();
+ if (!list.isEmpty()) {
+ qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
+ QString(QTest::currentTestFunction()).toLatin1().constData());
+ for (int i = 0; i < list.count(); ++i)
+ qWarning(" %d: Object: %p Event: '%s' Child: %d", i + 1, list.at(i)->object(),
+ qAccessibleEventString(list.at(i)->type()), list.at(i)->child());
+ }
+ QTestAccessibility::clearEvents();
+}
+
void tst_QQuickAccessible::commonTests_data()
{
QTest::addColumn<QString>("accessibleRoleFileName");
@@ -141,50 +182,7 @@ void tst_QQuickAccessible::commonTests()
QVERIFY(iface);
delete view;
-}
-
-
-
-QString eventName(const int ev)
-{
- switch (ev) {
- case 0x0001: return "SoundPlayed";
- case 0x0002: return "Alert";
- case 0x0003: return "ForegroundChanged";
- case 0x0004: return "MenuStart";
- case 0x0005: return "MenuEnd";
- case 0x0006: return "PopupMenuStart";
- case 0x0007: return "PopupMenuEnd";
- case 0x000C: return "ContextHelpStart";
- case 0x000D: return "ContextHelpEnd";
- case 0x000E: return "DragDropStart";
- case 0x000F: return "DragDropEnd";
- case 0x0010: return "DialogStart";
- case 0x0011: return "DialogEnd";
- case 0x0012: return "ScrollingStart";
- case 0x0013: return "ScrollingEnd";
- case 0x0018: return "MenuCommand";
- case 0x8000: return "ObjectCreated";
- case 0x8001: return "ObjectDestroyed";
- case 0x8002: return "ObjectShow";
- case 0x8003: return "ObjectHide";
- case 0x8004: return "ObjectReorder";
- case 0x8005: return "Focus";
- case 0x8006: return "Selection";
- case 0x8007: return "SelectionAdd";
- case 0x8008: return "SelectionRemove";
- case 0x8009: return "SelectionWithin";
- case 0x800A: return "StateChanged";
- case 0x800B: return "LocationChanged";
- case 0x800C: return "NameChanged";
- case 0x800D: return "DescriptionChanged";
- case 0x800E: return "ValueChanged";
- case 0x800F: return "ParentChanged";
- case 0x80A0: return "HelpChanged";
- case 0x80B0: return "DefaultActionChanged";
- case 0x80C0: return "AcceleratorChanged";
- default: return "Unknown Event";
- }
+ QTestAccessibility::clearEvents();
}
void tst_QQuickAccessible::quickAttachedProperties()
@@ -259,6 +257,7 @@ void tst_QQuickAccessible::quickAttachedProperties()
}
delete object;
}
+ QTestAccessibility::clearEvents();
}
@@ -309,6 +308,7 @@ void tst_QQuickAccessible::basicPropertiesTest()
QCOMPARE(text2->indexOfChild(item), -1);
delete window;
+ QTestAccessibility::clearEvents();
}
QAccessibleInterface *topLevelChildAt(QAccessibleInterface *iface, int x, int y)
@@ -374,6 +374,7 @@ void tst_QQuickAccessible::hitTest()
QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201"));
delete window;
+ QTestAccessibility::clearEvents();
}
void tst_QQuickAccessible::checkableTest()
@@ -381,6 +382,17 @@ void tst_QQuickAccessible::checkableTest()
QScopedPointer<QQuickView> window(new QQuickView());
window->setSource(testFileUrl("checkbuttons.qml"));
window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ QQuickItem *contentItem = window->contentItem();
+ QVERIFY(contentItem);
+ QQuickItem *rootItem = contentItem->childItems().first();
+ QVERIFY(rootItem);
+
+ // the window becomes active
+ QAccessible::State activatedChange;
+ activatedChange.active = true;
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data());
QVERIFY(iface);
@@ -391,9 +403,28 @@ void tst_QQuickAccessible::checkableTest()
QVERIFY(!(button1->state().checked));
QVERIFY(!(button1->state().checkable));
+ QVERIFY(button1->state().focusable);
+ QVERIFY(!button1->state().focused);
+
+ QTestAccessibility::clearEvents();
+
+ // set properties
+ QQuickItem *button1item = qobject_cast<QQuickItem*>(rootItem->childItems().at(0));
+ QVERIFY(button1item);
+ QCOMPARE(button1item->objectName(), QLatin1String("button1"));
+ button1item->forceActiveFocus();
+ QVERIFY(button1->state().focusable);
+ QVERIFY(button1->state().focused);
+
+ QAccessibleEvent focusEvent(button1item, QAccessible::Focus);
+ QVERIFY_EVENT(&focusEvent);
+
QAccessibleInterface *button2 = root->child(1);
QVERIFY(!(button2->state().checked));
QVERIFY(button2->state().checkable);
+ QQuickItem *button2item = qobject_cast<QQuickItem*>(rootItem->childItems().at(1));
+ QVERIFY(button2item);
+ QCOMPARE(button2item->objectName(), QLatin1String("button2"));
QAccessibleInterface *button3 = root->child(2);
QVERIFY(button3->state().checked);
@@ -401,12 +432,28 @@ void tst_QQuickAccessible::checkableTest()
QAccessibleInterface *checkBox1 = root->child(3);
QCOMPARE(checkBox1->role(), QAccessible::CheckBox);
- QVERIFY((checkBox1->state().checked));
+ QVERIFY(checkBox1->state().checked);
QVERIFY(checkBox1->state().checkable);
+ QQuickItem *checkbox1item = qobject_cast<QQuickItem*>(rootItem->childItems().at(3));
+ QVERIFY(checkbox1item);
+ QCOMPARE(checkbox1item->objectName(), QLatin1String("checkbox1"));
+
+ checkbox1item->setProperty("checked", false);
+ QVERIFY(!checkBox1->state().checked);
+ QAccessible::State checkState;
+ checkState.checked = true;
+ QAccessibleStateChangeEvent checkChanged(checkbox1item, checkState);
+ QVERIFY_EVENT(&checkChanged);
+
+ checkbox1item->setProperty("checked", true);
+ QVERIFY(checkBox1->state().checked);
+ QVERIFY_EVENT(&checkChanged);
QAccessibleInterface *checkBox2 = root->child(4);
QVERIFY(!(checkBox2->state().checked));
QVERIFY(checkBox2->state().checkable);
+
+ QTestAccessibility::clearEvents();
}
QTEST_MAIN(tst_QQuickAccessible)
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index 0377eaa71d..c1a223c30d 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -223,6 +223,10 @@ void tst_qquickanimatedimage::mirror_notRunning()
screenshot = window.grabWindow();
screenshot.save("screen.png");
+#if defined(Q_OS_WIN)
+ // QTBUG-36717
+ QSKIP("This test is failing in the CI system under mysterious circumstances");
+#endif
QCOMPARE(screenshot, expected);
// mirroring should not change the current frame or playing status
diff --git a/tests/auto/quick/qquickanimations/data/runningTrueBug.qml b/tests/auto/quick/qquickanimations/data/runningTrueBug.qml
index bec6fab368..b2e8afcf0f 100644
--- a/tests/auto/quick/qquickanimations/data/runningTrueBug.qml
+++ b/tests/auto/quick/qquickanimations/data/runningTrueBug.qml
@@ -26,5 +26,5 @@ Rectangle {
duration: 1000
}
}
- }
+ }
}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index c6f4779819..21872a5528 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -470,6 +470,9 @@ void tst_qquickanimations::pathInterpolator()
void tst_qquickanimations::pathInterpolatorBackwardJump()
{
+#ifdef Q_CC_MINGW
+ QSKIP("QTBUG-36290 - MinGW Animation tests are flaky.");
+#endif
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack.qml"));
diff --git a/tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning.qml b/tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning.qml
new file mode 100644
index 0000000000..1ec3a923d4
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ Behavior on x {
+ objectName: "MyBehavior"
+ NumberAnimation { id: myAnimation; objectName: "MyAnimation"; duration: 1000; }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning2.qml b/tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning2.qml
new file mode 100644
index 0000000000..fcd9c06de9
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/disabledWriteWhileRunning2.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRect"
+ width: 100; height: 100; color: "green"
+ Behavior on x {
+ objectName: "MyBehavior"
+ SmoothedAnimation { id: myAnimation; objectName: "MyAnimation"; duration: 1000; velocity: -1 }
+ }
+ }
+}
diff --git a/examples/quick/dialogs/systemdialogs/systemdialogs.qml b/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
index 1600e88812..9cf22dc7a1 100644
--- a/examples/quick/dialogs/systemdialogs/systemdialogs.qml
+++ b/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the examples of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
@@ -38,34 +38,34 @@
**
****************************************************************************/
-import QtQuick 2.2
-import "../../shared"
+import QtQuick 2.0
-TabSet {
- width: 580
- height: 440
+Item {
+ width: 400; height: 400
- FileDialogs {
- property string title: "File Dialog"
- anchors.fill: parent
- color: "#e3e3e3" // to match tab.png
- }
+ property alias animRunning: springAnim.running
- ColorDialogs {
- property string title: "Color Dialog"
- anchors.fill: parent
- color: "#e3e3e3" // to match tab.png
- }
+ Rectangle {
+ objectName: "myRect"
+ color: "green"
+ width: 20; height: 20
- FontDialogs {
- property string title: "Font Dialog"
- anchors.fill: parent
- color: "#e3e3e3" // to match tab.png
- }
+ property bool triggered: false
+
+ onXChanged: {
+ if (!triggered && x > 50 && x < 80) {
+ triggered = true
+ x = x //set same value
+ }
+ }
- MessageDialogs {
- property string title: "Message Dialog"
- anchors.fill: parent
- color: "#e3e3e3" // to match tab.png
+ Behavior on x {
+ SpringAnimation {
+ id: springAnim
+ spring: 3
+ damping: 0.2
+ mass: .5
+ }
+ }
}
}
diff --git a/tests/auto/quick/qquickbehaviors/data/qtbug21549.qml b/tests/auto/quick/qquickbehaviors/data/qtbug21549.qml
new file mode 100644
index 0000000000..db076bca9a
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/qtbug21549.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+Item {
+ width: 200
+ height: 200
+
+ property int behaviorCount: 0
+
+ Rectangle {
+ id: myRect
+ objectName: "myRect"
+ width: 100
+ height: 100
+ Behavior on x {
+ ScriptAction { script: ++behaviorCount }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index c40abbd55f..cabc029b82 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -47,6 +47,7 @@
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickbehavior_p.h>
#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquicksmoothedanimation_p.h>
#include <private/qquickitem_p.h>
#include "../../shared/util.h"
@@ -81,6 +82,8 @@ private slots:
void delayedRegistration();
void startOnCompleted();
void multipleChangesToValueType();
+ void currentValue();
+ void disabledWriteWhileRunning();
};
void tst_qquickbehaviors::simpleBehavior()
@@ -495,6 +498,144 @@ void tst_qquickbehaviors::multipleChangesToValueType()
QTRY_COMPARE(text->property("font").value<QFont>(), value);
}
+//QTBUG-21549
+void tst_qquickbehaviors::currentValue()
+{
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("qtbug21549.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+
+ QQuickRectangle *target = item->findChild<QQuickRectangle*>("myRect");
+ QVERIFY(target);
+
+ QCOMPARE(target->x(), qreal(0));
+
+ target->setProperty("x", 50);
+ QCOMPARE(item->property("behaviorCount").toInt(), 1);
+ QCOMPARE(target->x(), qreal(50));
+
+ target->setProperty("x", 50);
+ QCOMPARE(item->property("behaviorCount").toInt(), 1);
+ QCOMPARE(target->x(), qreal(50));
+
+ target->setX(100);
+ target->setProperty("x", 100);
+ QCOMPARE(item->property("behaviorCount").toInt(), 1);
+ QCOMPARE(target->x(), qreal(100));
+
+ delete item;
+ }
+
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("qtbug21549-2.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(item);
+
+ QQuickRectangle *target = item->findChild<QQuickRectangle*>("myRect");
+ QVERIFY(target);
+
+ QCOMPARE(target->x(), qreal(0));
+
+ target->setProperty("x", 100);
+
+ // the spring animation should smoothly transition to the new value triggered
+ // in the QML (which should be between 50 and 80);
+ QTRY_COMPARE(item->property("animRunning").toBool(), true);
+ QTRY_COMPARE(item->property("animRunning").toBool(), false);
+ QVERIFY(target->x() > qreal(50) && target->x() < qreal(80));
+
+ delete item;
+ }
+}
+
+void tst_qquickbehaviors::disabledWriteWhileRunning()
+{
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("disabledWriteWhileRunning.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(root);
+
+ QQuickRectangle *myRect = qobject_cast<QQuickRectangle*>(root->findChild<QQuickRectangle*>("MyRect"));
+ QQuickBehavior *myBehavior = qobject_cast<QQuickBehavior*>(root->findChild<QQuickBehavior*>("MyBehavior"));
+ QQuickNumberAnimation *myAnimation = qobject_cast<QQuickNumberAnimation*>(root->findChild<QQuickNumberAnimation*>("MyAnimation"));
+ QVERIFY(myRect);
+ QVERIFY(myBehavior);
+ QVERIFY(myAnimation);
+
+ // initial values
+ QCOMPARE(myBehavior->enabled(), true);
+ QCOMPARE(myAnimation->isRunning(), false);
+ QCOMPARE(myRect->x(), qreal(0));
+
+ // start animation
+ myRect->setProperty("x", 200);
+ QCOMPARE(myAnimation->isRunning(), true);
+ QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200));
+
+ // set disabled while animation is in progress
+ myBehavior->setProperty("enabled", false);
+ QCOMPARE(myAnimation->isRunning(), true);
+
+ // force new value while disabled and previous animation is in progress.
+ // animation should be stopped and value stay at forced value
+ myRect->setProperty("x", 100);
+ QCOMPARE(myAnimation->isRunning(), false);
+ QCOMPARE(myRect->x(), qreal(100));
+ QTest::qWait(200);
+ QCOMPARE(myRect->x(), qreal(100));
+
+ delete root;
+ }
+
+ //test additional complications with SmoothedAnimation
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("disabledWriteWhileRunning2.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(root);
+
+ QQuickRectangle *myRect = qobject_cast<QQuickRectangle*>(root->findChild<QQuickRectangle*>("MyRect"));
+ QQuickBehavior *myBehavior = qobject_cast<QQuickBehavior*>(root->findChild<QQuickBehavior*>("MyBehavior"));
+ QQuickSmoothedAnimation *myAnimation = qobject_cast<QQuickSmoothedAnimation*>(root->findChild<QQuickNumberAnimation*>("MyAnimation"));
+ QVERIFY(myRect);
+ QVERIFY(myBehavior);
+ QVERIFY(myAnimation);
+
+ // initial values
+ QCOMPARE(myBehavior->enabled(), true);
+ QCOMPARE(myAnimation->isRunning(), false);
+ QCOMPARE(myRect->x(), qreal(0));
+
+ // start animation
+ myRect->setProperty("x", 200);
+ QCOMPARE(myAnimation->isRunning(), true);
+ QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200));
+
+ //set second value
+ myRect->setProperty("x", 300);
+ QCOMPARE(myAnimation->isRunning(), true);
+ QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200));
+
+ // set disabled while animation is in progress
+ myBehavior->setProperty("enabled", false);
+ QCOMPARE(myAnimation->isRunning(), true);
+
+ // force new value while disabled and previous animation is in progress.
+ // animation should be stopped and value stay at forced value
+ myRect->setProperty("x", 100);
+ QCOMPARE(myAnimation->isRunning(), false);
+ QCOMPARE(myRect->x(), qreal(100));
+ QTest::qWait(200);
+ QCOMPARE(myRect->x(), qreal(100));
+
+ delete root;
+ }
+}
+
QTEST_MAIN(tst_qquickbehaviors)
#include "tst_qquickbehaviors.moc"
diff --git a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml
index bc11d349fa..e299147b36 100644
--- a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml
@@ -1,5 +1,6 @@
import QtQuick 2.0
import QtTest 1.0
+import QtQuick.Window 2.1
TestCase {
id:testCase
@@ -10,10 +11,12 @@ TestCase {
function cleanupTestCase() {
wait(100) //wait for a short while to make sure no leaked textures
}
+
function testData(type) {
if (type === "2d")
return [
{ tag:"image threaded", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Threaded}},
+ { tag:"image canvas invisible", properties:{visible: false, width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Threaded}},
// { tag:"image cooperative", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Cooperative}},
{ tag:"image immediate", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Immediate}},
// { tag:"fbo cooperative", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Cooperative}},
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
index f13039ad95..b92f6354a5 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
@@ -180,11 +180,20 @@ CanvasTestCase {
tryCompare(c, "availableChangedCount", 1);
//scene graph could be available immediately
//in this case, we force waiting a short while until the init paint finished
- tryCompare(c, "paintedCount", 1);
+ if (c.visible) {
+ tryCompare(c, "paintedCount", 1);
+ } else {
+ tryCompare(c, "paintedCount", 0);
+ }
ctx.fillRect(0, 0, c.width, c.height);
c.toDataURL();
- tryCompare(c, "paintedCount", 2);
- tryCompare(c, "paintCount", 1);
+ if (c.visible) {
+ tryCompare(c, "paintCount", 1);
+ tryCompare(c, "paintedCount", 2);
+ } else {
+ tryCompare(c, "paintCount", 0);
+ tryCompare(c, "paintedCount", 1);
+ }
c.destroy();
}
function test_loadImage(row) {
diff --git a/src/imports/dialogs/qquickplatformcolordialog_p.h b/tests/auto/quick/qquickgridview/data/displayMargin.qml
index 55d301da8b..1086b8defd 100644
--- a/src/imports/dialogs/qquickplatformcolordialog_p.h
+++ b/tests/auto/quick/qquickgridview/data/displayMargin.qml
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Jolla Ltd.
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,40 +39,47 @@
**
****************************************************************************/
-#ifndef QQUICKPLATFORMCOLORDIALOG_P_H
-#define QQUICKPLATFORMCOLORDIALOG_P_H
+import QtQuick 2.3
-//
-// 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.
-//
+Item {
+ width: 400; height: 400
-#include "qquickabstractcolordialog_p.h"
+ GridView {
+ id: view
+ anchors.top: header.bottom
+ anchors.bottom: footer.top
+ width: parent.width
-QT_BEGIN_NAMESPACE
+ cellWidth: 50
+ cellHeight: 25
-class QQuickPlatformColorDialog : public QQuickAbstractColorDialog
-{
- Q_OBJECT
+ cacheBuffer: 0
+ displayMarginBeginning: 60
+ displayMarginEnd: 60
-public:
- QQuickPlatformColorDialog(QObject *parent = 0);
- virtual ~QQuickPlatformColorDialog();
+ model: 200
+ delegate: Rectangle {
+ objectName: "delegate"
+ width: 50
+ height: 25
+ color: index % 2 ? "steelblue" : "lightsteelblue"
+ Text {
+ anchors.centerIn: parent
+ text: index
+ }
+ }
+ }
-protected:
- QPlatformColorDialogHelper *helper();
+ Rectangle {
+ id: header
+ width: parent.width; height: 60
+ color: "#80FF0000"
+ }
- Q_DISABLE_COPY(QQuickPlatformColorDialog)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPlatformColorDialog *)
-
-#endif // QQUICKPLATFORMCOLORDIALOG_P_H
+ Rectangle {
+ id: footer
+ anchors.bottom: parent.bottom
+ width: parent.width; height: 60
+ color: "#80FF0000"
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/data/gridview-enforcerange.qml b/tests/auto/quick/qquickgridview/data/gridview-enforcerange.qml
index 2bfe7da78e..d1f8c31e1d 100644
--- a/tests/auto/quick/qquickgridview/data/gridview-enforcerange.qml
+++ b/tests/auto/quick/qquickgridview/data/gridview-enforcerange.qml
@@ -39,7 +39,7 @@ Rectangle {
color: "lightsteelblue"
}
}
-
+
GridView {
id: grid
objectName: "grid"
diff --git a/tests/auto/quick/qquickgridview/data/propertychangestest.qml b/tests/auto/quick/qquickgridview/data/propertychangestest.qml
index 97efbe78f5..af3126f2d4 100644
--- a/tests/auto/quick/qquickgridview/data/propertychangestest.qml
+++ b/tests/auto/quick/qquickgridview/data/propertychangestest.qml
@@ -6,7 +6,7 @@ Rectangle {
id: delegate
Item {
id: wrapper
- width: 180; height: 40;
+ width: 180; height: 40;
Column {
x: 5; y: 5
Text { text: '<b>Name:</b> ' + name }
@@ -36,7 +36,7 @@ Rectangle {
flow: GridView.LeftToRight
}
- data:[
+ data:[
ListModel {
id: listModel
ListElement {
@@ -65,5 +65,5 @@ Rectangle {
}
]
}
-
-
+
+
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index f1adb7858f..2ee98c6c61 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -207,6 +207,8 @@ private slots:
void moved_topToBottom_RtL_BtT();
void moved_topToBottom_RtL_BtT_data();
+ void displayMargin();
+
private:
QList<int> toIntList(const QVariantList &list);
void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
@@ -6307,6 +6309,43 @@ void tst_QQuickGridView::matchItemLists(const QVariantList &itemLists, const QLi
}
}
+void tst_QQuickGridView::displayMargin()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("displayMargin.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickGridView *gridview = window->rootObject()->findChild<QQuickGridView*>();
+ QVERIFY(gridview != 0);
+
+ QQuickItem *content = gridview->contentItem();
+ QVERIFY(content != 0);
+
+ QQuickItem *item0;
+ QQuickItem *item97;
+
+ QVERIFY(item0 = findItem<QQuickItem>(content, "delegate", 0));
+ QCOMPARE(delegateVisible(item0), true);
+
+ // the 97th item should be within the end margin
+ QVERIFY(item97 = findItem<QQuickItem>(content, "delegate", 96));
+ QCOMPARE(delegateVisible(item97), true);
+
+ // GridView staggers item creation, so the 118th item should be outside the end margin.
+ QVERIFY(findItem<QQuickItem>(content, "delegate", 117) == 0);
+
+ // the first delegate should still be within the begin margin
+ gridview->positionViewAtIndex(20, QQuickGridView::Beginning);
+ QCOMPARE(delegateVisible(item0), true);
+
+ // the first delegate should now be outside the begin margin
+ gridview->positionViewAtIndex(36, QQuickGridView::Beginning);
+ QCOMPARE(delegateVisible(item0), false);
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquickimage/data/aspectratio.qml b/tests/auto/quick/qquickimage/data/aspectratio.qml
index b26f0e1f04..a04a09d64e 100644
--- a/tests/auto/quick/qquickimage/data/aspectratio.qml
+++ b/tests/auto/quick/qquickimage/data/aspectratio.qml
@@ -1,6 +1,6 @@
import QtQuick 2.0
-Image {
+Image {
source: "heart.png"
fillMode: Image.PreserveAspectFit;
}
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index 3eea3c955c..48af48b17b 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -105,10 +105,10 @@ public:
if (id == QLatin1String("no-such-file.png"))
return QImage();
- int width = 100;
+ int width = 100;
int height = 100;
QImage image(width, height, QImage::Format_RGB32);
- if (size)
+ if (size)
*size = QSize(width, height);
if (requestedSize.isValid())
image = image.scaled(requestedSize);
@@ -142,10 +142,10 @@ public:
if (id == QLatin1String("no-such-file.png"))
return QPixmap();
- int width = 100;
+ int width = 100;
int height = 100;
QPixmap image(width, height);
- if (size)
+ if (size)
*size = QSize(width, height);
if (requestedSize.isValid())
image = image.scaled(requestedSize);
@@ -161,7 +161,7 @@ Q_DECLARE_METATYPE(TestQPixmapProvider*);
QString tst_qquickimageprovider::newImageFileName() const
{
// need to generate new filenames each time or else images are loaded
- // from cache and we won't get loading status changes when testing
+ // from cache and we won't get loading status changes when testing
// async loading
static int count = 0;
return QString("image://test/image-%1.png").arg(count++);
@@ -229,7 +229,7 @@ void tst_qquickimageprovider::runTest(bool async, QQuickImageProvider *provider)
engine.addImageProvider("test", provider);
QVERIFY(engine.imageProvider("test") != 0);
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; "
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; "
+ (async ? "asynchronous: true; " : "")
+ properties + " }";
QQmlComponent component(&engine);
diff --git a/tests/auto/quick/qquickitem/data/visualParentOwnership.qml b/tests/auto/quick/qquickitem/data/visualParentOwnership.qml
new file mode 100644
index 0000000000..644d14ba43
--- /dev/null
+++ b/tests/auto/quick/qquickitem/data/visualParentOwnership.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Item {
+ Component {
+ id: factory
+ Item {}
+ }
+
+ property Item keepAliveProperty;
+
+ function createItemWithoutParent() {
+ return factory.createObject(/*parent*/ null);
+ }
+}
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index ad3c4fc208..efe9266d0a 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -40,15 +40,18 @@
****************************************************************************/
#include <qtest.h>
+#include <qsignalspy.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuick/qquickview.h>
#include "private/qquickfocusscope_p.h"
+#include "private/qquickwindow_p.h"
#include "private/qquickitem_p.h"
#include <qpa/qwindowsysteminterface.h>
#include <QDebug>
#include <QTimer>
+#include <QQmlEngine>
#include "../../shared/util.h"
class TestItem : public QQuickItem
@@ -155,6 +158,8 @@ private slots:
void touchEventAcceptIgnore();
void polishOutsideAnimation();
void polishOnCompleted();
+ void polishLaterWhenVisible();
+ void polishWhenOtherHidden();
void wheelEvent_data();
void wheelEvent();
@@ -167,6 +172,8 @@ private slots:
void acceptedMouseButtons();
+ void visualParentOwnership();
+
private:
enum PaintOrderOp {
@@ -1393,6 +1400,63 @@ void tst_qquickitem::polishOnCompleted()
QTRY_VERIFY(item->wasPolished);
}
+void tst_qquickitem::polishLaterWhenVisible()
+{
+ QQuickWindow window;
+ QQuickWindowPrivate *wp = QQuickWindowPrivate::get(&window);
+ window.resize(200, 200);
+ window.show();
+ QTest::qWaitForWindowExposed(&window);
+
+ TestPolishItem *item = new TestPolishItem(window.contentItem());
+ item->setSize(QSizeF(200, 100));
+ item->setVisible(false);
+ item->polish();
+
+ QVERIFY(!wp->itemsToPolish.contains(item));
+ window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+ QVERIFY(!item->wasPolished);
+
+ item->setVisible(true);
+ QVERIFY(wp->itemsToPolish.contains(item));
+ window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+ QVERIFY(item->wasPolished);
+ QVERIFY(!wp->itemsToPolish.contains(item));
+}
+
+void tst_qquickitem::polishWhenOtherHidden()
+{
+ QQuickWindow window;
+ QQuickWindowPrivate *wp = QQuickWindowPrivate::get(&window);
+ window.resize(200, 200);
+ window.show();
+ QTest::qWaitForWindowExposed(&window);
+
+ // a hidden item pending for polish...
+ TestPolishItem *hiddenItem = new TestPolishItem(window.contentItem());
+ hiddenItem->setSize(QSizeF(200, 100));
+ hiddenItem->setVisible(false);
+ hiddenItem->polish();
+
+ QVERIFY(!wp->itemsToPolish.contains(hiddenItem));
+ window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+ QVERIFY(!hiddenItem->wasPolished);
+
+ // ...should not block a visible item from being polished
+ TestPolishItem *visibleItem = new TestPolishItem(window.contentItem());
+ visibleItem->setSize(QSizeF(200, 100));
+ visibleItem->setVisible(true);
+ visibleItem->polish();
+
+ QVERIFY(wp->itemsToPolish.contains(visibleItem));
+ QVERIFY(!wp->itemsToPolish.contains(hiddenItem));
+ window.grabWindow(); // trigger QQuickWindowPrivate::polishItems()
+ QVERIFY(visibleItem->wasPolished);
+ QVERIFY(!hiddenItem->wasPolished);
+ QVERIFY(!wp->itemsToPolish.contains(visibleItem));
+ QVERIFY(!wp->itemsToPolish.contains(hiddenItem));
+}
+
void tst_qquickitem::wheelEvent_data()
{
QTest::addColumn<bool>("visible");
@@ -1754,6 +1818,68 @@ void tst_qquickitem::acceptedMouseButtons()
QCOMPARE(item.releaseCount, 3);
}
+static void gc(QQmlEngine &engine)
+{
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+}
+
+void tst_qquickitem::visualParentOwnership()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("visualParentOwnership.qml"));
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
+ QVERIFY(root);
+
+ QVariant newObject;
+ {
+ QVERIFY(QMetaObject::invokeMethod(root, "createItemWithoutParent", Q_RETURN_ARG(QVariant, newObject)));
+ QPointer<QQuickItem> newItem = qvariant_cast<QQuickItem*>(newObject);
+ QVERIFY(!newItem.isNull());
+
+ QVERIFY(!newItem->parent());
+ QVERIFY(!newItem->parentItem());
+
+ newItem->setParentItem(root);
+
+ gc(*view.engine());
+
+ QVERIFY(!newItem.isNull());
+ newItem->setParentItem(0);
+
+ gc(*view.engine());
+ QVERIFY(newItem.isNull());
+ }
+ {
+ QVERIFY(QMetaObject::invokeMethod(root, "createItemWithoutParent", Q_RETURN_ARG(QVariant, newObject)));
+ QPointer<QQuickItem> firstItem = qvariant_cast<QQuickItem*>(newObject);
+ QVERIFY(!firstItem.isNull());
+
+ firstItem->setParentItem(root);
+
+ QVERIFY(QMetaObject::invokeMethod(root, "createItemWithoutParent", Q_RETURN_ARG(QVariant, newObject)));
+ QPointer<QQuickItem> secondItem = qvariant_cast<QQuickItem*>(newObject);
+ QVERIFY(!firstItem.isNull());
+
+ secondItem->setParentItem(firstItem);
+
+ gc(*view.engine());
+
+ delete firstItem;
+
+ root->setProperty("keepAliveProperty", newObject);
+
+ gc(*view.engine());
+ QVERIFY(!secondItem.isNull());
+
+ root->setProperty("keepAliveProperty", QVariant());
+
+ gc(*view.engine());
+ QVERIFY(secondItem.isNull());
+ }
+}
QTEST_MAIN(tst_qquickitem)
diff --git a/tests/auto/quick/qquickitem2/data/childrenRectBug3.qml b/tests/auto/quick/qquickitem2/data/childrenRectBug3.qml
index 518e76509e..25d6a526d2 100644
--- a/tests/auto/quick/qquickitem2/data/childrenRectBug3.qml
+++ b/tests/auto/quick/qquickitem2/data/childrenRectBug3.qml
@@ -9,7 +9,7 @@ Rectangle {
Repeater {
model: 1
- Rectangle { }
+ Rectangle { }
}
}
}
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 8a4ed5ae4c..64795f9ebe 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -1972,6 +1972,8 @@ void tst_QQuickItem::transforms_data()
QTest::addColumn<QTransform>("transform");
QTest::newRow("translate") << QByteArray("Translate { x: 10; y: 20 }")
<< QTransform(1,0,0,0,1,0,10,20,1);
+ QTest::newRow("matrix4x4") << QByteArray("Matrix4x4 { matrix: Qt.matrix4x4(1,0,0,10, 0,1,0,15, 0,0,1,0, 0,0,0,1) }")
+ << QTransform(1,0,0,0,1,0,10,15,1);
QTest::newRow("rotation") << QByteArray("Rotation { angle: 90 }")
<< QTransform(0,1,0,-1,0,0,0,0,1);
QTest::newRow("scale") << QByteArray("Scale { xScale: 1.5; yScale: -2 }")
@@ -1985,7 +1987,7 @@ void tst_QQuickItem::transforms()
QFETCH(QByteArray, qml);
QFETCH(QTransform, transform);
QQmlComponent component(&engine);
- component.setData("import QtQuick 2.0\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
+ component.setData("import QtQuick 2.4\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(item->itemTransform(0,0), transform);
diff --git a/src/imports/dialogs/qquickplatformfiledialog_p.h b/tests/auto/quick/qquicklistview/data/displayMargin.qml
index 5431836271..fde48bc5b9 100644
--- a/src/imports/dialogs/qquickplatformfiledialog_p.h
+++ b/tests/auto/quick/qquicklistview/data/displayMargin.qml
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Jolla Ltd.
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,40 +39,44 @@
**
****************************************************************************/
-#ifndef QQUICKPLATFORMFILEDIALOG_P_H
-#define QQUICKPLATFORMFILEDIALOG_P_H
+import QtQuick 2.3
-//
-// 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.
-//
+Item {
+ width: 400; height: 400
-#include "qquickabstractfiledialog_p.h"
+ ListView {
+ id: view
+ anchors.top: header.bottom
+ anchors.bottom: footer.top
+ width: parent.width
-QT_BEGIN_NAMESPACE
+ cacheBuffer: 0
+ displayMarginBeginning: 60
+ displayMarginEnd: 60
-class QQuickPlatformFileDialog : public QQuickAbstractFileDialog
-{
- Q_OBJECT
+ model: 100
+ delegate: Rectangle {
+ objectName: "delegate"
+ width: parent.width
+ height: 25
+ color: index % 2 ? "steelblue" : "lightsteelblue"
+ Text {
+ anchors.centerIn: parent
+ text: index
+ }
+ }
+ }
-public:
- QQuickPlatformFileDialog(QObject *parent = 0);
- virtual ~QQuickPlatformFileDialog();
+ Rectangle {
+ id: header
+ width: parent.width; height: 60
+ color: "#80FF0000"
+ }
-protected:
- QPlatformFileDialogHelper *helper();
-
- Q_DISABLE_COPY(QQuickPlatformFileDialog)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPlatformFileDialog *)
-
-#endif // QQUICKPLATFORMFILEDIALOG_P_H
+ Rectangle {
+ id: footer
+ anchors.bottom: parent.bottom
+ width: parent.width; height: 60
+ color: "#80FF0000"
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/listview-enforcerange.qml b/tests/auto/quick/qquicklistview/data/listview-enforcerange.qml
index 4ccf3088b0..3d3885a5ca 100644
--- a/tests/auto/quick/qquicklistview/data/listview-enforcerange.qml
+++ b/tests/auto/quick/qquicklistview/data/listview-enforcerange.qml
@@ -39,7 +39,7 @@ Rectangle {
color: "lightsteelblue"
}
}
-
+
ListView {
id: list
objectName: "list"
diff --git a/tests/auto/quick/qquicklistview/data/propertychangestest.qml b/tests/auto/quick/qquicklistview/data/propertychangestest.qml
index 146f3f13b0..f269b4ab92 100644
--- a/tests/auto/quick/qquicklistview/data/propertychangestest.qml
+++ b/tests/auto/quick/qquicklistview/data/propertychangestest.qml
@@ -6,7 +6,7 @@ Rectangle {
id: delegate
Item {
id: wrapper
- width: 180; height: 40;
+ width: 180; height: 40;
Column {
x: 5; y: 5
Text { text: '<b>Name:</b> ' + name }
@@ -38,7 +38,7 @@ Rectangle {
snapMode: ListView.SnapToItem
}
- data:[
+ data:[
ListModel {
id: listModel
ListElement {
@@ -67,5 +67,5 @@ Rectangle {
}
]
}
-
-
+
+
diff --git a/tests/auto/quick/qquicklistview/incrementalmodel.cpp b/tests/auto/quick/qquicklistview/incrementalmodel.cpp
index 473d52eb28..3d4b716e6b 100644
--- a/tests/auto/quick/qquicklistview/incrementalmodel.cpp
+++ b/tests/auto/quick/qquicklistview/incrementalmodel.cpp
@@ -59,10 +59,10 @@ QVariant IncrementalModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
-
+
if (index.row() >= list.size() || index.row() < 0)
return QVariant();
-
+
if (role == Qt::DisplayRole)
return list.at(index.row());
return QVariant();
@@ -82,7 +82,7 @@ void IncrementalModel::fetchMore(const QModelIndex & /* index */)
int itemsToFetch = qMin(5, remainder);
beginInsertRows(QModelIndex(), count, count+itemsToFetch-1);
-
+
count += itemsToFetch;
endInsertRows();
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 97259e9fca..7d0b76ad63 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -215,6 +215,7 @@ private slots:
void testProxyModelChangedAfterMove();
void typedModel();
+ void displayMargin();
void highlightItemGeometryChanges();
@@ -7051,6 +7052,43 @@ void tst_QQuickListView::typedModel()
QCOMPARE(listview->count(), 0);
}
+void tst_QQuickListView::displayMargin()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("displayMargin.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QVERIFY(listview != 0);
+
+ QQuickItem *content = listview->contentItem();
+ QVERIFY(content != 0);
+
+ QQuickItem *item0;
+ QQuickItem *item14;
+
+ QVERIFY(item0 = findItem<QQuickItem>(content, "delegate", 0));
+ QCOMPARE(delegateVisible(item0), true);
+
+ // the 14th item should be within the end margin
+ QVERIFY(item14 = findItem<QQuickItem>(content, "delegate", 13));
+ QCOMPARE(delegateVisible(item14), true);
+
+ // the 15th item should be outside the end margin
+ QVERIFY(findItem<QQuickItem>(content, "delegate", 14) == 0);
+
+ // the first delegate should still be within the begin margin
+ listview->positionViewAtIndex(3, QQuickListView::Beginning);
+ QCOMPARE(delegateVisible(item0), true);
+
+ // the first delegate should now be outside the begin margin
+ listview->positionViewAtIndex(4, QQuickListView::Beginning);
+ QCOMPARE(delegateVisible(item0), false);
+
+ delete window;
+}
+
void tst_QQuickListView::highlightItemGeometryChanges()
{
QQmlEngine engine;
diff --git a/tests/auto/quick/qquickmousearea/data/dragproperties.qml b/tests/auto/quick/qquickmousearea/data/dragproperties.qml
index d8d7b3bb6e..4e0dbe6277 100644
--- a/tests/auto/quick/qquickmousearea/data/dragproperties.qml
+++ b/tests/auto/quick/qquickmousearea/data/dragproperties.qml
@@ -1,7 +1,7 @@
import QtQuick 2.0
Rectangle {
id: whiteRect
- width: 200
+ width: 200
height: 200
color: "white"
Rectangle {
diff --git a/tests/auto/quick/qquickmousearea/data/dragreset.qml b/tests/auto/quick/qquickmousearea/data/dragreset.qml
index 3259dcf87d..10039f1fcb 100644
--- a/tests/auto/quick/qquickmousearea/data/dragreset.qml
+++ b/tests/auto/quick/qquickmousearea/data/dragreset.qml
@@ -1,7 +1,7 @@
import QtQuick 2.0
Rectangle {
id: whiteRect
- width: 200
+ width: 200
height: 200
color: "white"
Rectangle {
diff --git a/tests/auto/quick/qquickpathview/data/propertychanges.qml b/tests/auto/quick/qquickpathview/data/propertychanges.qml
index 09b309f86f..17d24f6606 100644
--- a/tests/auto/quick/qquickpathview/data/propertychanges.qml
+++ b/tests/auto/quick/qquickpathview/data/propertychanges.qml
@@ -6,7 +6,7 @@ Rectangle {
id: myDelegate
Item {
id: wrapper
- width: 180; height: 40;
+ width: 180; height: 40;
opacity: PathView.opacity
Column {
x: 5; y: 5
@@ -46,7 +46,7 @@ Rectangle {
}
}
- data:[
+ data:[
ListModel {
id: listModel
ListElement {
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index 5657ec44a8..2ecb3c4725 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
#include <qtest.h>
+#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -54,6 +55,7 @@ public:
private slots:
void gradient();
+ void antialiasing();
private:
QQmlEngine engine;
@@ -94,6 +96,61 @@ void tst_qquickrectangle::gradient()
delete rect;
}
+void tst_qquickrectangle::antialiasing()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n Rectangle {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle *>(object.data());
+ QVERIFY(rect);
+
+ QSignalSpy spy(rect, SIGNAL(antialiasingChanged(bool)));
+
+ QCOMPARE(rect->antialiasing(), false);
+
+ rect->setAntialiasing(true);
+ QCOMPARE(rect->antialiasing(), true);
+ QCOMPARE(spy.count(), 1);
+
+ rect->setAntialiasing(true);
+ QCOMPARE(spy.count(), 1);
+
+ rect->resetAntialiasing();
+ QCOMPARE(rect->antialiasing(), false);
+ QCOMPARE(spy.count(), 2);
+
+ rect->setRadius(5);
+ QCOMPARE(rect->antialiasing(), true);
+ QCOMPARE(spy.count(), 3);
+
+ rect->resetAntialiasing();
+ QCOMPARE(rect->antialiasing(), true);
+ QCOMPARE(spy.count(), 3);
+
+ rect->setRadius(0);
+ QCOMPARE(rect->antialiasing(), false);
+ QCOMPARE(spy.count(), 4);
+
+ rect->resetAntialiasing();
+ QCOMPARE(rect->antialiasing(), false);
+ QCOMPARE(spy.count(), 4);
+
+ rect->setRadius(5);
+ QCOMPARE(rect->antialiasing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ rect->resetAntialiasing();
+ QCOMPARE(rect->antialiasing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ rect->setAntialiasing(false);
+ QCOMPARE(rect->antialiasing(), false);
+ QCOMPARE(spy.count(), 6);
+
+ rect->resetAntialiasing();
+ QCOMPARE(rect->antialiasing(), true);
+ QCOMPARE(spy.count(), 7);
+}
QTEST_MAIN(tst_qquickrectangle)
diff --git a/tests/auto/quick/qquickrepeater/data/properties.qml b/tests/auto/quick/qquickrepeater/data/properties.qml
index 035431c784..18d014f96d 100644
--- a/tests/auto/quick/qquickrepeater/data/properties.qml
+++ b/tests/auto/quick/qquickrepeater/data/properties.qml
@@ -1,11 +1,11 @@
import QtQuick 2.0
-Row {
- Repeater {
+Row {
+ Repeater {
objectName: "repeater"
model: 5
- Text {
- text: "I'm item " + index
- }
+ Text {
+ text: "I'm item " + index
+ }
}
}
diff --git a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
index 705ee5cf46..650ce09dfa 100644
--- a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
+++ b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
@@ -192,6 +192,9 @@ void tst_qquicksmoothedanimation::valueSource()
void tst_qquicksmoothedanimation::behavior()
{
+#ifdef Q_CC_MINGW
+ QSKIP("QTBUG-36290 - MinGW Animation tests are flaky.");
+#endif
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("smoothedanimationBehavior.qml"));
diff --git a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
index 4e9ceba2a2..a2e05ba883 100644
--- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
+++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
@@ -86,7 +86,7 @@ const QChar tst_qquickstyledtext::disc(0x25e6);
const QChar tst_qquickstyledtext::square(0x25a1);
// For malformed input all we test is that we get the expected text and format out.
-//
+//
void tst_qquickstyledtext::textOutput_data()
{
QTest::addColumn<QString>("input");
diff --git a/tests/auto/quick/qquicktext/data/lineLayoutHAlign.qml b/tests/auto/quick/qquicktext/data/lineLayoutHAlign.qml
new file mode 100644
index 0000000000..6349f7a644
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/lineLayoutHAlign.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+
+Item {
+ id: main
+ width: 200; height: 200
+
+ Text {
+ id: myText
+ objectName: "myText"
+ width: parent.width
+ font.family: "__Qt__Box__Engine__"
+ font.pixelSize: 14
+ horizontalAlignment: Text.AlignHCenter
+ text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+
+ onLineLaidOut: {
+ // do nothing
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 6a18323190..59806a8aec 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -101,6 +101,7 @@ private slots:
void color();
void smooth();
void renderType();
+ void antialiasing();
// QQuickFontValueType
void weight();
@@ -126,6 +127,7 @@ private slots:
void clipRect();
void lineLaidOut();
void lineLaidOutRelayout();
+ void lineLaidOutHAlign();
void imgTagsBaseUrl_data();
void imgTagsBaseUrl();
@@ -901,6 +903,8 @@ void tst_qquicktext::hAlignImplicitWidth()
{
// HCenter Align
text->setHAlign(QQuickText::AlignHCenter);
+ text->setText("Reset"); // set dummy string to force relayout once original text is set again
+ text->setText("AA\nBBBBBBB\nCCCCCCCCCCCCCCCC");
QImage image = view.grabWindow();
const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image);
const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image);
@@ -911,6 +915,8 @@ void tst_qquicktext::hAlignImplicitWidth()
{
// Right Align
text->setHAlign(QQuickText::AlignRight);
+ text->setText("Reset"); // set dummy string to force relayout once original text is set again
+ text->setText("AA\nBBBBBBB\nCCCCCCCCCCCCCCCC");
QImage image = view.grabWindow();
const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image);
const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image);
@@ -1306,6 +1312,30 @@ void tst_qquicktext::renderType()
QCOMPARE(spy.count(), 2);
}
+void tst_qquicktext::antialiasing()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n Text {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickText *text = qobject_cast<QQuickText *>(object.data());
+ QVERIFY(text);
+
+ QSignalSpy spy(text, SIGNAL(antialiasingChanged(bool)));
+
+ QCOMPARE(text->antialiasing(), true);
+
+ text->setAntialiasing(false);
+ QCOMPARE(text->antialiasing(), false);
+ QCOMPARE(spy.count(), 1);
+
+ text->setAntialiasing(false);
+ QCOMPARE(spy.count(), 1);
+
+ text->resetAntialiasing();
+ QCOMPARE(text->antialiasing(), true);
+ QCOMPARE(spy.count(), 2);
+}
+
void tst_qquicktext::weight()
{
{
@@ -1913,6 +1943,7 @@ void tst_qquicktext::linkInteraction()
QCOMPARE(test.hoveredLink, hoverEnterLink);
QCOMPARE(textObject->hoveredLink(), hoverEnterLink);
+ QCOMPARE(textObject->linkAt(mousePosition.x(), mousePosition.y()), hoverEnterLink);
for (int i = 1; i < mousePositions.count(); ++i) {
mousePosition = mousePositions.at(i);
@@ -1926,6 +1957,7 @@ void tst_qquicktext::linkInteraction()
QCOMPARE(test.hoveredLink, hoverMoveLink);
QCOMPARE(textObject->hoveredLink(), hoverMoveLink);
+ QCOMPARE(textObject->linkAt(mousePosition.x(), mousePosition.y()), hoverMoveLink);
{
QHoverEvent he(QEvent::HoverLeave, mousePosition, QPointF());
@@ -1938,6 +1970,7 @@ void tst_qquicktext::linkInteraction()
QCOMPARE(test.clickedLink, clickedLink);
QCOMPARE(test.hoveredLink, QString());
QCOMPARE(textObject->hoveredLink(), QString());
+ QCOMPARE(textObject->linkAt(-1, -1), QString());
delete textObject;
}
@@ -2648,6 +2681,23 @@ void tst_qquicktext::lineLaidOutRelayout()
delete window;
}
+void tst_qquicktext::lineLaidOutHAlign()
+{
+ QQuickView *window = createView(testFile("lineLayoutHAlign.qml"));
+
+ QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != 0);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != 0);
+
+ QCOMPARE(textPrivate->layout.lineCount(), 1);
+
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().x() < 0.0);
+
+ delete window;
+}
+
void tst_qquicktext::imgTagsBaseUrl_data()
{
QTest::addColumn<QUrl>("src");
diff --git a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTest.qml b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTest.qml
index 043304d027..5deffe7d11 100644
--- a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTest.qml
+++ b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTest.qml
@@ -1,12 +1,12 @@
import QtQuick 2.0
Rectangle { width: 300; height: 300; color: "white"
- resources: [
+ resources: [
Component { id:cursorFail; FailItem { objectName: "delegateFail" } },
Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } },
Component { id:cursorErr; ErrItem { objectName: "delegateErrorA" } }
- ]
+ ]
TextEdit {
cursorDelegate: cursorFail
cursorVisible: true
diff --git a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail1.qml b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail1.qml
index a6556454fe..bff8ae435b 100644
--- a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail1.qml
+++ b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail1.qml
@@ -1,11 +1,11 @@
import QtQuick 2.0
Rectangle { width: 300; height: 300; color: "white"
- resources: [
+ resources: [
Component { id:cursorFail; FailItem { objectName: "delegateFail" } },
Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } }
- ]
+ ]
TextEdit {
cursorDelegate: cursorFail
cursorVisible: true
diff --git a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail2.qml b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail2.qml
index 9429779a87..1cf1ed47f2 100644
--- a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail2.qml
+++ b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestFail2.qml
@@ -1,11 +1,11 @@
import QtQuick 2.0
Rectangle { width: 300; height: 300; color: "white"
- resources: [
+ resources: [
Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } },
Component { id:cursorErr; ErrItem { objectName: "delegateErrorA" } }
- ]
+ ]
TextEdit {
cursorDelegate: cursorWait
cursorVisible: true
diff --git a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestPass.qml b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestPass.qml
index 69e498ef8d..d97a9a609a 100644
--- a/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestPass.qml
+++ b/tests/auto/quick/qquicktextedit/data/http/cursorHttpTestPass.qml
@@ -1,10 +1,10 @@
import QtQuick 2.0
Rectangle { width: 300; height: 300; color: "white"
- resources: [
+ resources: [
Component { id:cursorWait; WaitItem { objectName: "delegateSlow" } },
Component { id:cursorNorm; NormItem { objectName: "delegateOkay" } }
- ]
+ ]
TextEdit {
cursorDelegate: cursorWait
text: "Hello"
diff --git a/tests/auto/quick/qquicktextedit/data/inputmethodhints.qml b/tests/auto/quick/qquicktextedit/data/inputmethodhints.qml
index dec3b978e7..5ec99198a4 100644
--- a/tests/auto/quick/qquicktextedit/data/inputmethodhints.qml
+++ b/tests/auto/quick/qquicktextedit/data/inputmethodhints.qml
@@ -1,6 +1,6 @@
import QtQuick 2.0
-TextEdit {
+TextEdit {
text: "Hello world!"
inputMethodHints: Qt.ImhNoPredictiveText
}
diff --git a/tests/auto/quick/qquicktextedit/data/navigation.qml b/tests/auto/quick/qquicktextedit/data/navigation.qml
index 0201c62b3c..7604c96adf 100644
--- a/tests/auto/quick/qquicktextedit/data/navigation.qml
+++ b/tests/auto/quick/qquicktextedit/data/navigation.qml
@@ -5,7 +5,7 @@ Rectangle {
width: 800; height: 600; color: "blue"
- Item {
+ Item {
id: firstItem;
KeyNavigation.right: input
}
@@ -18,7 +18,7 @@ Rectangle {
text: "a"
}
Item {
- id: lastItem
+ id: lastItem
KeyNavigation.left: input
}
}
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index ff9554718b..e6a83b3338 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -2393,12 +2393,14 @@ void tst_qquicktextedit::linkInteraction()
QCOMPARE(spy.last()[0].toString(), link);
QCOMPARE(hover.last()[0].toString(), link);
QCOMPARE(texteditObject->hoveredLink(), link);
+ QCOMPARE(texteditObject->linkAt(linkPos.x(), linkPos.y()), link);
QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
QTRY_COMPARE(spy.count(), 1);
QTRY_COMPARE(hover.count(), 2);
QCOMPARE(hover.last()[0].toString(), QString());
QCOMPARE(texteditObject->hoveredLink(), QString());
+ QCOMPARE(texteditObject->linkAt(textPos.x(), textPos.y()), QString());
texteditObject->setReadOnly(true);
@@ -2408,12 +2410,14 @@ void tst_qquicktextedit::linkInteraction()
QCOMPARE(spy.last()[0].toString(), link);
QCOMPARE(hover.last()[0].toString(), link);
QCOMPARE(texteditObject->hoveredLink(), link);
+ QCOMPARE(texteditObject->linkAt(linkPos.x(), linkPos.y()), link);
QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
QTRY_COMPARE(spy.count(), 2);
QTRY_COMPARE(hover.count(), 4);
QCOMPARE(hover.last()[0].toString(), QString());
QCOMPARE(texteditObject->hoveredLink(), QString());
+ QCOMPARE(texteditObject->linkAt(textPos.x(), textPos.y()), QString());
}
void tst_qquicktextedit::cursorDelegate_data()
@@ -2663,8 +2667,8 @@ void tst_qquicktextedit::delegateLoading_data()
// import installed
QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
- QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection ";
- QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
+ QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection";
+ QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type";
}
void tst_qquicktextedit::delegateLoading()
diff --git a/tests/auto/quick/qquicktextinput/data/navigation.qml b/tests/auto/quick/qquicktextinput/data/navigation.qml
index 3a7d07b3c7..8df0d151a7 100644
--- a/tests/auto/quick/qquicktextinput/data/navigation.qml
+++ b/tests/auto/quick/qquicktextinput/data/navigation.qml
@@ -5,7 +5,7 @@ Rectangle {
width: 800; height: 600; color: "blue"
- Item {
+ Item {
id: firstItem;
KeyNavigation.right: input
}
@@ -18,7 +18,7 @@ Rectangle {
KeyNavigation.down: lastItem
}
Item {
- id: lastItem
+ id: lastItem
KeyNavigation.left: input
}
}
diff --git a/tests/auto/quick/qquicktextinput/data/validators.qml b/tests/auto/quick/qquicktextinput/data/validators.qml
index 0ba87e0592..b923f69801 100644
--- a/tests/auto/quick/qquicktextinput/data/validators.qml
+++ b/tests/auto/quick/qquicktextinput/data/validators.qml
@@ -25,5 +25,5 @@ Item {
property bool acceptable: acceptableInput
}
}
-
+
}
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 697dba182c..273c0de660 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -229,6 +229,8 @@ private slots:
void maskCharacter_data();
void maskCharacter();
void fixup();
+ void baselineOffset_data();
+ void baselineOffset();
private:
void simulateKey(QWindow *, int key);
@@ -6358,6 +6360,108 @@ void tst_qquicktextinput::fixup()
QCOMPARE(input->text(), QStringLiteral("ok"));
}
+typedef qreal (*ExpectedBaseline)(QQuickTextInput *item);
+Q_DECLARE_METATYPE(ExpectedBaseline)
+
+static qreal expectedBaselineTop(QQuickTextInput *item)
+{
+ QFontMetricsF fm(item->font());
+ return fm.ascent();
+}
+
+static qreal expectedBaselineBottom(QQuickTextInput *item)
+{
+ QFontMetricsF fm(item->font());
+ return item->height() - item->contentHeight() + fm.ascent();
+}
+
+static qreal expectedBaselineCenter(QQuickTextInput *item)
+{
+ QFontMetricsF fm(item->font());
+ return ((item->height() - item->contentHeight()) / 2) + fm.ascent();
+}
+
+static qreal expectedBaselineMultilineBottom(QQuickTextInput *item)
+{
+ QFontMetricsF fm(item->font());
+ return item->height() - item->contentHeight() + fm.ascent();
+}
+
+void tst_qquicktextinput::baselineOffset_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QByteArray>("bindings");
+ QTest::addColumn<qreal>("setHeight");
+ QTest::addColumn<ExpectedBaseline>("expectedBaseline");
+ QTest::addColumn<ExpectedBaseline>("expectedBaselineEmpty");
+
+ QTest::newRow("normal")
+ << "Typography"
+ << QByteArray()
+ << -1.
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("top align")
+ << "Typography"
+ << QByteArray("height: 200; verticalAlignment: Text.AlignTop")
+ << -1.
+ << &expectedBaselineTop
+ << &expectedBaselineTop;
+
+ QTest::newRow("bottom align")
+ << "Typography"
+ << QByteArray("height: 200; verticalAlignment: Text.AlignBottom")
+ << 100.
+ << &expectedBaselineBottom
+ << &expectedBaselineBottom;
+
+ QTest::newRow("center align")
+ << "Typography"
+ << QByteArray("height: 200; verticalAlignment: Text.AlignVCenter")
+ << 100.
+ << &expectedBaselineCenter
+ << &expectedBaselineCenter;
+
+ QTest::newRow("multiline bottom aligned")
+ << "The quick brown fox jumps over the lazy dog"
+ << QByteArray("height: 200; width: 30; verticalAlignment: Text.AlignBottom; wrapMode: TextInput.WordWrap")
+ << -1.
+ << &expectedBaselineMultilineBottom
+ << &expectedBaselineBottom;
+}
+
+void tst_qquicktextinput::baselineOffset()
+{
+ QFETCH(QString, text);
+ QFETCH(QByteArray, bindings);
+ QFETCH(qreal, setHeight);
+ QFETCH(ExpectedBaseline, expectedBaseline);
+ QFETCH(ExpectedBaseline, expectedBaselineEmpty);
+
+ QQmlComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "TextInput {\n"
+ + bindings + "\n"
+ "}", QUrl());
+
+ QScopedPointer<QObject> object(component.create());
+ QQuickTextInput *item = qobject_cast<QQuickTextInput *>(object.data());
+
+ int passes = setHeight >= 0 ? 2 : 1;
+ while (passes--) {
+ QVERIFY(item);
+ QCOMPARE(item->baselineOffset(), expectedBaselineEmpty(item));
+ item->setText(text);
+ QCOMPARE(item->baselineOffset(), expectedBaseline(item));
+ item->setText(QString());
+ QCOMPARE(item->baselineOffset(), expectedBaselineEmpty(item));
+ if (setHeight >= 0)
+ item->setHeight(setHeight);
+ }
+}
+
QTEST_MAIN(tst_qquicktextinput)
#include "tst_qquicktextinput.moc"
diff --git a/tests/auto/quick/qquicktimeline/qquicktimeline.pro b/tests/auto/quick/qquicktimeline/qquicktimeline.pro
new file mode 100644
index 0000000000..3fafc33505
--- /dev/null
+++ b/tests/auto/quick/qquicktimeline/qquicktimeline.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+CONFIG += parallel_test
+TARGET = tst_qquicktimeline
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquicktimeline.cpp
+QT += core-private gui-private qml quick qml-private quick-private testlib
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp b/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp
new file mode 100644
index 0000000000..e9fbb5448c
--- /dev/null
+++ b/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <private/qquicktimeline_p_p.h>
+#include <limits>
+
+class tst_QQuickTimeLine : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void overflow();
+};
+
+void tst_QQuickTimeLine::overflow()
+{
+ QQuickTimeLine timeline;
+ QQuickTimeLineValue value;
+
+ // overflow -> negative time -> assertion failure (QTBUG-35046)
+ QCOMPARE(timeline.accel(value, std::numeric_limits<qreal>::max(), 0.0001f), -1);
+ QCOMPARE(timeline.accel(value, std::numeric_limits<qreal>::max(), 0.0001f, 0.0001f), -1);
+ QCOMPARE(timeline.accelDistance(value, 0.0001f, std::numeric_limits<qreal>::max()), -1);
+}
+
+QTEST_MAIN(tst_QQuickTimeLine)
+
+#include "tst_qquicktimeline.moc"
diff --git a/tests/auto/quick/qquickview/tst_qquickview.cpp b/tests/auto/quick/qquickview/tst_qquickview.cpp
index 02c00ff073..9b4fd2b32f 100644
--- a/tests/auto/quick/qquickview/tst_qquickview.cpp
+++ b/tests/auto/quick/qquickview/tst_qquickview.cpp
@@ -225,7 +225,7 @@ void tst_QQuickView::engine()
QCOMPARE(view3->engine(), view4->engine());
delete view3;
QVERIFY(!view4->engine());
- QTest::ignoreMessage(QtWarningMsg, "QQuickView: invalid qml engine. ");
+ QTest::ignoreMessage(QtWarningMsg, "QQuickView: invalid qml engine.");
view4->setSource(QUrl());
QCOMPARE(view4->status(), QQuickView::Error);
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 107d1d71f7..edde8d2134 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -250,6 +250,18 @@ int TestTouchItem::mousePressNum = 0;
int TestTouchItem::mouseMoveNum = 0;
int TestTouchItem::mouseReleaseNum = 0;
+class EventFilter : public QObject
+{
+public:
+ bool eventFilter(QObject *watched, QEvent *event) {
+ Q_UNUSED(watched);
+ events.append(event->type());
+ return false;
+ }
+
+ QList<int> events;
+};
+
class ConstantUpdateItem : public QQuickItem
{
Q_OBJECT
@@ -331,10 +343,16 @@ private slots:
void crashWhenHoverItemDeleted();
+ void qobjectEventFilter_touch();
+ void qobjectEventFilter_key();
+ void qobjectEventFilter_mouse();
+
#ifndef QT_NO_CURSOR
void cursor();
#endif
+ void animatingSignal();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -923,6 +941,9 @@ void tst_qquickwindow::mouseFiltering()
QTRY_COMPARE(middleItem->mousePressId, 1);
QTRY_COMPARE(bottomItem->mousePressId, 2);
QTRY_COMPARE(topItem->mousePressId, 3);
+
+ // clean up mouse press state for the next tests
+ QTest::mouseRelease(window, Qt::LeftButton, 0, pos);
}
void tst_qquickwindow::qmlCreation()
@@ -1560,6 +1581,97 @@ void tst_qquickwindow::crashWhenHoverItemDeleted()
}
}
+// QTBUG-32004
+void tst_qquickwindow::qobjectEventFilter_touch()
+{
+ QQuickWindow window;
+
+ window.resize(250, 250);
+ window.setPosition(100, 100);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ TestTouchItem *item = new TestTouchItem(window.contentItem());
+ item->setSize(QSizeF(150, 150));
+
+ EventFilter eventFilter;
+ item->installEventFilter(&eventFilter);
+
+ QPointF pos(10, 10);
+
+ // press single point
+ QTest::touchEvent(&window, touchDevice).press(0, item->mapToScene(pos).toPoint(), &window);
+
+ QCOMPARE(eventFilter.events.count(), 1);
+ QCOMPARE(eventFilter.events.first(), (int)QEvent::TouchBegin);
+}
+
+// QTBUG-32004
+void tst_qquickwindow::qobjectEventFilter_key()
+{
+ QQuickWindow window;
+
+ window.resize(250, 250);
+ window.setPosition(100, 100);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ TestTouchItem *item = new TestTouchItem(window.contentItem());
+ item->setSize(QSizeF(150, 150));
+ item->setFocus(true);
+
+ EventFilter eventFilter;
+ item->installEventFilter(&eventFilter);
+
+ QTest::keyPress(&window, Qt::Key_A);
+
+ // NB: It may also receive some QKeyEvent(ShortcutOverride) which we're not interested in
+ QVERIFY(eventFilter.events.contains((int)QEvent::KeyPress));
+ eventFilter.events.clear();
+
+ QTest::keyRelease(&window, Qt::Key_A);
+
+ QVERIFY(eventFilter.events.contains((int)QEvent::KeyRelease));
+}
+
+// QTBUG-32004
+void tst_qquickwindow::qobjectEventFilter_mouse()
+{
+ QQuickWindow window;
+
+ window.resize(250, 250);
+ window.setPosition(100, 100);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ TestTouchItem *item = new TestTouchItem(window.contentItem());
+ item->setSize(QSizeF(150, 150));
+
+ EventFilter eventFilter;
+ item->installEventFilter(&eventFilter);
+
+ QPoint point = item->mapToScene(QPointF(10, 10)).toPoint();
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, point);
+
+ QVERIFY(eventFilter.events.contains((int)QEvent::MouseButtonPress));
+
+ // clean up mouse press state for the next tests
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, point);
+}
+
+void tst_qquickwindow::animatingSignal()
+{
+ QQuickWindow window;
+ window.setGeometry(100, 100, 300, 200);
+
+ QSignalSpy spy(&window, SIGNAL(afterAnimating()));
+
+ window.show();
+ QTRY_VERIFY(window.isExposed());
+
+ QTRY_VERIFY(spy.count() > 1);
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
index 12ae3c273f..a3cfa0011a 100644
--- a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
+++ b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
@@ -744,9 +744,9 @@ void tst_qquickxmllistmodel::noKeysValueChanges()
QQmlComponent component(&engine, testFileUrl("roleKeys.qml"));
QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
QVERIFY(model != 0);
-
+
QString xml;
-
+
xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
model->setProperty("xml",xml);
QTRY_COMPARE(model->rowCount(), 2);
@@ -820,11 +820,11 @@ void tst_qquickxmllistmodel::threading()
QQmlComponent component(&engine, testFileUrl("roleKeys.qml"));
QAbstractItemModel *m1 = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(m1 != 0);
+ QVERIFY(m1 != 0);
QAbstractItemModel *m2 = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(m2 != 0);
+ QVERIFY(m2 != 0);
QAbstractItemModel *m3 = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(m3 != 0);
+ QVERIFY(m3 != 0);
for (int dataCount=0; dataCount<xmlDataCount; dataCount++) {
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 92bbe7e0fb..6c163d9619 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -26,6 +26,7 @@ PRIVATETESTS += \
qquickstyledtext \
qquickstates \
qquicksystempalette \
+ qquicktimeline \
qquickxmllistmodel
# This test requires the xmlpatterns module
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index 7d1590e5f6..06338e09e2 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -57,18 +57,18 @@ public:
QImage runTest(const QString &fileName)
{
- QQuickView view;
- view.setSource(testFileUrl(fileName));
+ QQuickView view(&outerWindow);
view.setResizeMode(QQuickView::SizeViewToRootObject);
- const QRect screenGeometry = view.screen()->availableGeometry();
- const QSize size = view.size();
- const QPoint offset = QPoint(size.width() / 2, size.height() / 2);
- view.setFramePosition(screenGeometry.center() - offset);
- view.showNormal();
+ view.setSource(testFileUrl(fileName));
+ view.setVisible(true);
QTest::qWaitForWindowExposed(&view);
return view.grabWindow();
}
+ //It is important for platforms that only are able to show fullscreen windows
+ //to have a container for the window that is painted on.
+ QQuickWindow outerWindow;
+
private slots:
void renderOrder();
void messUpState();
@@ -187,6 +187,8 @@ tst_rendernode::tst_rendernode()
{
qmlRegisterType<ClearItem>("Test", 1, 0, "ClearItem");
qmlRegisterType<MessUpItem>("Test", 1, 0, "MessUpItem");
+ outerWindow.showNormal();
+ outerWindow.setGeometry(0,0,400,400);
}
static bool fuzzyCompareColor(QRgb x, QRgb y, QByteArray *errorMessage)
diff --git a/tests/auto/quick/scenegraph/data/blacknwhite.png b/tests/auto/quick/scenegraph/data/blacknwhite.png
new file mode 100644
index 0000000000..efbc61e79d
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/blacknwhite.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/mipmap_large.png b/tests/auto/quick/scenegraph/data/mipmap_large.png
new file mode 100644
index 0000000000..9cb0fc7de1
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/mipmap_large.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/mipmap_small.png b/tests/auto/quick/scenegraph/data/mipmap_small.png
new file mode 100644
index 0000000000..dc5216fb6c
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/mipmap_small.png
Binary files differ
diff --git a/src/imports/dialogs/qquickfontdialog_p.h b/tests/auto/quick/scenegraph/data/render_ImageFiltering.qml
index a8e2d82e6f..f91bc59931 100644
--- a/src/imports/dialogs/qquickfontdialog_p.h
+++ b/tests/auto/quick/scenegraph/data/render_ImageFiltering.qml
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,42 +39,35 @@
**
****************************************************************************/
-#ifndef QQUICKFONTDIALOG_P_H
-#define QQUICKFONTDIALOG_P_H
+import QtQuick 2.2
-//
-// 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.
-//
+/*
+ The test verifies that batching does not interfere with overlapping
+ regions.
-#include "qquickabstractfontdialog_p.h"
+ #samples: 8
+ PixelPos R G B Error-tolerance
+ #final: 10 10 0.0 0.0 0.0 0.0
+ #final: 20 10 1.0 1.0 1.0 0.0
+ #final: 30 10 0.0 0.0 0.0 0.0
+ #final: 40 10 0.5 0.5 0.5 0.1
+ #final: 50 10 0.0 0.0 0.0 0.0
+ #final: 60 10 1.0 1.0 1.0 0.0
+ #final: 70 10 0.0 0.0 0.0 0.0
+ #final: 80 10 0.5 0.5 0.5 0.1
+*/
-QT_BEGIN_NAMESPACE
-
-class QQuickFontDialog : public QQuickAbstractFontDialog
+RenderTestBase
{
- Q_OBJECT
- Q_PROPERTY(QObject* implementation READ qmlImplementation WRITE setQmlImplementation DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "implementation")
-
-public:
- explicit QQuickFontDialog(QObject *parent = 0);
- ~QQuickFontDialog();
-
-protected:
- virtual QPlatformFontDialogHelper *helper() { return 0; }
-
- Q_DISABLE_COPY(QQuickFontDialog)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickFontDialog *)
+ Item {
+ x: 10
+ y: 10
+ scale: 10
+ Image { x: 0; source: "blacknwhite.png"; smooth: false }
+ Image { x: 2; source: "blacknwhite.png"; smooth: true }
+ Image { x: 4; source: "blacknwhite.png"; smooth: false }
+ Image { x: 6; source: "blacknwhite.png"; smooth: true }
+ }
-#endif // QQUICKFONTDIALOG_P_H
+ finalStageComplete: true
+}
diff --git a/src/imports/dialogs-private/dialogsprivateplugin.cpp b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
index f920df30f3..0a6195fc1f 100644
--- a/src/imports/dialogs-private/dialogsprivateplugin.cpp
+++ b/tests/auto/quick/scenegraph/data/render_Mipmap.qml
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,28 +39,39 @@
**
****************************************************************************/
-#include <QtQml/qqmlextensionplugin.h>
-#include <QtQml/qqml.h>
-#include "qquickwritingsystemlistmodel_p.h"
-#include "qquickfontlistmodel_p.h"
+import QtQuick 2.3
-QT_BEGIN_NAMESPACE
+/*
+ The test verifies that scaled down mipmapped images contains
+ colors from all pixels.
-class QtQuick2DialogsPrivatePlugin : public QQmlExtensionPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
-
-public:
- virtual void registerTypes(const char *uri)
- {
- Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Dialogs.Private"));
+ #samples: 2
+ PixelPos R G B Error-tolerance
+ #final: 0 0 0.33 0.33 0.33 0.1
+ #final: 1 0 0.33 0.33 0.33 0.1
+*/
- qmlRegisterType<QQuickWritingSystemListModel>(uri, 1, 1, "WritingSystemListModel");
- qmlRegisterType<QQuickFontListModel>(uri, 1, 1, "FontListModel");
+RenderTestBase
+{
+ Image {
+ x: 0
+ y: 0
+ transformOrigin: Item.TopLeft
+ source: "mipmap_small.png"
+ mipmap: true
+ smooth: false
+ scale: 1 / width;
}
-};
-QT_END_NAMESPACE
+ Image {
+ x: 1
+ y: 0
+ transformOrigin: Item.TopLeft
+ source: "mipmap_large.png"
+ mipmap: true
+ smooth: false
+ scale: 1 / width;
+ }
-#include "dialogsprivateplugin.moc"
+ onEnterFinalStage: finalStageComplete = true;
+}
diff --git a/tests/auto/quick/scenegraph/scenegraph.pro b/tests/auto/quick/scenegraph/scenegraph.pro
index 1aa73ca60a..0ad13a086f 100644
--- a/tests/auto/quick/scenegraph/scenegraph.pro
+++ b/tests/auto/quick/scenegraph/scenegraph.pro
@@ -12,4 +12,5 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
OTHER_FILES += \
data/render_OutOfFloatRange.qml \
- data/simple.qml
+ data/simple.qml \
+ data/render_ImageFiltering.qml
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 780d5a97db..5d393fedb5 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -326,6 +326,8 @@ void tst_SceneGraph::render_data()
<< "data/render_BreakOpacityBatch.qml"
<< "data/render_OutOfFloatRange.qml"
<< "data/render_StackingOrder.qml"
+ << "data/render_Mipmap.qml"
+ << "data/render_ImageFiltering.qml"
;
QRegExp sampleCount("#samples: *(\\d+)");
diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp
index 20df0c12f5..d3de584084 100644
--- a/tests/auto/shared/testhttpserver.cpp
+++ b/tests/auto/shared/testhttpserver.cpp
@@ -127,7 +127,7 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod
QFile expectFile(expect.toLocalFile());
if (!expectFile.open(QIODevice::ReadOnly)) return false;
-
+
QFile replyFile(reply.toLocalFile());
if (!replyFile.open(QIODevice::ReadOnly)) return false;
@@ -325,7 +325,7 @@ void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data)
QByteArray total = dataCache[socket] + data;
dataCache[socket] = total;
-
+
if (total.contains("\n\r\n")) {
bool close = true;
@@ -342,7 +342,7 @@ void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data)
}
dataCache.remove(socket);
- if (close)
+ if (close)
socket->disconnectFromHost();
}
}
diff --git a/tests/benchmarks/qml/binding/data/localproperty.txt b/tests/benchmarks/qml/binding/data/localproperty.txt
index c7ca0efdb4..d1b1f4386a 100644
--- a/tests/benchmarks/qml/binding/data/localproperty.txt
+++ b/tests/benchmarks/qml/binding/data/localproperty.txt
@@ -1,5 +1,5 @@
import Test 1.0
-MyQmlObject {
+MyQmlObject {
result: ###
}
diff --git a/tests/benchmarks/qml/javascript/testtypes.h b/tests/benchmarks/qml/javascript/testtypes.h
index 99781fc797..05b1c7ef9c 100644
--- a/tests/benchmarks/qml/javascript/testtypes.h
+++ b/tests/benchmarks/qml/javascript/testtypes.h
@@ -44,7 +44,7 @@
#include <QtCore/qobject.h>
-class TestObject : public QObject
+class TestObject : public QObject
{
Q_OBJECT
Q_PROPERTY(int intValue READ intValue);
@@ -58,7 +58,7 @@ public:
private:
QString m_string;
-};
+};
void registerTypes();
diff --git a/tests/benchmarks/qml/painting/paintbenchmark.cpp b/tests/benchmarks/qml/painting/paintbenchmark.cpp
index 1fc7813c04..672bed4c10 100644
--- a/tests/benchmarks/qml/painting/paintbenchmark.cpp
+++ b/tests/benchmarks/qml/painting/paintbenchmark.cpp
@@ -351,8 +351,8 @@ public:
last = elapsed;
}
QPainter p(this);
- p.fillRect(rect(), Qt::white);
- p.setPen(Qt::black);
+ p.fillRect(rect(), Qt::white);
+ p.setPen(Qt::black);
QTime drawTimer;
drawTimer.start();
testFunc(p);
diff --git a/tests/benchmarks/qml/qmltime/qmltime.cpp b/tests/benchmarks/qml/qmltime/qmltime.cpp
index bae0b51824..d6b73ed5f4 100644
--- a/tests/benchmarks/qml/qmltime/qmltime.cpp
+++ b/tests/benchmarks/qml/qmltime/qmltime.cpp
@@ -111,10 +111,10 @@ void Timer::run(uint iterations)
QObject *o = m_component->create(&context);
QGraphicsObject *go = qobject_cast<QGraphicsObject *>(o);
- if (m_willparent && go)
+ if (m_willparent && go)
go->setParentItem(&m_item);
delete o;
-
+
runTest(&context, iterations);
}
@@ -135,7 +135,7 @@ void Timer::runTest(QQmlContext *context, uint iterations)
for (uint ii = 0; ii < iterations; ++ii) {
QObject *o = m_component->create(context);
QGraphicsObject *go = qobject_cast<QGraphicsObject *>(o);
- if (m_willparent && go)
+ if (m_willparent && go)
go->setParentItem(&m_item);
delete o;
}
diff --git a/tests/benchmarks/qml/qmltime/qmltime.pro b/tests/benchmarks/qml/qmltime/qmltime.pro
index c151b8d10f..4e3e9471a4 100644
--- a/tests/benchmarks/qml/qmltime/qmltime.pro
+++ b/tests/benchmarks/qml/qmltime/qmltime.pro
@@ -4,6 +4,6 @@ TARGET = qmltime
QT += qml widgets testlib
macx:CONFIG -= app_bundle
-SOURCES += qmltime.cpp
+SOURCES += qmltime.cpp
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/benchmarks/qml/qqmlmetaproperty/qqmlmetaproperty.pro b/tests/benchmarks/qml/qqmlmetaproperty/qqmlmetaproperty.pro
index e71f16aecb..ce66e1e51f 100644
--- a/tests/benchmarks/qml/qqmlmetaproperty/qqmlmetaproperty.pro
+++ b/tests/benchmarks/qml/qqmlmetaproperty/qqmlmetaproperty.pro
@@ -4,7 +4,7 @@ TARGET = tst_qqmlmetaproperty
QT += qml testlib
macx:CONFIG -= app_bundle
-SOURCES += tst_qqmlmetaproperty.cpp
+SOURCES += tst_qqmlmetaproperty.cpp
# Define SRCDIR equal to test's source directory
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/benchmarks/qml/script/data/slot_complex.qml b/tests/benchmarks/qml/script/data/slot_complex.qml
index 4e467da901..ffc9e2f98f 100644
--- a/tests/benchmarks/qml/script/data/slot_complex.qml
+++ b/tests/benchmarks/qml/script/data/slot_complex.qml
@@ -47,7 +47,7 @@ TestObject {
var a = 1;
while (n > 0) {
a = a * n;
- n--;
+ n--;
}
return a;
}
diff --git a/tests/manual/httpserver/httpserver.pro b/tests/manual/httpserver/httpserver.pro
new file mode 100644
index 0000000000..2a6c32f1cf
--- /dev/null
+++ b/tests/manual/httpserver/httpserver.pro
@@ -0,0 +1,13 @@
+QT = core network
+
+TARGET = httpserver
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+SERVER = $$PWD/../../auto/shared
+INCLUDEPATH += $$SERVER
+
+SOURCES += main.cpp $$SERVER/testhttpserver.cpp
+HEADERS += $$SERVER/testhttpserver.h
diff --git a/tests/manual/httpserver/main.cpp b/tests/manual/httpserver/main.cpp
new file mode 100644
index 0000000000..ea729547ce
--- /dev/null
+++ b/tests/manual/httpserver/main.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <testhttpserver.h>
+
+#include <QCoreApplication>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+#include <QDebug>
+#include <QDir>
+#include <QFileInfo>
+
+#include <iostream>
+#include <iterator>
+#include <algorithm>
+
+inline std::wostream &operator<<(std::wostream &str, const QString &s)
+{
+#ifdef Q_OS_WIN
+ str << reinterpret_cast<const wchar_t *>(s.utf16());
+#else
+ str << s.toStdWString();
+#endif
+ return str;
+}
+
+enum { defaultPort = 14457 };
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+ QCoreApplication::setApplicationName("HttpServer");
+ QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+
+ QCommandLineParser commandLineParser;
+ commandLineParser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+ commandLineParser.setApplicationDescription(QStringLiteral("HTTP Test server"));
+ commandLineParser.addHelpOption();
+ commandLineParser.addVersionOption();
+
+ QCommandLineOption portOption(QStringLiteral("p"),
+ QStringLiteral("Port (default: ") + QString::number(defaultPort) + QLatin1Char(')'),
+ QStringLiteral("port"));
+
+ commandLineParser.addOption(portOption);
+
+ commandLineParser.addPositionalArgument(QStringLiteral("[directory]"),
+ QStringLiteral("Directory to serve."));
+
+ commandLineParser.process(a);
+
+ const QStringList args = commandLineParser.positionalArguments();
+ if (args.size() != 1)
+ commandLineParser.showHelp(1);
+
+ const QString directory = QDir::cleanPath(args.front());
+ if (!QFileInfo(directory).isDir()) {
+ std::wcerr << '"' << QDir::toNativeSeparators(directory) << "\" is not a directory.\n";
+ return -1;
+ }
+
+ unsigned short port = defaultPort;
+ if (commandLineParser.isSet(portOption)) {
+ const QString portV = commandLineParser.value(portOption);
+ bool ok;
+ port = portV.toUShort(&ok);
+ if (!ok) {
+ std::wcerr << portV << " is not a valid port number.\n";
+ return -1;
+ }
+ }
+
+ std::wcout << "Serving \"" << QDir::toNativeSeparators(directory)
+ << "\":\n\n" << QDir(directory).entryList(QDir::Files).join(QLatin1Char('\n'))
+ << "\n\non http://localhost:" << port << '\n';
+
+ TestHTTPServer server(port);
+ server.serveDirectory(directory);
+
+ return a.exec();
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_sinhala.qml b/tests/manual/scenegraph_lancelot/data/text/text_sinhala.qml
new file mode 100644
index 0000000000..e74b72da92
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_sinhala.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ Text {
+ anchors.fill: parent
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ font.family: "Arial"
+ font.pixelSize: 20
+ text: "සිංහළ අකුරු අබලං"
+ }
+}
+
+
diff --git a/tests/manual/v4/TestExpectations b/tests/manual/v4/TestExpectations
index 93a87f9ccc..49f107452a 100644
--- a/tests/manual/v4/TestExpectations
+++ b/tests/manual/v4/TestExpectations
@@ -2,6 +2,18 @@
# uses octal number
15.2.3.6-2-17-1 failing
+# these fail after the update to Unicode 6.3.
+# the reason is that u+180e changed type from whitespace to control
+S9.3.1_A2
+S9.3.1_A3_T1
+S9.3.1_A3_T2
+S15.1.2.2_A2_T10
+S15.1.2.3_A2_T10
+15.5.4.20-3-2
+15.5.4.20-3-3
+15.5.4.20-3-4
+15.5.4.20-3-5
+15.5.4.20-3-6
10.4.3-1-106 failing
11.2.3-3_3 failing
@@ -16,4 +28,4 @@ S15.2.4.4_A14 failing
Sbp_12.5_A9_T3 failing
Sbp_12.6.1_A13_T3 failing
Sbp_12.6.2_A13_T3 failing
-Sbp_12.6.4_A13_T3 failing \ No newline at end of file
+Sbp_12.6.4_A13_T3 failing
diff --git a/tests/manual/v4/sparsearraytest.js b/tests/manual/v4/sparsearraytest.js
new file mode 100644
index 0000000000..3d7adfe903
--- /dev/null
+++ b/tests/manual/v4/sparsearraytest.js
@@ -0,0 +1,55 @@
+var max
+for (max = 2; max < 100; ++max) {
+ var arr = [];
+ // force a sparse array
+ Object.defineProperty(arr, "0", {
+ get: function () {
+ return 0;
+ },
+ configurable: true
+ });
+ var i;
+ var j;
+ for (i = 1; i < max; ++i)
+ arr[i] = i;
+ for (i = 1; i < max; i += 2) {
+ delete arr[i];
+ for (j = 0; j < max; ++j) {
+ if (j <= i && (j %2)) {
+ if (arr[j] != undefined)
+ throw "err1"
+ } else {
+ if (arr[j] != j)
+ throw "err2"
+ }
+ }
+ }
+}
+
+for (max = 2; max < 100; ++max) {
+ var arr = [];
+ // force a sparse array
+ Object.defineProperty(arr, "0", {
+ get: function () {
+ return 0;
+ },
+ configurable: true
+ });
+
+ var i;
+ var j;
+ for (i = 1; i < max; ++i)
+ arr[i] = i;
+ for (i = 0; i < max; i += 2) {
+ delete arr[i];
+ for (j = 0; j < max; ++j) {
+ if (j <= i && !(j %2)) {
+ if (arr[j] != undefined)
+ throw "err1 " + i + " " + j + " " + arr[j]
+ } else {
+ if (arr[j] != j)
+ throw "err2 " + j
+ }
+ }
+ }
+}
diff --git a/tests/manual/v4/test262.py b/tests/manual/v4/test262.py
index dbc6049a1a..acd467ea23 100755
--- a/tests/manual/v4/test262.py
+++ b/tests/manual/v4/test262.py
@@ -162,9 +162,9 @@ def BuildOptions():
help="Print summary after running tests")
result.add_option("--full-summary", default=False, action="store_true",
help="Print summary and test output after running tests")
- result.add_option("--strict_only", default=False, action="store_true",
+ result.add_option("--strict_only", default=False, action="store_true",
help="Test only strict mode")
- result.add_option("--non_strict_only", default=False, action="store_true",
+ result.add_option("--non_strict_only", default=False, action="store_true",
help="Test only non-strict mode")
result.add_option("--parallel", default=False, action="store_true",
help="Run tests in parallel")
@@ -174,7 +174,7 @@ def BuildOptions():
help="Update test expectations fail when a test passes that was expected to fail")
# TODO: Once enough tests are made strict compat, change the default
# to "both"
- result.add_option("--unmarked_default", default="non_strict",
+ result.add_option("--unmarked_default", default="non_strict",
help="default mode for tests of unspecified strictness")
return result
@@ -293,7 +293,7 @@ class TestCase(object):
del testRecord["header"]
del testRecord["commentary"]
self.testRecord = testRecord;
-
+
def GetName(self):
return path.join(*self.name)
@@ -570,8 +570,8 @@ def Main():
parser = BuildOptions()
(options, args) = parser.parse_args()
ValidateOptions(options)
- test_suite = TestSuite(options.tests,
- options.strict_only,
+ test_suite = TestSuite(options.tests,
+ options.strict_only,
options.non_strict_only,
options.unmarked_default,
options.with_test_expectations)
diff --git a/tests/manual/v4/v8-bench.js b/tests/manual/v4/v8-bench.js
index baa6274136..41a04fa29a 100644
--- a/tests/manual/v4/v8-bench.js
+++ b/tests/manual/v4/v8-bench.js
@@ -4339,7 +4339,7 @@ function initRuntime() {
tmp = tmp.replace(/\n/g, "<br />");
tmp = tmp.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp");
return tmp;
-
+
}
document.write("<div id='stdout'></div>");
@@ -4865,7 +4865,7 @@ sc_Pair.prototype.sc_toWriteOrDisplayString = function(writeOrDisplay) {
} else // current.cdr == null
break;
}
-
+
res += ")";
return res;
@@ -5205,7 +5205,7 @@ function sc_reverseAppendBang(l1, l2) {
}
return res;
}
-
+
function sc_dualAppend(l1, l2) {
if (l1 === null) return l2;
if (l2 === null) return l1;
@@ -6639,7 +6639,7 @@ sc_Tokenizer.prototype.nextToken = function() {
if (c === "(")
return new sc_Token(14/*VECTOR_BEGIN*/);
-
+
if (c === "\\") { // character
var tmp = ""
while (!isWhitespaceOrEOF(port.peekChar()))
@@ -6684,7 +6684,7 @@ sc_Tokenizer.prototype.nextToken = function() {
} else
return new sc_Token(13/*ERROR*/, "bad #-pattern5");
}
-
+
};
skipWhitespaceAndComments();
@@ -6763,7 +6763,7 @@ sc_Reader.prototype.read = function() {
+ " " + par.type;
else
return sc_reverseAppendBang(res, cdr);
-
+
default:
res = sc_cons(this.read(), res);
@@ -6782,7 +6782,7 @@ sc_Reader.prototype.read = function() {
case 2/*CLOSE_PAR*/:
tokenizer.readToken();
return a;
-
+
default:
a.push(this.read());
}
@@ -6794,7 +6794,7 @@ sc_Reader.prototype.read = function() {
this.backref[nb] = tmp;
return tmp;
};
-
+
function readReference(nb) {
if (nb in this.backref)
return this.backref[nb];
diff --git a/tools/qmljs/main.cpp b/tools/qmljs/main.cpp
index 9c10851b21..f13f42881c 100644
--- a/tools/qmljs/main.cpp
+++ b/tools/qmljs/main.cpp
@@ -71,8 +71,9 @@ using namespace QV4;
struct Print: FunctionObject
{
+ V4_OBJECT
Print(ExecutionContext *scope): FunctionObject(scope, QStringLiteral("print")) {
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static ReturnedValue call(Managed *, CallData *callData)
@@ -86,29 +87,26 @@ struct Print: FunctionObject
std::cout << std::endl;
return Encode::undefined();
}
-
- static const ManagedVTable static_vtbl;
};
-DEFINE_MANAGED_VTABLE(Print);
+DEFINE_OBJECT_VTABLE(Print);
struct GC: public FunctionObject
{
+ V4_OBJECT
GC(ExecutionContext* scope)
: FunctionObject(scope, QStringLiteral("gc"))
{
- setVTable(&static_vtbl);
+ setVTable(staticVTable());
}
static ReturnedValue call(Managed *m, CallData *)
{
m->engine()->memoryManager->runGC();
return Encode::undefined();
}
-
- static const ManagedVTable static_vtbl;
};
-DEFINE_MANAGED_VTABLE(GC);
+DEFINE_OBJECT_VTABLE(GC);
} // builtins
@@ -176,12 +174,12 @@ int main(int argc, char *argv[])
switch (mode) {
case use_masm:
case use_moth: {
- QQmlJS::EvalISelFactory* iSelFactory = 0;
+ QV4::EvalISelFactory* iSelFactory = 0;
if (mode == use_moth) {
- iSelFactory = new QQmlJS::Moth::ISelFactory;
+ iSelFactory = new QV4::Moth::ISelFactory;
#ifdef V4_ENABLE_JIT
} else {
- iSelFactory = new QQmlJS::MASM::ISelFactory;
+ iSelFactory = new QV4::JIT::ISelFactory;
#endif // V4_ENABLE_JIT
}
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index d53005109e..e53d8c2800 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -684,8 +684,26 @@ void printUsage(const QString &appName)
appName)) << std::endl;
}
+inline std::wostream &operator<<(std::wostream &str, const QString &s)
+{
+#ifdef Q_OS_WIN
+ str << reinterpret_cast<const wchar_t *>(s.utf16());
+#else
+ str << s.toStdWString();
+#endif
+ return str;
+}
+
+void printDebugMessage(QtMsgType, const QMessageLogContext &, const QString &msg)
+{
+ std::wcerr << msg << std::endl;
+ // In case of QtFatalMsg the calling code will abort() when appropriate.
+}
+
int main(int argc, char *argv[])
{
+ // The default message handler might not print to console on some systems. Enforce this.
+ qInstallMessageHandler(printDebugMessage);
#ifdef Q_OS_UNIX
// qmldump may crash, but we don't want any crash handlers to pop up
// therefore we intercept the segfault and just exit() ourselves
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index 5c225948dd..67af71c59f 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -9,7 +9,7 @@ SOURCES += \
HEADERS += \
qmlstreamwriter.h
-mac {
+macx {
# Prevent qmlplugindump from popping up in the dock when launched.
# We embed the Info.plist file, so the application doesn't need to
# be a bundle.
diff --git a/tools/qmlprofiler/qpacketprotocol.cpp b/tools/qmlprofiler/qpacketprotocol.cpp
index e0fe08740d..b8017fad60 100644
--- a/tools/qmlprofiler/qpacketprotocol.cpp
+++ b/tools/qmlprofiler/qpacketprotocol.cpp
@@ -235,7 +235,7 @@ QPacketProtocol::~QPacketProtocol()
/*!
Returns the maximum packet size allowed. By default this is
2,147,483,647 bytes.
-
+
If a packet claiming to be larger than the maximum packet size is received,
the QPacketProtocol::invalidPacket() signal is emitted.
diff --git a/tools/qmlprofiler/qqmldebugclient.cpp b/tools/qmlprofiler/qqmldebugclient.cpp
index 3ba8b334ff..334fc7297f 100644
--- a/tools/qmlprofiler/qqmldebugclient.cpp
+++ b/tools/qmlprofiler/qqmldebugclient.cpp
@@ -335,7 +335,7 @@ QQmlDebugClientPrivate::QQmlDebugClientPrivate()
{
}
-QQmlDebugClient::QQmlDebugClient(const QString &name,
+QQmlDebugClient::QQmlDebugClient(const QString &name,
QQmlDebugConnection *parent)
: QObject(parent),
d(new QQmlDebugClientPrivate)