aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules2
-rw-r--r--.qmake.conf2
-rw-r--r--examples/quick/demos/calqlatr/calqlatr.pro19
-rw-r--r--examples/quick/demos/calqlatr/calqlatr.qml173
-rw-r--r--examples/quick/demos/calqlatr/calqlatr.qmlproject16
-rw-r--r--examples/quick/demos/calqlatr/calqlatr.qrc12
-rw-r--r--examples/quick/demos/calqlatr/content/Button.qml104
-rw-r--r--examples/quick/demos/calqlatr/content/Display.qml203
-rw-r--r--examples/quick/demos/calqlatr/content/NumberPad.qml81
-rw-r--r--examples/quick/demos/calqlatr/content/calculator.js161
-rw-r--r--examples/quick/demos/calqlatr/content/images/paper-edge-left.pngbin12401 -> 0 bytes
-rw-r--r--examples/quick/demos/calqlatr/content/images/paper-edge-right.pngbin12967 -> 0 bytes
-rw-r--r--examples/quick/demos/calqlatr/content/images/paper-grip.pngbin298 -> 0 bytes
-rw-r--r--examples/quick/demos/calqlatr/doc/images/qtquick-demo-calqlatr.pngbin37120 -> 0 bytes
-rw-r--r--examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc195
-rw-r--r--examples/quick/demos/calqlatr/main.cpp51
-rw-r--r--examples/quick/demos/clocks/clocks.pro14
-rw-r--r--examples/quick/demos/clocks/clocks.qml98
-rw-r--r--examples/quick/demos/clocks/clocks.qmlproject8
-rw-r--r--examples/quick/demos/clocks/clocks.qrc15
-rw-r--r--examples/quick/demos/clocks/content/Clock.qml150
-rw-r--r--examples/quick/demos/clocks/content/arrow.pngbin692 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/background.pngbin46895 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/center.pngbin765 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/clock-night.pngbin23359 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/clock.pngbin20653 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/hour.pngbin518 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/minute.pngbin528 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/quit.pngbin583 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/content/second.pngbin231 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/doc/images/qtquick-demo-clocks-small.pngbin26067 -> 0 bytes
-rw-r--r--examples/quick/demos/clocks/doc/src/clocks.qdoc127
-rw-r--r--examples/quick/demos/clocks/main.cpp51
-rw-r--r--examples/quick/demos/demos.pro11
-rw-r--r--examples/quick/demos/maroon/content/BuildButton.qml100
-rw-r--r--examples/quick/demos/maroon/content/GameCanvas.qml250
-rw-r--r--examples/quick/demos/maroon/content/GameOverScreen.qml125
-rw-r--r--examples/quick/demos/maroon/content/InfoBar.qml94
-rw-r--r--examples/quick/demos/maroon/content/NewGameScreen.qml121
-rw-r--r--examples/quick/demos/maroon/content/SoundEffect.qml62
-rw-r--r--examples/quick/demos/maroon/content/audio/bomb-action.wavbin20972 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/catch-action.wavbin13274 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/catch.wavbin8638 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/currency.wavbin15790 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/factory-action.wavbin4936 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/melee-action.wavbin17798 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/projectile-action.wavbin2562 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/audio/shooter-action.wavbin27554 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/background.pngbin5802 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/bomb-action.pngbin23974 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/bomb-idle.pngbin12238 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/bomb.pngbin4067 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/button-help.pngbin8916 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/button-play.pngbin13945 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/catch-action.pngbin6760 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/catch.pngbin4771 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/cloud.pngbin3398 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/currency.pngbin1889 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/dialog-bomb.pngbin3751 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/dialog-factory.pngbin3946 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/dialog-melee.pngbin4392 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/dialog-pointer.pngbin911 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/dialog-shooter.pngbin3737 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/dialog.pngbin3362 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/factory-action.pngbin22440 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/factory-idle.pngbin12729 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/factory.pngbin4138 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/grid.pngbin2830 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/help.pngbin38255 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/lifes.pngbin1675 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/logo-bubble.pngbin7706 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/logo-fish.pngbin3477 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/logo.pngbin18332 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/melee-action.pngbin7797 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/melee-idle.pngbin22832 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/melee.pngbin4046 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/mob-idle.pngbin6181 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/mob.pngbin2391 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/points.pngbin1561 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/projectile-action.pngbin6257 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/projectile.pngbin801 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/scores.pngbin1535 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/shooter-action.pngbin18121 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/shooter-idle.pngbin11929 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/shooter.pngbin4137 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/sunlight.pngbin248412 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/text-1.pngbin2777 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/text-2.pngbin4959 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/text-3.pngbin5063 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/text-blank.pngbin1326 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/text-gameover.pngbin1515 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/text-go.pngbin4230 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/gfx/wave.pngbin2763 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/content/logic.js274
-rw-r--r--examples/quick/demos/maroon/content/mobs/MobBase.qml272
-rw-r--r--examples/quick/demos/maroon/content/towers/Bomb.qml143
-rw-r--r--examples/quick/demos/maroon/content/towers/Factory.qml124
-rw-r--r--examples/quick/demos/maroon/content/towers/Melee.qml93
-rw-r--r--examples/quick/demos/maroon/content/towers/Ranged.qml138
-rw-r--r--examples/quick/demos/maroon/content/towers/TowerBase.qml82
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-1.pngbin73390 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-2.pngbin61303 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpgbin25541 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpgbin79678 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpgbin27911 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpgbin59198 -> 0 bytes
-rw-r--r--examples/quick/demos/maroon/doc/src/maroon.qdoc889
-rw-r--r--examples/quick/demos/maroon/main.cpp51
-rw-r--r--examples/quick/demos/maroon/maroon.pro9
-rw-r--r--examples/quick/demos/maroon/maroon.qml245
-rw-r--r--examples/quick/demos/maroon/maroon.qmlproject16
-rw-r--r--examples/quick/demos/maroon/maroon.qrc71
-rw-r--r--examples/quick/demos/photosurface/doc/images/qtquick-demo-photosurface-small.pngbin47271 -> 0 bytes
-rw-r--r--examples/quick/demos/photosurface/doc/src/photosurface.qdoc157
-rw-r--r--examples/quick/demos/photosurface/main.cpp139
-rw-r--r--examples/quick/demos/photosurface/photosurface.pro13
-rw-r--r--examples/quick/demos/photosurface/photosurface.qml286
-rw-r--r--examples/quick/demos/photosurface/photosurface.qmlproject20
-rw-r--r--examples/quick/demos/photosurface/photosurface.qrc6
-rw-r--r--examples/quick/demos/photosurface/resources/folder.pngbin5851 -> 0 bytes
-rw-r--r--examples/quick/demos/photosurface/resources/icon.pngbin35894 -> 0 bytes
-rw-r--r--examples/quick/demos/photosurface/resources/photosurface.icnsbin47407 -> 0 bytes
-rw-r--r--examples/quick/demos/photosurface/resources/photosurface.icobin38623 -> 0 bytes
-rw-r--r--examples/quick/demos/photosurface/resources/photosurface.rc32
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml157
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml59
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/Button.qml81
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/EditableButton.qml94
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml198
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/ProgressBar.qml66
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/RssModel.qml66
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/Tag.qml100
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/images/box-shadow.pngbin371 -> 0 bytes
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/images/busy.pngbin1564 -> 0 bytes
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/images/cardboard.pngbin8477 -> 0 bytes
-rw-r--r--examples/quick/demos/photoviewer/PhotoViewerCore/script/script.js27
-rw-r--r--examples/quick/demos/photoviewer/doc/images/qtquick-demo-photoviewer-small.pngbin73662 -> 0 bytes
-rw-r--r--examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc326
-rw-r--r--examples/quick/demos/photoviewer/i18n/qml_de.qmbin310 -> 0 bytes
-rw-r--r--examples/quick/demos/photoviewer/i18n/qml_de.ts35
-rw-r--r--examples/quick/demos/photoviewer/i18n/qml_fr.qmbin247 -> 0 bytes
-rw-r--r--examples/quick/demos/photoviewer/i18n/qml_fr.ts35
-rw-r--r--examples/quick/demos/photoviewer/main.qml139
-rw-r--r--examples/quick/demos/photoviewer/photoviewer.pro20
-rw-r--r--examples/quick/demos/photoviewer/qml.qrc20
-rw-r--r--examples/quick/demos/rssnews/content/BusyIndicator.qml64
-rw-r--r--examples/quick/demos/rssnews/content/NewsDelegate.qml140
-rw-r--r--examples/quick/demos/rssnews/content/RssFeeds.qml66
-rw-r--r--examples/quick/demos/rssnews/content/ScrollBar.qml126
-rw-r--r--examples/quick/demos/rssnews/content/images/Asia.jpgbin10578 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Business.jpgbin17276 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Entertainment.jpgbin15433 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Europe.jpgbin15872 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Health.jpgbin16015 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Politics.jpgbin16401 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Science.jpgbin9496 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Sports.jpgbin9281 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Technology.jpgbin22290 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/TopStories.jpgbin8067 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/USNational.jpgbin9635 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/World.jpgbin15128 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/btn_close.pngbin328 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/busy.pngbin1564 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/scrollbar.pngbin79 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.pngbin56830 -> 0 bytes
-rw-r--r--examples/quick/demos/rssnews/doc/src/rssnews.qdoc372
-rw-r--r--examples/quick/demos/rssnews/main.cpp51
-rw-r--r--examples/quick/demos/rssnews/rssnews.pro13
-rw-r--r--examples/quick/demos/rssnews/rssnews.qml169
-rw-r--r--examples/quick/demos/rssnews/rssnews.qmlproject16
-rw-r--r--examples/quick/demos/rssnews/rssnews.qrc25
-rw-r--r--examples/quick/demos/samegame/content/Block.qml124
-rw-r--r--examples/quick/demos/samegame/content/BlockEmitter.qml67
-rw-r--r--examples/quick/demos/samegame/content/Button.qml80
-rw-r--r--examples/quick/demos/samegame/content/GameArea.qml238
-rw-r--r--examples/quick/demos/samegame/content/LogoAnimation.qml112
-rw-r--r--examples/quick/demos/samegame/content/MenuEmitter.qml63
-rw-r--r--examples/quick/demos/samegame/content/PaintEmitter.qml108
-rw-r--r--examples/quick/demos/samegame/content/PrimaryPack.qml132
-rw-r--r--examples/quick/demos/samegame/content/PuzzleBlock.qml121
-rw-r--r--examples/quick/demos/samegame/content/SamegameText.qml59
-rw-r--r--examples/quick/demos/samegame/content/SimpleBlock.qml118
-rw-r--r--examples/quick/demos/samegame/content/SmokeText.qml93
-rw-r--r--examples/quick/demos/samegame/content/gfx/background-puzzle.pngbin86666 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/background.pngbin101018 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/bar.pngbin10970 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/blue-puzzle.pngbin2219 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/blue.pngbin1018 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/bubble-highscore.pngbin2276 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/bubble-puzzle.pngbin2811 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-game-1.pngbin2728 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-game-2.pngbin3378 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-game-3.pngbin1423 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-game-4.pngbin2096 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-game-new.pngbin3662 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-menu.pngbin2391 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-puzzle-next.pngbin3658 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/but-quit.pngbin2100 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/green-puzzle.pngbin2271 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/green.pngbin1024 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/icon-fail.pngbin6549 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/icon-ok.pngbin7190 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/icon-time.pngbin1159 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/logo-a.pngbin1814 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/logo-e.pngbin1725 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/logo-g.pngbin1765 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/logo-m.pngbin1743 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/logo-s.pngbin1791 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/logo.pngbin3608 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/particle-brick.pngbin861 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/particle-paint.pngbin714 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/particle-smoke.pngbin5409 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/red-puzzle.pngbin2218 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/red.pngbin1018 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-highscore-new.pngbin6767 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-highscore.pngbin3179 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-no-winner.pngbin6321 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-p1-go.pngbin5395 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-p1-won.pngbin5618 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-p1.pngbin1751 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-p2-go.pngbin5874 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-p2-won.pngbin6177 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/text-p2.pngbin2381 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/yellow-puzzle.pngbin2239 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/gfx/yellow.pngbin1008 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/content/levels/TemplateBase.qml80
-rw-r--r--examples/quick/demos/samegame/content/levels/level0.qml69
-rw-r--r--examples/quick/demos/samegame/content/levels/level1.qml69
-rw-r--r--examples/quick/demos/samegame/content/levels/level2.qml71
-rw-r--r--examples/quick/demos/samegame/content/levels/level4.qml68
-rw-r--r--examples/quick/demos/samegame/content/levels/level5.qml69
-rw-r--r--examples/quick/demos/samegame/content/levels/level6.qml70
-rw-r--r--examples/quick/demos/samegame/content/levels/level7.qml68
-rw-r--r--examples/quick/demos/samegame/content/levels/level8.qml69
-rw-r--r--examples/quick/demos/samegame/content/levels/level9.qml72
-rw-r--r--examples/quick/demos/samegame/content/qmldir13
-rw-r--r--examples/quick/demos/samegame/content/samegame.js590
-rw-r--r--examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-1.pngbin100713 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-2.pngbin134892 -> 0 bytes
-rw-r--r--examples/quick/demos/samegame/doc/src/samegame.qdoc47
-rw-r--r--examples/quick/demos/samegame/main.cpp51
-rw-r--r--examples/quick/demos/samegame/samegame.pro8
-rw-r--r--examples/quick/demos/samegame/samegame.qml382
-rw-r--r--examples/quick/demos/samegame/samegame.qmlproject16
-rw-r--r--examples/quick/demos/samegame/samegame.qrc73
-rw-r--r--examples/quick/demos/stocqt/content/+windows/Settings.qml56
-rw-r--r--examples/quick/demos/stocqt/content/Banner.qml96
-rw-r--r--examples/quick/demos/stocqt/content/Button.qml74
-rw-r--r--examples/quick/demos/stocqt/content/CheckBox.qml86
-rw-r--r--examples/quick/demos/stocqt/content/Settings.qml56
-rw-r--r--examples/quick/demos/stocqt/content/StockChart.qml400
-rw-r--r--examples/quick/demos/stocqt/content/StockInfo.qml130
-rw-r--r--examples/quick/demos/stocqt/content/StockListDelegate.qml163
-rw-r--r--examples/quick/demos/stocqt/content/StockListModel.qml130
-rw-r--r--examples/quick/demos/stocqt/content/StockListView.qml88
-rw-r--r--examples/quick/demos/stocqt/content/StockModel.qml148
-rw-r--r--examples/quick/demos/stocqt/content/StockSettingsPanel.qml163
-rw-r--r--examples/quick/demos/stocqt/content/StockView.qml110
-rw-r--r--examples/quick/demos/stocqt/content/data/AAPL.csv147
-rw-r--r--examples/quick/demos/stocqt/content/data/ADSK.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/AMD.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/AMZN.csv147
-rw-r--r--examples/quick/demos/stocqt/content/data/CSCO.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/EA.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/EBAY.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/FB.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/GOOG.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/GOOGL.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/INTC.csv147
-rw-r--r--examples/quick/demos/stocqt/content/data/MSFT.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/NCLH.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/NFLX.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/NTAP.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/NVDA.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/PYPL.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/QCOM.csv147
-rw-r--r--examples/quick/demos/stocqt/content/data/TSLA.csv148
-rw-r--r--examples/quick/demos/stocqt/content/data/TXN.csv148
-rw-r--r--examples/quick/demos/stocqt/content/images/icon-left-arrow.pngbin358 -> 0 bytes
-rw-r--r--examples/quick/demos/stocqt/content/images/wheel-touch.pngbin4767 -> 0 bytes
-rw-r--r--examples/quick/demos/stocqt/content/images/wheel.pngbin36223 -> 0 bytes
-rw-r--r--examples/quick/demos/stocqt/content/qmldir12
-rw-r--r--examples/quick/demos/stocqt/doc/images/qtquick-demo-stocqt.pngbin27425 -> 0 bytes
-rw-r--r--examples/quick/demos/stocqt/doc/src/stocqt.qdoc85
-rw-r--r--examples/quick/demos/stocqt/main.cpp51
-rw-r--r--examples/quick/demos/stocqt/stocqt.pro9
-rw-r--r--examples/quick/demos/stocqt/stocqt.qmlproject16
-rw-r--r--examples/quick/demos/stocqt/stocqt.qrc42
-rw-r--r--examples/quick/demos/tweetsearch/content/FlipBar.qml183
-rw-r--r--examples/quick/demos/tweetsearch/content/LineInput.qml108
-rw-r--r--examples/quick/demos/tweetsearch/content/ListFooter.qml164
-rw-r--r--examples/quick/demos/tweetsearch/content/ListHeader.qml91
-rw-r--r--examples/quick/demos/tweetsearch/content/SearchDelegate.qml135
-rw-r--r--examples/quick/demos/tweetsearch/content/TweetDelegate.qml199
-rw-r--r--examples/quick/demos/tweetsearch/content/TweetsModel.qml135
-rw-r--r--examples/quick/demos/tweetsearch/content/resources/anonymous.pngbin1788 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/content/resources/bird-anim-sprites.pngbin11079 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/content/resources/icon-clear.pngbin1166 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/content/resources/icon-loading.pngbin1542 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/content/resources/icon-refresh.pngbin1202 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/content/resources/icon-search.pngbin1284 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/content/tweetsearch.js62
-rw-r--r--examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-1.pngbin18531 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-2.pngbin90622 -> 0 bytes
-rw-r--r--examples/quick/demos/tweetsearch/doc/src/tweetsearch.qdoc79
-rw-r--r--examples/quick/demos/tweetsearch/main.cpp51
-rw-r--r--examples/quick/demos/tweetsearch/tweetsearch.pro13
-rw-r--r--examples/quick/demos/tweetsearch/tweetsearch.qml142
-rw-r--r--examples/quick/demos/tweetsearch/tweetsearch.qmlproject16
-rw-r--r--examples/quick/demos/tweetsearch/tweetsearch.qrc19
-rw-r--r--examples/quick/quick.pro4
-rw-r--r--examples/quick/tableview/pixelator/doc/images/qt-pixelator.pngbin0 -> 23771 bytes
-rw-r--r--examples/quick/tableview/pixelator/doc/src/pixelator.qdoc95
-rw-r--r--examples/quick/tableview/pixelator/imagemodel.cpp (renamed from examples/quick/demos/rssnews/content/CategoryDelegate.qml)91
-rw-r--r--examples/quick/tableview/pixelator/imagemodel.h (renamed from examples/quick/demos/samegame/content/Settings.qml)43
-rw-r--r--examples/quick/tableview/pixelator/main.cpp (renamed from examples/quick/demos/photoviewer/main.cpp)21
-rw-r--r--examples/quick/tableview/pixelator/main.qml (renamed from examples/quick/demos/stocqt/stocqt.qml)104
-rw-r--r--examples/quick/tableview/pixelator/pixelator.pro11
-rw-r--r--examples/quick/tableview/pixelator/qt.pngbin0 -> 3858 bytes
-rw-r--r--examples/quick/tableview/tableview.pro3
-rw-r--r--examples/quick/window/window.qml2
-rw-r--r--src/3rdparty/masm/assembler/AssemblerBuffer.h2
-rw-r--r--src/3rdparty/masm/assembler/LinkBuffer.h4
-rw-r--r--src/3rdparty/masm/assembler/X86Assembler.h20
-rw-r--r--src/3rdparty/masm/masm.pri5
-rw-r--r--src/3rdparty/masm/wtf/OSAllocatorPosix.cpp87
-rw-r--r--src/3rdparty/masm/wtf/VMTags.h8
-rw-r--r--src/imports/folderlistmodel/plugin.cpp9
-rw-r--r--src/imports/handlers/plugin.cpp9
-rw-r--r--src/imports/imports.pro7
-rw-r--r--src/imports/layouts/plugin.cpp8
-rw-r--r--src/imports/localstorage/plugin.cpp30
-rw-r--r--src/imports/models/plugin.cpp9
-rw-r--r--src/imports/particles/plugin.cpp9
-rw-r--r--src/imports/qtqml/plugins.qmltypes15
-rw-r--r--src/imports/qtquick2/plugin.cpp9
-rw-r--r--src/imports/settings/plugin.cpp10
-rw-r--r--src/imports/settings/plugins.qmltypes11
-rw-r--r--src/imports/settings/qqmlsettings.cpp71
-rw-r--r--src/imports/settings/qqmlsettings_p.h7
-rw-r--r--src/imports/settings/settings.pro2
-rw-r--r--src/imports/shapes/plugin.cpp17
-rw-r--r--src/imports/shapes/shapes.pro24
-rw-r--r--src/imports/statemachine/plugin.cpp9
-rw-r--r--src/imports/tableview/plugin.cpp64
-rw-r--r--src/imports/tableview/plugins.qmltypes33
-rw-r--r--src/imports/tableview/qmldir5
-rw-r--r--src/imports/tableview/tableview.pro10
-rw-r--r--src/imports/testlib/TestCase.qml18
-rw-r--r--src/imports/testlib/main.cpp9
-rw-r--r--src/imports/window/plugin.cpp9
-rw-r--r--src/imports/xmllistmodel/plugin.cpp9
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel.cpp32
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel_p.h2
-rw-r--r--src/imports/xmllistmodel/xmllistmodel.pro3
-rw-r--r--src/particles/qquickcustomaffector.cpp2
-rw-r--r--src/particles/qquickparticleemitter.cpp2
-rw-r--r--src/particles/qquicktrailemitter.cpp2
-rw-r--r--src/particles/qquickv4particledata.cpp4
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp66
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp22
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp11
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro29
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.cpp202
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.h89
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.cpp432
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.h125
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.cpp185
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.h105
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp313
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h92
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp102
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h76
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp165
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h98
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp39
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.h58
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp19
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp17
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp20
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp52
-rw-r--r--src/plugins/qmltooling/qmltooling.pro5
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp14
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h2
-rw-r--r--src/qml/animations/qabstractanimationjob.cpp2
-rw-r--r--src/qml/animations/qabstractanimationjob_p.h2
-rw-r--r--src/qml/animations/qanimationgroupjob_p.h2
-rw-r--r--src/qml/animations/qanimationjobutil_p.h2
-rw-r--r--src/qml/animations/qcontinuinganimationgroupjob_p.h2
-rw-r--r--src/qml/animations/qparallelanimationgroupjob_p.h2
-rw-r--r--src/qml/animations/qpauseanimationjob_p.h2
-rw-r--r--src/qml/animations/qsequentialanimationgroupjob_p.h2
-rw-r--r--src/qml/compiler/compiler.pri6
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp109
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h23
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h28
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp12
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator_p.h3
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp25
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h2
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp48
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h76
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp529
-rw-r--r--src/qml/compiler/qv4bytecodehandler_p.h113
-rw-r--r--src/qml/compiler/qv4codegen.cpp1985
-rw-r--r--src/qml/compiler/qv4codegen_p.h106
-rw-r--r--src/qml/compiler/qv4compilationunitmapper_unix.cpp12
-rw-r--r--src/qml/compiler/qv4compilationunitmapper_win.cpp20
-rw-r--r--src/qml/compiler/qv4compileddata.cpp139
-rw-r--r--src/qml/compiler/qv4compileddata_p.h172
-rw-r--r--src/qml/compiler/qv4compiler.cpp173
-rw-r--r--src/qml/compiler/qv4compiler_p.h8
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp254
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h119
-rw-r--r--src/qml/compiler/qv4compilercontrolflow_p.h412
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp495
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h51
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp151
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h226
-rw-r--r--src/qml/configure.json57
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h6
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp2
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp9
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h2
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc4
-rw-r--r--src/qml/doc/src/cppintegration/exposecppattributes.qdoc3
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc46
-rw-r--r--src/qml/jit/jit.pri6
-rw-r--r--src/qml/jit/qv4assembler.cpp158
-rw-r--r--src/qml/jit/qv4assembler_p.h15
-rw-r--r--src/qml/jit/qv4baselinejit.cpp (renamed from src/qml/jit/qv4jit.cpp)838
-rw-r--r--src/qml/jit/qv4baselinejit_p.h (renamed from src/qml/jit/qv4jit_p.h)110
-rw-r--r--src/qml/jit/qv4jithelpers.cpp162
-rw-r--r--src/qml/jit/qv4jithelpers_p.h90
-rw-r--r--src/qml/jsapi/qjsengine.cpp79
-rw-r--r--src/qml/jsapi/qjsengine.h2
-rw-r--r--src/qml/jsapi/qjsvalue.cpp38
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp12
-rw-r--r--src/qml/jsruntime/jsruntime.pri43
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp130
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h25
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp16
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h4
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp91
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h30
-rw-r--r--src/qml/jsruntime/qv4arrayiterator.cpp106
-rw-r--r--src/qml/jsruntime/qv4arrayiterator_p.h106
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp538
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4context.cpp122
-rw-r--r--src/qml/jsruntime/qv4context_p.h90
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp60
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h4
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp137
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4engine.cpp500
-rw-r--r--src/qml/jsruntime/qv4engine_p.h154
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h15
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp24
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h37
-rw-r--r--src/qml/jsruntime/qv4estable.cpp181
-rw-r--r--src/qml/jsruntime/qv4estable_p.h87
-rw-r--r--src/qml/jsruntime/qv4function.cpp52
-rw-r--r--src/qml/jsruntime/qv4function_p.h24
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp349
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h92
-rw-r--r--src/qml/jsruntime/qv4generatorobject.cpp252
-rw-r--r--src/qml/jsruntime/qv4generatorobject_p.h149
-rw-r--r--src/qml/jsruntime/qv4global_p.h22
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp86
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h48
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp210
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h50
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp560
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h128
-rw-r--r--src/qml/jsruntime/qv4iterator.cpp64
-rw-r--r--src/qml/jsruntime/qv4iterator_p.h82
-rw-r--r--src/qml/jsruntime/qv4jscall_p.h10
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp20
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp86
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h50
-rw-r--r--src/qml/jsruntime/qv4managed.cpp61
-rw-r--r--src/qml/jsruntime/qv4managed_p.h124
-rw-r--r--src/qml/jsruntime/qv4mapiterator.cpp107
-rw-r--r--src/qml/jsruntime/qv4mapiterator_p.h104
-rw-r--r--src/qml/jsruntime/qv4mapobject.cpp279
-rw-r--r--src/qml/jsruntime/qv4mapobject_p.h118
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp239
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h12
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp830
-rw-r--r--src/qml/jsruntime/qv4object_p.h250
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp34
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h25
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp201
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h23
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp6
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp9
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h2
-rw-r--r--src/qml/jsruntime/qv4property_p.h13
-rw-r--r--src/qml/jsruntime/qv4propertykey.cpp70
-rw-r--r--src/qml/jsruntime/qv4propertykey_p.h143
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp553
-rw-r--r--src/qml/jsruntime/qv4proxy_p.h120
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp54
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h4
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp101
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h19
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp260
-rw-r--r--src/qml/jsruntime/qv4reflect_p.h89
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp743
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h36
-rw-r--r--src/qml/jsruntime/qv4runtimecodegen.cpp9
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h105
-rw-r--r--src/qml/jsruntime/qv4script.cpp20
-rw-r--r--src/qml/jsruntime/qv4script_p.h17
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp71
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp26
-rw-r--r--src/qml/jsruntime/qv4setiterator.cpp98
-rw-r--r--src/qml/jsruntime/qv4setiterator_p.h103
-rw-r--r--src/qml/jsruntime/qv4setobject.cpp248
-rw-r--r--src/qml/jsruntime/qv4setobject_p.h115
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp2
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h3
-rw-r--r--src/qml/jsruntime/qv4stackframe.cpp74
-rw-r--r--src/qml/jsruntime/qv4stackframe_p.h196
-rw-r--r--src/qml/jsruntime/qv4string.cpp41
-rw-r--r--src/qml/jsruntime/qv4string_p.h113
-rw-r--r--src/qml/jsruntime/qv4stringiterator.cpp95
-rw-r--r--src/qml/jsruntime/qv4stringiterator_p.h103
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp318
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h22
-rw-r--r--src/qml/jsruntime/qv4symbol.cpp182
-rw-r--r--src/qml/jsruntime/qv4symbol_p.h127
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp150
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h44
-rw-r--r--src/qml/jsruntime/qv4util_p.h20
-rw-r--r--src/qml/jsruntime/qv4value.cpp56
-rw-r--r--src/qml/jsruntime/qv4value_p.h163
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h3
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp479
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h9
-rw-r--r--src/qml/jsruntime/qv4vtable_p.h221
-rw-r--r--src/qml/memory/qv4heap_p.h99
-rw-r--r--src/qml/memory/qv4mm.cpp62
-rw-r--r--src/qml/memory/qv4mm_p.h228
-rw-r--r--src/qml/parser/parser.pri16
-rw-r--r--src/qml/parser/qqmljs.g4602
-rw-r--r--src/qml/parser/qqmljsast.cpp551
-rw-r--r--src/qml/parser/qqmljsast_p.h884
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h30
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h71
-rw-r--r--src/qml/parser/qqmljsengine_p.cpp7
-rw-r--r--src/qml/parser/qqmljsengine_p.h28
-rw-r--r--src/qml/parser/qqmljsgrammar.cpp1167
-rw-r--r--src/qml/parser/qqmljsgrammar_p.h215
-rw-r--r--src/qml/parser/qqmljskeywords_p.h131
-rw-r--r--src/qml/parser/qqmljslexer.cpp762
-rw-r--r--src/qml/parser/qqmljslexer_p.h88
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h15
-rw-r--r--src/qml/parser/qqmljsparser.cpp2010
-rw-r--r--src/qml/parser/qqmljsparser_p.h258
-rw-r--r--src/qml/qml.pro4
-rw-r--r--src/qml/qml/ftw/qflagpointer_p.h8
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h20
-rw-r--r--src/qml/qml/qml.pri21
-rw-r--r--src/qml/qml/qqml.h2
-rw-r--r--src/qml/qml/qqmlbinding.cpp11
-rw-r--r--src/qml/qml/qqmlbinding_p.h3
-rw-r--r--src/qml/qml/qqmlcomponent.cpp30
-rw-r--r--src/qml/qml/qqmlcomponent_p.h7
-rw-r--r--src/qml/qml/qqmldata_p.h2
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp4
-rw-r--r--src/qml/qml/qqmldirparser.cpp9
-rw-r--r--src/qml/qml/qqmldirparser_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp94
-rw-r--r--src/qml/qml/qqmlengine.h16
-rw-r--r--src/qml/qml/qqmlguard_p.h28
-rw-r--r--src/qml/qml/qqmlimport.cpp20
-rw-r--r--src/qml/qml/qqmlimport_p.h3
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp10
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h17
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp55
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h7
-rw-r--r--src/qml/qml/qqmllocale.cpp6
-rw-r--r--src/qml/qml/qqmllocale_p.h2
-rw-r--r--src/qml/qml/qqmlloggingcategory.cpp36
-rw-r--r--src/qml/qml/qqmlloggingcategory_p.h13
-rw-r--r--src/qml/qml/qqmlmetatype.cpp59
-rw-r--r--src/qml/qml/qqmlmetatype_p.h7
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp41
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h4
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp122
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h5
-rw-r--r--src/qml/qml/qqmlproperty.cpp2
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h6
-rw-r--r--src/qml/qml/qqmltypeloader.cpp130
-rw-r--r--src/qml/qml/qqmltypeloader_p.h41
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp84
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h16
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp47
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h10
-rw-r--r--src/qml/qml/qqmlvme_p.h4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp6
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h6
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp110
-rw-r--r--src/qml/qml/qqmlxmlhttprequest_p.h4
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp39
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h6
-rw-r--r--src/qml/qml/v8/qv8engine.cpp37
-rw-r--r--src/qml/qml/v8/qv8engine_p.h10
-rw-r--r--src/qml/qtqmlglobal.h1
-rw-r--r--src/qml/qtqmlglobal_p.h2
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp347
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h10
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h26
-rw-r--r--src/qml/types/qqmllistmodel.cpp171
-rw-r--r--src/qml/types/qqmllistmodel_p.h4
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h40
-rw-r--r--src/qml/types/qqmllistmodelworkeragent_p.h2
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp5
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h2
-rw-r--r--src/qml/types/qqmltableinstancemodel.cpp341
-rw-r--r--src/qml/types/qqmltableinstancemodel_p.h132
-rw-r--r--src/qml/types/qqmltimer_p.h2
-rw-r--r--src/qml/types/qquickworkerscript.cpp12
-rw-r--r--src/qml/types/types.pri24
-rw-r--r--src/qml/util/qqmladaptormodel.cpp177
-rw-r--r--src/qml/util/qqmladaptormodel_p.h26
-rw-r--r--src/qml/util/qqmlpropertymap.cpp4
-rw-r--r--src/qmldebug/qmldebug.pro3
-rw-r--r--src/qmldebug/qqmldebugclient.cpp5
-rw-r--r--src/qmldebug/qqmldebugclient_p.h5
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp4
-rw-r--r--src/qmldebug/qqmldebugmessageclient.cpp5
-rw-r--r--src/qmldebug/qqmldebugmessageclient_p.h5
-rw-r--r--src/qmldebug/qqmlenginecontrolclient.cpp6
-rw-r--r--src/qmldebug/qqmlpreviewclient.cpp120
-rw-r--r--src/qmldebug/qqmlpreviewclient_p.h95
-rw-r--r--src/qmldebug/qqmlpreviewclient_p_p.h70
-rw-r--r--src/qmldebug/qqmlprofilerclient.cpp7
-rw-r--r--src/qmldebug/qqmlprofilerclient_p.h2
-rw-r--r--src/qmldebug/qqmlprofilerclient_p_p.h3
-rw-r--r--src/qmltest/doc/src/qtquicktest-index.qdoc5
-rw-r--r--src/qmltest/qtestoptions_p.h6
-rw-r--r--src/qmltest/quicktest.cpp28
-rw-r--r--src/qmltest/quicktestresult.cpp14
-rw-r--r--src/qmltest/quicktestresult_p.h2
-rw-r--r--src/quick/configure.json12
-rw-r--r--src/quick/designer/qqmldesignermetaobject.cpp4
-rw-r--r--src/quick/doc/images/qml-item-canvas-lineDash.pngbin0 -> 6254 bytes
-rw-r--r--src/quick/doc/snippets/qml/pathview/pathview.qml4
-rw-r--r--src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml12
-rw-r--r--src/quick/handlers/handlers.pri9
-rw-r--r--src/quick/handlers/qquickdragaxis.cpp75
-rw-r--r--src/quick/handlers/qquickdragaxis_p.h87
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp35
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h31
-rw-r--r--src/quick/handlers/qquickhandlerpoint.cpp351
-rw-r--r--src/quick/handlers/qquickhandlerpoint_p.h120
-rw-r--r--src/quick/handlers/qquickhandlersmodule.cpp2
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp107
-rw-r--r--src/quick/handlers/qquickhoverhandler_p.h91
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp73
-rw-r--r--src/quick/handlers/qquickmultipointhandler_p.h15
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp64
-rw-r--r--src/quick/handlers/qquickpinchhandler_p.h13
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler.cpp103
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler_p.h26
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler_p_p.h75
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp211
-rw-r--r--src/quick/handlers/qquickpointerhandler_p.h38
-rw-r--r--src/quick/handlers/qquickpointerhandler_p_p.h85
-rw-r--r--src/quick/handlers/qquickpointhandler.cpp2
-rw-r--r--src/quick/handlers/qquicksinglepointhandler.cpp300
-rw-r--r--src/quick/handlers/qquicksinglepointhandler_p.h63
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp6
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp172
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h5
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp26
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h14
-rw-r--r--src/quick/items/items.pri10
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp11
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h2
-rw-r--r--src/quick/items/qquickevents.cpp214
-rw-r--r--src/quick/items/qquickevents_p_p.h108
-rw-r--r--src/quick/items/qquickflickable.cpp32
-rw-r--r--src/quick/items/qquickflickable_p.h5
-rw-r--r--src/quick/items/qquickflickable_p_p.h1
-rw-r--r--src/quick/items/qquickgridview.cpp10
-rw-r--r--src/quick/items/qquickitem.cpp26
-rw-r--r--src/quick/items/qquickitem_p.h2
-rw-r--r--src/quick/items/qquickitemsmodule.cpp4
-rw-r--r--src/quick/items/qquickitemview.cpp106
-rw-r--r--src/quick/items/qquickitemview_p_p.h37
-rw-r--r--src/quick/items/qquickitemviewfxitem.cpp165
-rw-r--r--src/quick/items/qquickitemviewfxitem_p_p.h108
-rw-r--r--src/quick/items/qquicklistview.cpp10
-rw-r--r--src/quick/items/qquickloader.cpp17
-rw-r--r--src/quick/items/qquickloader_p_p.h3
-rw-r--r--src/quick/items/qquickrectangle.cpp121
-rw-r--r--src/quick/items/qquickrectangle_p.h17
-rw-r--r--src/quick/items/qquickrectangle_p_p.h2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp1
-rw-r--r--src/quick/items/qquickscalegrid.cpp4
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h12
-rw-r--r--src/quick/items/qquicktableview.cpp1463
-rw-r--r--src/quick/items/qquicktableview_p.h194
-rw-r--r--src/quick/items/qquicktableview_p_p.h342
-rw-r--r--src/quick/items/qquicktext.cpp47
-rw-r--r--src/quick/items/qquicktext_p_p.h1
-rw-r--r--src/quick/items/qquickwindow.cpp201
-rw-r--r--src/quick/items/qquickwindow_p.h9
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h1
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp4
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp12
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h4
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp12
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h10
-rw-r--r--src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp225
-rw-r--r--src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h2
-rw-r--r--src/quick/util/qquickanimation.cpp22
-rw-r--r--src/quick/util/qquickanimation_p.h1
-rw-r--r--src/quick/util/qquickglobal.cpp2
-rw-r--r--src/quick/util/qquickimageprovider.cpp5
-rw-r--r--src/quick/util/qquickimageprovider.h6
-rw-r--r--src/quick/util/qquickimageprovider_p.h72
-rw-r--r--src/quick/util/qquickpixmapcache.cpp19
-rw-r--r--src/quick/util/qquickprofiler.cpp3
-rw-r--r--src/quick/util/qquickprofiler_p.h2
-rw-r--r--src/quick/util/qquickpropertychanges.cpp6
-rw-r--r--src/quick/util/qquickstate.cpp2
-rw-r--r--src/quick/util/qquickstate_p_p.h4
-rw-r--r--src/quick/util/qquicksvgparser.cpp3
-rw-r--r--src/quick/util/qquickutilmodule.cpp3
-rw-r--r--src/quick/util/util.pri1
-rw-r--r--src/quickshapes/qquicknvprfunctions.cpp (renamed from src/imports/shapes/qquicknvprfunctions.cpp)0
-rw-r--r--src/quickshapes/qquicknvprfunctions_p.h (renamed from src/imports/shapes/qquicknvprfunctions_p.h)1
-rw-r--r--src/quickshapes/qquicknvprfunctions_p_p.h (renamed from src/imports/shapes/qquicknvprfunctions_p_p.h)3
-rw-r--r--src/quickshapes/qquickshape.cpp (renamed from src/imports/shapes/qquickshape.cpp)13
-rw-r--r--src/quickshapes/qquickshape_p.h (renamed from src/imports/shapes/qquickshape_p.h)15
-rw-r--r--src/quickshapes/qquickshape_p_p.h (renamed from src/imports/shapes/qquickshape_p_p.h)5
-rw-r--r--src/quickshapes/qquickshapegenericrenderer.cpp (renamed from src/imports/shapes/qquickshapegenericrenderer.cpp)0
-rw-r--r--src/quickshapes/qquickshapegenericrenderer_p.h (renamed from src/imports/shapes/qquickshapegenericrenderer_p.h)3
-rw-r--r--src/quickshapes/qquickshapenvprrenderer.cpp (renamed from src/imports/shapes/qquickshapenvprrenderer.cpp)0
-rw-r--r--src/quickshapes/qquickshapenvprrenderer_p.h (renamed from src/imports/shapes/qquickshapenvprrenderer_p.h)5
-rw-r--r--src/quickshapes/qquickshapesglobal.h56
-rw-r--r--src/quickshapes/qquickshapesglobal_p.h63
-rw-r--r--src/quickshapes/qquickshapesoftwarerenderer.cpp (renamed from src/imports/shapes/qquickshapesoftwarerenderer.cpp)0
-rw-r--r--src/quickshapes/qquickshapesoftwarerenderer_p.h (renamed from src/imports/shapes/qquickshapesoftwarerenderer_p.h)3
-rw-r--r--src/quickshapes/qtquickshapes.qrc (renamed from src/imports/shapes/qtquickshapesplugin.qrc)0
-rw-r--r--src/quickshapes/quickshapes.pro33
-rw-r--r--src/quickshapes/shaders/blit.frag (renamed from src/imports/shapes/shaders/blit.frag)0
-rw-r--r--src/quickshapes/shaders/blit.vert (renamed from src/imports/shapes/shaders/blit.vert)0
-rw-r--r--src/quickshapes/shaders/blit_core.frag (renamed from src/imports/shapes/shaders/blit_core.frag)0
-rw-r--r--src/quickshapes/shaders/blit_core.vert (renamed from src/imports/shapes/shaders/blit_core.vert)0
-rw-r--r--src/quickshapes/shaders/conicalgradient.frag (renamed from src/imports/shapes/shaders/conicalgradient.frag)0
-rw-r--r--src/quickshapes/shaders/conicalgradient.vert (renamed from src/imports/shapes/shaders/conicalgradient.vert)0
-rw-r--r--src/quickshapes/shaders/conicalgradient_core.frag (renamed from src/imports/shapes/shaders/conicalgradient_core.frag)0
-rw-r--r--src/quickshapes/shaders/conicalgradient_core.vert (renamed from src/imports/shapes/shaders/conicalgradient_core.vert)0
-rw-r--r--src/quickshapes/shaders/lineargradient.frag (renamed from src/imports/shapes/shaders/lineargradient.frag)0
-rw-r--r--src/quickshapes/shaders/lineargradient.vert (renamed from src/imports/shapes/shaders/lineargradient.vert)0
-rw-r--r--src/quickshapes/shaders/lineargradient_core.frag (renamed from src/imports/shapes/shaders/lineargradient_core.frag)0
-rw-r--r--src/quickshapes/shaders/lineargradient_core.vert (renamed from src/imports/shapes/shaders/lineargradient_core.vert)0
-rw-r--r--src/quickshapes/shaders/radialgradient.frag (renamed from src/imports/shapes/shaders/radialgradient.frag)0
-rw-r--r--src/quickshapes/shaders/radialgradient.vert (renamed from src/imports/shapes/shaders/radialgradient.vert)0
-rw-r--r--src/quickshapes/shaders/radialgradient_core.frag (renamed from src/imports/shapes/shaders/radialgradient_core.frag)0
-rw-r--r--src/quickshapes/shaders/radialgradient_core.vert (renamed from src/imports/shapes/shaders/radialgradient_core.vert)0
-rw-r--r--src/src.pro18
-rw-r--r--sync.profile4
-rw-r--r--tests/auto/guiapplauncher/demos.txt8
-rw-r--r--tests/auto/qml/debugger/debugger.pro8
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp9
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/breakpointRelocation.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/changeBreakpoint.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/condition.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/condition.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/createComponent.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/encodeQmlScope.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/exception.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/exception.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/loadjsfile.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/oncompleted.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/quit.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/quit.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/stepAction.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/test.js (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/test.js)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/test.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/test.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/timer.qml (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/timer.qml)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro26
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro24
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.pro12
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp)12
-rw-r--r--tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp (renamed from tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.cpp)0
-rw-r--r--tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.pro9
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/broken.qml31
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml71
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window.qml44
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window1.qml43
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window2.qml43
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/zoom.qml51
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/qqmlpreview.pro24
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp317
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml40
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp48
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp31
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp105
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h31
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugprocess.cpp8
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugprocess_p.h4
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp1
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.h3
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations2855
-rw-r--r--tests/auto/qml/ecmascripttests/ecmascripttests.pro15
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/main.cpp114
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/qjstest.pro13
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp760
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/test262runner.h131
m---------tests/auto/qml/ecmascripttests/test2620
-rwxr-xr-xtests/auto/qml/ecmascripttests/test262.py91
-rw-r--r--tests/auto/qml/ecmascripttests/testcase.pro15
-rw-r--r--tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp48
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp168
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp2
-rw-r--r--tests/auto/qml/qml.pro1
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp12
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp3
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp24
-rw-r--r--tests/auto/qml/qqmlconsole/data/categorized_logging.qml14
-rw-r--r--tests/auto/qml/qqmlconsole/data/logging.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp24
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.8.qml16
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/importPragmaLibraryWithPragmaLibraryImports.js2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleRemoteImport.js2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jsimport/testJsRemoteImport.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/lib/com/qt/JsModule/ScriptAPI.js (renamed from tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js)0
-rw-r--r--tests/auto/qml/qqmlecmascript/data/lib/com/qt/JsModule/qmldir (renamed from tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir)0
-rw-r--r--tests/auto/qml/qqmlecmascript/data/remote/com/qt/JsRemoteModule/ScriptAPI.js (renamed from tests/auto/qml/qqmlecmascript/data/remote/com/nokia/JsRemoteModule/ScriptAPI.js)0
-rw-r--r--tests/auto/qml/qqmlecmascript/data/remote/com/qt/JsRemoteModule/qmldir (renamed from tests/auto/qml/qqmlecmascript/data/remote/com/nokia/JsRemoteModule/qmldir)0
-rw-r--r--tests/auto/qml/qqmlecmascript/data/removeBindingsWithNoDependencies.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/tryStatement.3.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/tryStatement.4.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp397
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp117
-rw-r--r--tests/auto/qml/qqmllanguage/data/dynamicMeta.5.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/property.4.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest18.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/wrongType.16.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp9
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp50
-rw-r--r--tests/auto/qml/qqmllistmodel/data/dynamicroles.qml21
-rw-r--r--tests/auto/qml/qqmllistmodel/data/qtbug38907.qml25
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp111
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp2
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp82
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp32
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp2
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp10
-rw-r--r--tests/auto/qml/qqmltranslation/data/translationChange.qml8
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp6
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp4
-rw-r--r--tests/auto/qml/qv4identifiertable/qv4identifiertable.pro8
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp305
-rw-r--r--tests/auto/qml/qv4mm/tst_qv4mm.cpp11
-rw-r--r--tests/auto/qmltest/rectangle/tst_rectangle.qml23
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml123
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml (renamed from tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml)16
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml19
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp133
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp13
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp23
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml38
-rw-r--r--tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp33
-rw-r--r--tests/auto/quick/qquickanimations/data/finished.qml95
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp74
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_line.qml91
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/TestComponent.qml4
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/test.qml4
-rw-r--r--tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp8
-rw-r--r--tests/auto/quick/qquickflickable/BLACKLIST1
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp66
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp4
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp31
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp65
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp70
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp4
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp8
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp20
-rw-r--r--tests/auto/quick/qquickrectangle/data/gradient-preset.qml16
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp28
-rw-r--r--tests/auto/quick/qquickrepeater/data/ownership.qml4
-rw-r--r--tests/auto/quick/qquickrepeater/data/package.qml35
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp88
-rw-r--r--tests/auto/quick/qquickshape/qquickshape.pro24
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp2
-rw-r--r--tests/auto/quick/qquicktableview/data/countingtableview.qml85
-rw-r--r--tests/auto/quick/qquicktableview/data/plaintableview.qml80
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml66
-rw-r--r--tests/auto/quick/qquicktableview/qquicktableview.pro14
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h89
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp791
-rw-r--r--tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml27
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp23
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp5
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp45
-rw-r--r--tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp13
-rw-r--r--tests/auto/quick/quick.pro3
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp8
-rw-r--r--tests/auto/quick/shared/viewtestutil.h3
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp50
-rw-r--r--tests/auto/quicktest/quicktest.pro3
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp29
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.pro11
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml38
-rw-r--r--tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml38
-rw-r--r--tests/auto/quicktest/testfiltering/test/test.pro5
-rw-r--r--tests/auto/quicktest/testfiltering/testfiltering.pro4
-rw-r--r--tests/auto/quicktest/testfiltering/tst_testfiltering.cpp135
-rw-r--r--tests/manual/pointer/content/MultiButton.qml1
-rw-r--r--tests/manual/pointer/map.qml8
-rw-r--r--tests/manual/pointer/multibuttons.qml3
-rw-r--r--tests/manual/pointer/pinchDragFlingMPTA.qml2
-rw-r--r--tests/manual/pointer/pinchHandler.qml6
-rw-r--r--tests/manual/pointer/sidebar.qml186
-rw-r--r--tests/manual/pointer/singlePointHandlerProperties.qml5
-rw-r--r--tests/manual/tableview/abstracttablemodel/abstracttablemodel.pro10
-rw-r--r--tests/manual/tableview/abstracttablemodel/main.cpp100
-rw-r--r--tests/manual/tableview/abstracttablemodel/main.qml91
-rw-r--r--tests/manual/tableview/listmodel/listmodel.pro10
-rw-r--r--tests/manual/tableview/listmodel/main.cpp52
-rw-r--r--tests/manual/tableview/listmodel/main.qml86
-rw-r--r--tests/manual/tableview/storagemodel/main.cpp56
-rw-r--r--tests/manual/tableview/storagemodel/main.qml75
-rw-r--r--tests/manual/tableview/storagemodel/storagemodel.cpp226
-rw-r--r--tests/manual/tableview/storagemodel/storagemodel.h (renamed from examples/quick/demos/samegame/content/levels/level3.qml)63
-rw-r--r--tests/manual/tableview/storagemodel/storagemodel.pro11
-rw-r--r--tests/manual/tableview/tableview.pro4
-rw-r--r--tests/manual/touch/flicktext.qml8
-rw-r--r--tools/qml/main.cpp6
-rw-r--r--tools/qml/qml.pro2
-rw-r--r--tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in (renamed from tools/qmlcachegen/Qt5QuickCompilerConfig.cmake)36
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp10
-rw-r--r--tools/qmlcachegen/qmlcachegen.pro16
-rw-r--r--tools/qmljs/qmljs.cpp11
-rw-r--r--tools/qmlmin/main.cpp104
-rw-r--r--tools/qmlpreview/main.cpp36
-rw-r--r--tools/qmlpreview/qmlpreview.pro13
-rw-r--r--tools/qmlpreview/qmlpreviewapplication.cpp266
-rw-r--r--tools/qmlpreview/qmlpreviewapplication.h83
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.cpp6
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.cpp4
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.h2
-rw-r--r--tools/tools.pro22
991 files changed, 39027 insertions, 32581 deletions
diff --git a/.gitmodules b/.gitmodules
index e6e5650150..e93f38f128 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
[submodule "tests/auto/qml/ecmascripttests/test262"]
path = tests/auto/qml/ecmascripttests/test262
url = ../qtdeclarative-testsuites.git
- branch = snapshot-20150317-8f6a508-based
+ branch = snapshot-20180312-3c69133-based
diff --git a/.qmake.conf b/.qmake.conf
index db74e7164b..81caa27c53 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,4 +1,4 @@
load(qt_build_config)
CONFIG += warning_clean
-MODULE_VERSION = 5.11.1
+MODULE_VERSION = 5.12.0
diff --git a/examples/quick/demos/calqlatr/calqlatr.pro b/examples/quick/demos/calqlatr/calqlatr.pro
deleted file mode 100644
index 20543c08da..0000000000
--- a/examples/quick/demos/calqlatr/calqlatr.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick
-SOURCES += main.cpp
-
-RESOURCES += calqlatr.qrc \
- ../../shared/shared.qrc
-
-OTHER_FILES = calqlatr.qml \
- content/Button.qml \
- content/Display.qml \
- content/NumberPad.qml \
- content/calculator.js \
- content/images/paper-edge-left.png \
- content/images/paper-edge-right.png \
- content/images/paper-grip.png
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/calqlatr
-INSTALLS += target
diff --git a/examples/quick/demos/calqlatr/calqlatr.qml b/examples/quick/demos/calqlatr/calqlatr.qml
deleted file mode 100644
index 769513b7bd..0000000000
--- a/examples/quick/demos/calqlatr/calqlatr.qml
+++ /dev/null
@@ -1,173 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "content"
-import "content/calculator.js" as CalcEngine
-
-
-Rectangle {
- id: window
- width: 320
- height: 480
- focus: true
- color: "#272822"
-
- onWidthChanged: controller.reload()
- onHeightChanged: controller.reload()
-
- function operatorPressed(operator) {
- CalcEngine.operatorPressed(operator)
- numPad.buttonPressed()
- }
- function digitPressed(digit) {
- CalcEngine.digitPressed(digit)
- numPad.buttonPressed()
- }
- function isButtonDisabled(op) {
- return CalcEngine.disabled(op)
- }
-
- Item {
- id: pad
- width: 180
- NumberPad { id: numPad; y: 10; anchors.horizontalCenter: parent.horizontalCenter }
- }
-
- AnimationController {
- id: controller
- animation: ParallelAnimation {
- id: anim
- NumberAnimation { target: display; property: "x"; duration: 400; from: -16; to: window.width - display.width; easing.type: Easing.InOutQuad }
- NumberAnimation { target: pad; property: "x"; duration: 400; from: window.width - pad.width; to: 0; easing.type: Easing.InOutQuad }
- SequentialAnimation {
- NumberAnimation { target: pad; property: "scale"; duration: 200; from: 1; to: 0.97; easing.type: Easing.InOutQuad }
- NumberAnimation { target: pad; property: "scale"; duration: 200; from: 0.97; to: 1; easing.type: Easing.InOutQuad }
- }
- }
- }
-
- Keys.onPressed: {
- if (event.key == Qt.Key_0)
- digitPressed("0")
- else if (event.key == Qt.Key_1)
- digitPressed("1")
- else if (event.key == Qt.Key_2)
- digitPressed("2")
- else if (event.key == Qt.Key_3)
- digitPressed("3")
- else if (event.key == Qt.Key_4)
- digitPressed("4")
- else if (event.key == Qt.Key_5)
- digitPressed("5")
- else if (event.key == Qt.Key_6)
- digitPressed("6")
- else if (event.key == Qt.Key_7)
- digitPressed("7")
- else if (event.key == Qt.Key_8)
- digitPressed("8")
- else if (event.key == Qt.Key_9)
- digitPressed("9")
- else if (event.key == Qt.Key_Plus)
- operatorPressed("+")
- else if (event.key == Qt.Key_Minus)
- operatorPressed("−")
- else if (event.key == Qt.Key_Asterisk)
- operatorPressed("×")
- else if (event.key == Qt.Key_Slash)
- operatorPressed("÷")
- else if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return)
- operatorPressed("=")
- else if (event.key == Qt.Key_Comma || event.key == Qt.Key_Period)
- digitPressed(".")
- else if (event.key == Qt.Key_Backspace)
- operatorPressed("backspace")
- }
-
- Display {
- id: display
- x: -16
- width: window.width - pad.width
- height: parent.height
-
- MouseArea {
- id: mouseInput
- property real startX: 0
- property real oldP: 0
- property bool rewind: false
-
- anchors {
- bottom: parent.bottom
- left: parent.left
- right: parent.right
- }
- height: 50
- onPositionChanged: {
- var reverse = startX > window.width / 2
- var mx = mapToItem(window, mouseInput.mouseX, mouseInput.mouseY).x
- var p = Math.abs((mx - startX) / (window.width - display.width))
- if (p < oldP)
- rewind = reverse ? false : true
- else
- rewind = reverse ? true : false
- controller.progress = reverse ? 1 - p : p
- oldP = p
- }
- onPressed: startX = mapToItem(window, mouseInput.mouseX, mouseInput.mouseY).x
- onReleased: {
- if (rewind)
- controller.completeToBeginning()
- else
- controller.completeToEnd()
- }
- }
- }
-
-}
diff --git a/examples/quick/demos/calqlatr/calqlatr.qmlproject b/examples/quick/demos/calqlatr/calqlatr.qmlproject
deleted file mode 100644
index ce2d59d310..0000000000
--- a/examples/quick/demos/calqlatr/calqlatr.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "calqlatr.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
-}
diff --git a/examples/quick/demos/calqlatr/calqlatr.qrc b/examples/quick/demos/calqlatr/calqlatr.qrc
deleted file mode 100644
index 7483304e02..0000000000
--- a/examples/quick/demos/calqlatr/calqlatr.qrc
+++ /dev/null
@@ -1,12 +0,0 @@
-<RCC>
- <qresource prefix="/demos/calqlatr">
- <file>calqlatr.qml</file>
- <file>content/Button.qml</file>
- <file>content/calculator.js</file>
- <file>content/Display.qml</file>
- <file>content/NumberPad.qml</file>
- <file>content/images/paper-edge-left.png</file>
- <file>content/images/paper-edge-right.png</file>
- <file>content/images/paper-grip.png</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/calqlatr/content/Button.qml b/examples/quick/demos/calqlatr/content/Button.qml
deleted file mode 100644
index 5279596ef1..0000000000
--- a/examples/quick/demos/calqlatr/content/Button.qml
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: button
- property alias text: textItem.text
- property color color: "#eceeea"
-
- property bool operator: false
- property bool dimmable: false
- property bool dimmed: false
-
- width: 30
- height: 50
-
- Text {
- id: textItem
- font.pixelSize: 48
- wrapMode: Text.WordWrap
- lineHeight: 0.75
- color: (dimmable && dimmed) ? Qt.darker(button.color) : button.color
- Behavior on color { ColorAnimation { duration: 120; easing.type: Easing.OutElastic} }
- states: [
- State {
- name: "pressed"
- when: mouse.pressed && !dimmed
- PropertyChanges {
- target: textItem
- color: Qt.lighter(button.color)
- }
- }
- ]
- }
-
- MouseArea {
- id: mouse
- anchors.fill: parent
- anchors.margins: -5
- onClicked: {
- if (operator)
- window.operatorPressed(parent.text)
- else
- window.digitPressed(parent.text)
- }
- }
-
- function updateDimmed() {
- dimmed = window.isButtonDisabled(button.text)
- }
-
- Component.onCompleted: {
- numPad.buttonPressed.connect(updateDimmed)
- updateDimmed()
- }
-}
diff --git a/examples/quick/demos/calqlatr/content/Display.qml b/examples/quick/demos/calqlatr/content/Display.qml
deleted file mode 100644
index 9ddd64d251..0000000000
--- a/examples/quick/demos/calqlatr/content/Display.qml
+++ /dev/null
@@ -1,203 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Window 2.0
-
-Item {
- id: display
- property real fontSize: Math.floor(Screen.pixelDensity * 5.0)
- property bool enteringDigits: false
- property int maxDigits: (width / fontSize) + 1
- property string displayedOperand
- property string errorString: qsTr("ERROR")
- property bool isError: displayedOperand === errorString
-
- function displayOperator(operator)
- {
- listView.model.append({ "operator": operator, "operand": "" })
- enteringDigits = true
- listView.positionViewAtEnd()
- }
-
- function newLine(operator, operand)
- {
- displayedOperand = displayNumber(operand)
- listView.model.append({ "operator": operator, "operand": displayedOperand })
- enteringDigits = false
- listView.positionViewAtEnd()
- }
-
- function appendDigit(digit)
- {
- if (!enteringDigits)
- listView.model.append({ "operator": "", "operand": "" })
- var i = listView.model.count - 1;
- listView.model.get(i).operand = listView.model.get(i).operand + digit;
- enteringDigits = true
- listView.positionViewAtEnd()
- }
-
- function setDigit(digit)
- {
- var i = listView.model.count - 1;
- listView.model.get(i).operand = digit;
- listView.positionViewAtEnd()
- }
-
- function clear()
- {
- displayedOperand = ""
- if (enteringDigits) {
- var i = listView.model.count - 1
- if (i >= 0)
- listView.model.remove(i)
- enteringDigits = false
- }
- }
-
- // Returns a string representation of a number that fits in
- // display.maxDigits characters, trying to keep as much precision
- // as possible. If the number cannot be displayed, returns an
- // error string.
- function displayNumber(num) {
- if (typeof(num) != "number")
- return errorString;
-
- var intNum = parseInt(num);
- var intLen = intNum.toString().length;
-
- // Do not count the minus sign as a digit
- var maxLen = num < 0 ? maxDigits + 1 : maxDigits;
-
- if (num.toString().length <= maxLen) {
- if (isFinite(num))
- return num.toString();
- return errorString;
- }
-
- // Integer part of the number is too long - try
- // an exponential notation
- if (intNum == num || intLen > maxLen - 3) {
- var expVal = num.toExponential(maxDigits - 6).toString();
- if (expVal.length <= maxLen)
- return expVal;
- }
-
- // Try a float presentation with fixed number of digits
- var floatStr = parseFloat(num).toFixed(maxDigits - intLen - 1).toString();
- if (floatStr.length <= maxLen)
- return floatStr;
-
- return errorString;
- }
-
- Item {
- id: theItem
- width: parent.width + 32
- height: parent.height
-
- Rectangle {
- id: rect
- x: 16
- color: "white"
- height: parent.height
- width: display.width - 16
- }
- Image {
- anchors.right: rect.left
- source: "images/paper-edge-left.png"
- height: parent.height
- fillMode: Image.TileVertically
- }
- Image {
- anchors.left: rect.right
- source: "images/paper-edge-right.png"
- height: parent.height
- fillMode: Image.TileVertically
- }
-
- Image {
- id: grip
- source: "images/paper-grip.png"
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 20
- }
-
- ListView {
- id: listView
- x: 16; y: 30
- width: display.width
- height: display.height - 50 - y
- delegate: Item {
- height: display.fontSize * 1.1
- width: parent.width
- Text {
- id: operator
- x: 6
- font.pixelSize: display.fontSize
- color: "#6da43d"
- text: model.operator
- }
- Text {
- id: operand
- font.pixelSize: display.fontSize
- anchors.right: parent.right
- anchors.rightMargin: 22
- text: model.operand
- }
- }
- model: ListModel { }
- }
-
- }
-
-}
diff --git a/examples/quick/demos/calqlatr/content/NumberPad.qml b/examples/quick/demos/calqlatr/content/NumberPad.qml
deleted file mode 100644
index 9936116fa1..0000000000
--- a/examples/quick/demos/calqlatr/content/NumberPad.qml
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Grid {
- columns: 3
- columnSpacing: 32
- rowSpacing: 16
-
- signal buttonPressed
-
- Button { text: "7" }
- Button { text: "8" }
- Button { text: "9" }
- Button { text: "4" }
- Button { text: "5" }
- Button { text: "6" }
- Button { text: "1" }
- Button { text: "2" }
- Button { text: "3" }
- Button { text: "0" }
- Button { text: "."; dimmable: true }
- Button { text: " " }
- Button { text: "±"; color: "#6da43d"; operator: true; dimmable: true }
- Button { text: "−"; color: "#6da43d"; operator: true; dimmable: true }
- Button { text: "+"; color: "#6da43d"; operator: true; dimmable: true }
- Button { text: "√"; color: "#6da43d"; operator: true; dimmable: true }
- Button { text: "÷"; color: "#6da43d"; operator: true; dimmable: true }
- Button { text: "×"; color: "#6da43d"; operator: true; dimmable: true }
- Button { text: "C"; color: "#6da43d"; operator: true }
- Button { text: " "; color: "#6da43d"; operator: true }
- Button { text: "="; color: "#6da43d"; operator: true; dimmable: true }
-}
diff --git a/examples/quick/demos/calqlatr/content/calculator.js b/examples/quick/demos/calqlatr/content/calculator.js
deleted file mode 100644
index 37eb752191..0000000000
--- a/examples/quick/demos/calqlatr/content/calculator.js
+++ /dev/null
@@ -1,161 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-var curVal = 0
-var memory = 0
-var lastOp = ""
-var previousOperator = ""
-var digits = ""
-
-function disabled(op) {
- if (digits == "" && !((op >= "0" && op <= "9") || op == "."))
- return true
- else if (op == '=' && previousOperator.length != 1)
- return true
- else if (op == "." && digits.toString().search(/\./) != -1) {
- return true
- } else if (op == "√" && digits.toString().search(/-/) != -1) {
- return true
- } else {
- return false
- }
-}
-
-function digitPressed(op)
-{
- if (disabled(op))
- return
- if (digits.toString().length >= display.maxDigits)
- return
- if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp == ".") ) {
- digits = digits + op.toString()
- display.appendDigit(op.toString())
- } else {
- digits = op
- display.appendDigit(op.toString())
- }
- lastOp = op
-}
-
-function operatorPressed(op)
-{
- if (disabled(op))
- return
- lastOp = op
-
- if (op == "±") {
- digits = Number(digits.valueOf() * -1)
- display.setDigit(display.displayNumber(digits))
- return
- }
-
- if (previousOperator == "+") {
- digits = Number(digits.valueOf()) + Number(curVal.valueOf())
- } else if (previousOperator == "−") {
- digits = Number(curVal.valueOf()) - Number(digits.valueOf())
- } else if (previousOperator == "×") {
- digits = Number(curVal) * Number(digits.valueOf())
- } else if (previousOperator == "÷") {
- digits = Number(curVal) / Number(digits.valueOf())
- }
-
- if (op == "+" || op == "−" || op == "×" || op == "÷") {
- previousOperator = op
- curVal = digits.valueOf()
- digits = ""
- display.displayOperator(previousOperator)
- return
- }
-
- if (op == "=") {
- display.newLine("=", digits.valueOf())
- }
-
- curVal = 0
- previousOperator = ""
-
- if (op == "1/x") {
- digits = (1 / digits.valueOf()).toString()
- } else if (op == "x^2") {
- digits = (digits.valueOf() * digits.valueOf()).toString()
- } else if (op == "Abs") {
- digits = (Math.abs(digits.valueOf())).toString()
- } else if (op == "Int") {
- digits = (Math.floor(digits.valueOf())).toString()
- } else if (op == "√") {
- digits = Number(Math.sqrt(digits.valueOf()))
- display.newLine("√", digits.valueOf())
- } else if (op == "mc") {
- memory = 0;
- } else if (op == "m+") {
- memory += digits.valueOf()
- } else if (op == "mr") {
- digits = memory.toString()
- } else if (op == "m-") {
- memory = digits.valueOf()
- } else if (op == "backspace") {
- digits = digits.toString().slice(0, -1)
- display.clear()
- display.appendDigit(digits)
- } else if (op == "Off") {
- Qt.quit();
- }
-
- // Reset the state on 'C' operator or after
- // an error occurred
- if (op == "C" || display.isError) {
- display.clear()
- curVal = 0
- memory = 0
- lastOp = ""
- digits = ""
- }
-}
-
diff --git a/examples/quick/demos/calqlatr/content/images/paper-edge-left.png b/examples/quick/demos/calqlatr/content/images/paper-edge-left.png
deleted file mode 100644
index ca29a3ae10..0000000000
--- a/examples/quick/demos/calqlatr/content/images/paper-edge-left.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/calqlatr/content/images/paper-edge-right.png b/examples/quick/demos/calqlatr/content/images/paper-edge-right.png
deleted file mode 100644
index 7c2da7b930..0000000000
--- a/examples/quick/demos/calqlatr/content/images/paper-edge-right.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/calqlatr/content/images/paper-grip.png b/examples/quick/demos/calqlatr/content/images/paper-grip.png
deleted file mode 100644
index 953c408bca..0000000000
--- a/examples/quick/demos/calqlatr/content/images/paper-grip.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/calqlatr/doc/images/qtquick-demo-calqlatr.png b/examples/quick/demos/calqlatr/doc/images/qtquick-demo-calqlatr.png
deleted file mode 100644
index af67f63dd1..0000000000
--- a/examples/quick/demos/calqlatr/doc/images/qtquick-demo-calqlatr.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc b/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc
deleted file mode 100644
index 02503fe3b9..0000000000
--- a/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc
+++ /dev/null
@@ -1,195 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Calqlatr
- \ingroup qtquickdemos
- \example demos/calqlatr
- \brief A QML app designed for portrait devices that uses custom components,
- animated with AnimationController, and JavaScript for the application logic.
- \image qtquick-demo-calqlatr.png
-
- \e{Calqlatr} demonstrates various QML and \l{Qt Quick} features, such as
- displaying custom components and using animation to move the components
- around in the application view. The application logic is implemented in
- JavaScript and the appearance is implemented in QML.
-
- \include examples-run.qdocinc
-
- \section1 Displaying Custom Components
-
- In the Calqlatr application, we use the following custom types that are
- each defined in a separate .qml file:
-
- \list
- \li Button.qml
- \li Display.qml
- \li NumberPad.qml
- \endlist
-
- To use the custom types, we add an import statement to the main QML file,
- calqlatr.qml that imports the folder called \c content where the types are
- located:
-
- \code
- import "content"
- \endcode
-
- We can then display custom components by adding the component types to
- any QML file. For example, we use the NumberPad type in calqlatr.qml to
- create the number pad of the calculator. We place the type inside an
- \l{Item} QML type, which is the base type for all visual items in Qt Quick:
-
- \quotefromfile demos/calqlatr/calqlatr.qml
- \skipto Item
- \printuntil }
- \printuntil }
-
- Further, we use the Button type in the \c NumberPad type to create the
- calculator buttons. Button.qml specifies the basic properties for a
- button that we can modify for each button instance in NumberPad.qml. For the
- digit and separator buttons, we additionally specify the text property using
- the property alias \c text that we define in Button.qml.
-
- For the operator buttons, we also specify another color (green) using the
- property alias \c color and set the operator property to \c true. We use
- the operator property in functions that perform the calculations.
-
- We place the buttons inside a \l{Grid} QML type to position them in a grid:
-
- \quotefromfile demos/calqlatr/content/NumberPad.qml
- \skipto Grid
- \printuntil /^\}/
-
- Some of the buttons also have a \c dimmable property set, meaning that they
- can be visually disabled (dimmed) whenever the calculator engine does not
- accept input from that button. As an example, the button for square root
- operator is dimmed for negative values.
-
- \section1 Animating Components
-
- We use the Display type to display calculations. In Display.qml, we use
- images to make the display component look like a slip of paper that contains
- a grip. Users can drag the grip to move the display from left to right.
-
- When users release the grip, the AnimationController QML type that we define
- in the calqlatr.qml file finishes running the controlled animation in either
- a forwards or a backwards direction. To run the animation, we call either
- completeToEnd() or completeToBeginning(), depending on the direction. We do
- this in the MouseArea's \c onReleased signal handler, where \c controller
- is the id of our AnimationController:
-
- \quotefromfile demos/calqlatr/calqlatr.qml
- \skipto MouseArea
- \printuntil {
- \dots 12
- \skipto onReleased
- \printuntil }
- \printuntil }
-
- Unlike other QML animation types, AnimationController is not driven by
- internal timers but by explicitly setting its progress property to a
- value between \c 0.0 and \c 1.0.
-
- Inside the AnimationController, we run two NumberAnimation instances in
- parallel to move the number pad and the display components simultaneously to
- the opposite sides of the view. In addition, we run a SequentialAnimation
- instance to scale the number pad during the transition, giving the animation
- some depth.
-
- \quotefromfile demos/calqlatr/calqlatr.qml
- \skipto AnimationController
- \printuntil 1; easing.type
- \printuntil }
- \printuntil }
- \printuntil }
-
- We use the easing curve of the type \c Easing.InOutQuad to accelerate the
- motion until halfway and then decelerate it.
-
- In Button.qml, the text colors of the number pad buttons are also animated.
-
- \quotefromfile demos/calqlatr/content/Button.qml
- \skipto Text
- \printuntil id:
- \dots 8
- \skipto color:
- \printuntil ]
- \printuntil }
-
- We use \l {QtQml::Qt::darker()}{Qt.darker()} to darken the color when the
- button is dimmed, and \l {QtQml::Qt::lighter()}{Qt.lighter()} to \e {light up}
- the button when pressed. The latter is done in a separate \l [QML] {State}
- {state} called \e "pressed", which activates when the \c pressed
- property of the button's MouseArea is set.
-
- The color changes are animated by defining a \l Behavior on the \c color
- property.
-
- In order to dynamically change the \c dimmed property of all the buttons
- of the \c NumberPad, we connect its \c buttonPressed signal to the
- \c Button's \c updateDimmed() function in Button.qml:
-
- \quotefromfile demos/calqlatr/content/Button.qml
- \skipto function updateDimmed() {
- \printuntil buttonPressed.connect
- \printuntil }
-
- This way, when a button is pressed, all buttons on the \c NumPad
- receive a \c buttonPressed signal and are activated or deactivated
- according to the state of the calculator engine.
-
- \section1 Performing Calculations
-
- The calculator.js file defines our calculator engine. It contains variables
- to store the calculator state, and functions that are called when the
- user presses the digit and operator buttons. To use the engine, we
- import calculator.js in the calqlatr.qml file as \c CalcEngine:
-
- \code
- import "content/calculator.js" as CalcEngine
- \endcode
-
- Importing the engine creates a new instance of it. Therefore, we only do it
- in the main QML file, \c calqlatr.qml. The root item defined in this file
- contains helper functions that allow other types to access the calculator
- engine:
-
- \quotefromfile demos/calqlatr/calqlatr.qml
- \skipto operatorPressed
- \printuntil CalcEngine.disabled
- \printuntil }
-
- When users press a digit, the text from the digit appears on the
- display. When they press an operator, the appropriate calculation is
- performed, and the result can be displayed using the equals (=) operator.
- The clear (C) operator resets the calculator engine.
-
- \section1 List of Files
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/calqlatr/main.cpp b/examples/quick/demos/calqlatr/main.cpp
deleted file mode 100644
index bc6e591e98..0000000000
--- a/examples/quick/demos/calqlatr/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/calqlatr/calqlatr)
diff --git a/examples/quick/demos/clocks/clocks.pro b/examples/quick/demos/clocks/clocks.pro
deleted file mode 100644
index 21d3f7f971..0000000000
--- a/examples/quick/demos/clocks/clocks.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick
-
-SOURCES += main.cpp
-RESOURCES += clocks.qrc
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/clocks
-INSTALLS += target
-
-OTHER_FILES += \
- clocks.qml \
- content/Clock.qml \
- content/*.png
diff --git a/examples/quick/demos/clocks/clocks.qml b/examples/quick/demos/clocks/clocks.qml
deleted file mode 100644
index 5224e29a38..0000000000
--- a/examples/quick/demos/clocks/clocks.qml
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "content" as Content
-
-Rectangle {
- id: root
- width: 640; height: 320
- color: "#646464"
-
- ListView {
- id: clockview
- anchors.fill: parent
- orientation: ListView.Horizontal
- cacheBuffer: 2000
- snapMode: ListView.SnapOneItem
- highlightRangeMode: ListView.ApplyRange
-
- delegate: Content.Clock { city: cityName; shift: timeShift }
- model: ListModel {
- ListElement { cityName: "New York"; timeShift: -4 }
- ListElement { cityName: "London"; timeShift: 0 }
- ListElement { cityName: "Oslo"; timeShift: 1 }
- ListElement { cityName: "Mumbai"; timeShift: 5.5 }
- ListElement { cityName: "Tokyo"; timeShift: 9 }
- ListElement { cityName: "Brisbane"; timeShift: 10 }
- ListElement { cityName: "Los Angeles"; timeShift: -8 }
- }
- }
-
- Image {
- anchors.left: parent.left
- anchors.bottom: parent.bottom
- anchors.margins: 10
- source: "content/arrow.png"
- rotation: -90
- opacity: clockview.atXBeginning ? 0 : 0.5
- Behavior on opacity { NumberAnimation { duration: 500 } }
- }
-
- Image {
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.margins: 10
- source: "content/arrow.png"
- rotation: 90
- opacity: clockview.atXEnd ? 0 : 0.5
- Behavior on opacity { NumberAnimation { duration: 500 } }
- }
-}
diff --git a/examples/quick/demos/clocks/clocks.qmlproject b/examples/quick/demos/clocks/clocks.qmlproject
deleted file mode 100644
index b15654600e..0000000000
--- a/examples/quick/demos/clocks/clocks.qmlproject
+++ /dev/null
@@ -1,8 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "clocks.qml"
- QmlFiles { directory: "." }
- JavaScriptFiles { directory: "." }
- ImageFiles { directory: "." }
-}
diff --git a/examples/quick/demos/clocks/clocks.qrc b/examples/quick/demos/clocks/clocks.qrc
deleted file mode 100644
index eaff4729ae..0000000000
--- a/examples/quick/demos/clocks/clocks.qrc
+++ /dev/null
@@ -1,15 +0,0 @@
-<RCC>
- <qresource prefix="/demos/clocks">
- <file>clocks.qml</file>
- <file>content/arrow.png</file>
- <file>content/background.png</file>
- <file>content/center.png</file>
- <file>content/clock-night.png</file>
- <file>content/clock.png</file>
- <file>content/Clock.qml</file>
- <file>content/hour.png</file>
- <file>content/minute.png</file>
- <file>content/quit.png</file>
- <file>content/second.png</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/clocks/content/Clock.qml b/examples/quick/demos/clocks/content/Clock.qml
deleted file mode 100644
index 542333d13d..0000000000
--- a/examples/quick/demos/clocks/content/Clock.qml
+++ /dev/null
@@ -1,150 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id : clock
- width: {
- if (ListView.view && ListView.view.width >= 200)
- return ListView.view.width / Math.floor(ListView.view.width / 200.0);
- else
- return 200;
- }
-
- height: {
- if (ListView.view && ListView.view.height >= 240)
- return ListView.view.height;
- else
- return 240;
- }
-
- property alias city: cityLabel.text
- property int hours
- property int minutes
- property int seconds
- property real shift
- property bool night: false
- property bool internationalTime: true //Unset for local time
-
- function timeChanged() {
- var date = new Date;
- hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours()
- night = ( hours < 7 || hours > 19 )
- minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes()
- seconds = date.getUTCSeconds();
- }
-
- Timer {
- interval: 100; running: true; repeat: true;
- onTriggered: clock.timeChanged()
- }
-
- Item {
- anchors.centerIn: parent
- width: 200; height: 240
-
- Image { id: background; source: "clock.png"; visible: clock.night == false }
- Image { source: "clock-night.png"; visible: clock.night == true }
-
-
- Image {
- x: 92.5; y: 27
- source: "hour.png"
- transform: Rotation {
- id: hourRotation
- origin.x: 7.5; origin.y: 73;
- angle: (clock.hours * 30) + (clock.minutes * 0.5)
- Behavior on angle {
- SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
- }
- }
- }
-
- Image {
- x: 93.5; y: 17
- source: "minute.png"
- transform: Rotation {
- id: minuteRotation
- origin.x: 6.5; origin.y: 83;
- angle: clock.minutes * 6
- Behavior on angle {
- SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
- }
- }
- }
-
- Image {
- x: 97.5; y: 20
- source: "second.png"
- transform: Rotation {
- id: secondRotation
- origin.x: 2.5; origin.y: 80;
- angle: clock.seconds * 6
- Behavior on angle {
- SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
- }
- }
- }
-
- Image {
- anchors.centerIn: background; source: "center.png"
- }
-
- Text {
- id: cityLabel
- y: 210; anchors.horizontalCenter: parent.horizontalCenter
- color: "white"
- font.family: "Helvetica"
- font.bold: true; font.pixelSize: 16
- style: Text.Raised; styleColor: "black"
- }
- }
-}
diff --git a/examples/quick/demos/clocks/content/arrow.png b/examples/quick/demos/clocks/content/arrow.png
deleted file mode 100644
index e437312217..0000000000
--- a/examples/quick/demos/clocks/content/arrow.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/background.png b/examples/quick/demos/clocks/content/background.png
deleted file mode 100644
index a885950862..0000000000
--- a/examples/quick/demos/clocks/content/background.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/center.png b/examples/quick/demos/clocks/content/center.png
deleted file mode 100644
index 7fbd802a44..0000000000
--- a/examples/quick/demos/clocks/content/center.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/clock-night.png b/examples/quick/demos/clocks/content/clock-night.png
deleted file mode 100644
index cc7151a397..0000000000
--- a/examples/quick/demos/clocks/content/clock-night.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/clock.png b/examples/quick/demos/clocks/content/clock.png
deleted file mode 100644
index 462edacc0e..0000000000
--- a/examples/quick/demos/clocks/content/clock.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/hour.png b/examples/quick/demos/clocks/content/hour.png
deleted file mode 100644
index 9f33fc5d48..0000000000
--- a/examples/quick/demos/clocks/content/hour.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/minute.png b/examples/quick/demos/clocks/content/minute.png
deleted file mode 100644
index e2f216c897..0000000000
--- a/examples/quick/demos/clocks/content/minute.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/quit.png b/examples/quick/demos/clocks/content/quit.png
deleted file mode 100644
index b822057d4e..0000000000
--- a/examples/quick/demos/clocks/content/quit.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/content/second.png b/examples/quick/demos/clocks/content/second.png
deleted file mode 100644
index d95d99e83d..0000000000
--- a/examples/quick/demos/clocks/content/second.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/doc/images/qtquick-demo-clocks-small.png b/examples/quick/demos/clocks/doc/images/qtquick-demo-clocks-small.png
deleted file mode 100644
index 94b641d891..0000000000
--- a/examples/quick/demos/clocks/doc/images/qtquick-demo-clocks-small.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/clocks/doc/src/clocks.qdoc b/examples/quick/demos/clocks/doc/src/clocks.qdoc
deleted file mode 100644
index a4bf1a1f82..0000000000
--- a/examples/quick/demos/clocks/doc/src/clocks.qdoc
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Clocks
- \ingroup qtquickdemos
- \example demos/clocks
- \brief A QML clock application that demonstrates using a ListView type to
- display data generated by a ListModel and a SpringAnimation type to animate
- images.
- \image qtquick-demo-clocks-small.png
-
- \e Clocks demonstrates using a ListView type to display data generated by a
- ListModel. The delegate used by the model is specified as a custom QML type
- that is specified in the Clock.qml file.
-
- JavaScript methods are used to fetch the current time in several cities in
- different time zones and QML types are used to display the time on a clock
- face with animated clock hands.
-
- \include examples-run.qdocinc
-
- \section1 Displaying Data Generated by List Models
-
- In the clocks.qml file, we use a \l Rectangle type to create the application
- main window:
-
- \quotefromfile demos/clocks/clocks.qml
- \skipto Rectangle
- \printuntil color
-
- We use a ListView type to display a list of the items provided by a
- ListModel type:
-
- \printuntil Los Angeles
- \printuntil }
- \printuntil }
-
- List elements are defined like other QML types except that they contain a
- collection of \e role definitions instead of properties. Roles both define
- how the data is accessed and include the data itself.
-
- For each list element, we use the \c cityName role to specify the name of a
- city and the \c timeShift role to specify a time zone as a positive or
- negative offset from UTC (coordinated universal time).
-
- The Clock custom type is used as the ListView's \c delegate, defining the
- visual appearance of list items. To use the Clock type, we add an import
- statement that imports the folder called \c content where the type is
- located:
-
- \quotefromfile demos/clocks/clocks.qml
- \skipto content
- \printuntil "
-
- We use an \l Image type to display arrows that indicate whether users can
- flick the view to see more clocks on the left or right:
-
- \quotefromfile demos/clocks/clocks.qml
- \skipto Image
- \printuntil /^\}/
-
- We use the \c opacity property to hide the arrows when the list view is
- located at the beginning or end of the x axis.
-
- In Clock.qml, we define a \c timeChanged() function in which we use
- methods from the JavaScript \c Date object to fetch the current time in
- UTC and to adjust it to the correct time zone:
-
- \quotefromfile demos/clocks/content/Clock.qml
- \skipto timeChanged
- \printuntil }
-
- We use a \l Timer type to update the time at intervals of 100 milliseconds:
-
- \printuntil }
-
- We use \l Image types within an \l Item type to display the time on an
- analog clock face. Different images are used for daytime and nighttime
- hours:
-
- \printuntil clock-night.png
-
- A \l Rotation transform applied to \l Image types provides a way to rotate
- the clock hands. The \c origin property holds the point that stays fixed
- relative to the parent as the rest of the item rotates. The \c angle
- property determines the angle to rotate the hands in degrees clockwise.
-
- \printuntil center.png
- \printuntil }
-
- We use a \l Behavior type on the \c angle property to apply a
- SpringAnimation when the time changes. The \c spring and \c damping
- properties enable the spring-like motion of the clock hands, and a
- \c modulus of \c 360 makes the animation target values wrap around at a
- full circle.
-
- We use a \l Text type to display the city name below the clock:
-
- \printuntil }
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/clocks/main.cpp b/examples/quick/demos/clocks/main.cpp
deleted file mode 100644
index 5d5b0ca64d..0000000000
--- a/examples/quick/demos/clocks/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/clocks/clocks)
diff --git a/examples/quick/demos/demos.pro b/examples/quick/demos/demos.pro
deleted file mode 100644
index 0644b81a22..0000000000
--- a/examples/quick/demos/demos.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = samegame \
- calqlatr \
- clocks \
- tweetsearch \
- maroon \
- photosurface \
- stocqt
-
-qtHaveModule(xmlpatterns): SUBDIRS += rssnews photoviewer
-
diff --git a/examples/quick/demos/maroon/content/BuildButton.qml b/examples/quick/demos/maroon/content/BuildButton.qml
deleted file mode 100644
index 09d37746f1..0000000000
--- a/examples/quick/demos/maroon/content/BuildButton.qml
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "logic.js" as Logic
-
-Item {
- id: container
- width: 64
- height: 64
- property alias source: img.source
- property int index
- property int row: 0
- property int col: 0
- property int towerType
- property bool canBuild: true
- property Item gameCanvas: parent.parent.parent
- signal clicked()
-
- Image {
- id: img
- opacity: (canBuild && gameCanvas.coins >= Logic.towerData[towerType-1].cost) ? 1.0 : 0.4
- }
- Text {
- anchors.right: parent.right
- font.pointSize: 14
- font.bold: true
- color: "#ffffff"
- text: Logic.towerData[towerType - 1].cost
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- Logic.buildTower(towerType, col, row)
- container.clicked()
- }
- }
- Image {
- visible: col == index && row != 0
- source: "gfx/dialog-pointer.png"
- anchors.top: parent.bottom
- anchors.topMargin: 4
- anchors.horizontalCenter: parent.horizontalCenter
- }
- Image {
- visible: col == index && row == 0
- source: "gfx/dialog-pointer.png"
- rotation: 180
- anchors.bottom: parent.top
- anchors.bottomMargin: 6
- anchors.horizontalCenter: parent.horizontalCenter
- }
-}
diff --git a/examples/quick/demos/maroon/content/GameCanvas.qml b/examples/quick/demos/maroon/content/GameCanvas.qml
deleted file mode 100644
index 0c6772dc98..0000000000
--- a/examples/quick/demos/maroon/content/GameCanvas.qml
+++ /dev/null
@@ -1,250 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "logic.js" as Logic
-import "towers" as Towers
-
-Item {
- id: grid
-
- property int squareSize: 64
- property int rows: 6
- property int cols: 4
- property Item canvas: grid
- property int score: 0
- property int coins: 100
- property int lives: 3
- property int waveNumber: 0
- property int waveProgress: 0
- property var towers
- property var mobs
- property bool gameRunning: false
- property bool gameOver: false
- property bool errored: false
- property string errorString: ""
-
- width: cols * squareSize
- height: rows * squareSize
-
- function freshState() {
- lives = 3
- coins = 100
- score = 0
- waveNumber = 0
- waveProgress = 0
- gameOver = false
- gameRunning = false
- towerMenu.shown = false
- helpButton.comeBack();
- }
-
- Text {
- id: errorText // Mostly for debug purposes
- text: errorString
- visible: errored
- color: "red"
- font.pixelSize: 18
- wrapMode: Text.WordWrap
- width: parent.width / 1.2
- height: parent.height / 1.2
- anchors.centerIn: parent
- z: 1000
- }
-
- Timer {
- interval: 16
- running: true
- repeat: true
- onTriggered: Logic.tick()
- }
-
- MouseArea {
- id: ma
- anchors.fill: parent
- onClicked: {
- if (towerMenu.visible)
- towerMenu.finish()
- else
- towerMenu.open(mouse.x, mouse.y)
- }
- }
-
- Image {
- id: towerMenu
- visible: false
- z: 1500
- scale: 0.9
- opacity: 0.7
- property int dragDistance: 16
- property int targetRow: 0
- property int targetCol: 0
- property bool shown: false
- property bool towerExists: false
-
- function finish() {
- shown = false
- }
-
- function open(xp,yp) {
- if (!grid.gameRunning)
- return
- targetRow = Logic.row(yp)
- targetCol = Logic.col(xp)
- if (targetRow == 0)
- towerMenu.y = (targetRow + 1) * grid.squareSize
- else
- towerMenu.y = (targetRow - 1) * grid.squareSize
- towerExists = (grid.towers[Logic.towerIdx(targetCol, targetRow)] != null)
- shown = true
- helpButton.goAway();
- }
-
- states: State {
- name: "shown"; when: towerMenu.shown && !grid.gameOver
- PropertyChanges { target: towerMenu; visible: true; scale: 1; opacity: 1 }
- }
-
- transitions: Transition {
- PropertyAction { property: "visible" }
- NumberAnimation { properties: "opacity,scale"; duration: 500; easing.type: Easing.OutElastic }
- }
-
- x: -32
- source: "gfx/dialog.png"
- Row {
- id: buttonRow
- height: 100
- anchors.centerIn: parent
- spacing: 8
- BuildButton {
- row: towerMenu.targetRow; col: towerMenu.targetCol
- anchors.verticalCenter: parent.verticalCenter
- towerType: 1; index: 0
- canBuild: !towerMenu.towerExists
- source: "gfx/dialog-melee.png"
- onClicked: towerMenu.finish()
- }
- BuildButton {
- row: towerMenu.targetRow; col: towerMenu.targetCol
- anchors.verticalCenter: parent.verticalCenter
- towerType: 2; index: 1
- canBuild: !towerMenu.towerExists
- source: "gfx/dialog-shooter.png"
- onClicked: towerMenu.finish()
- }
- BuildButton {
- row: towerMenu.targetRow; col: towerMenu.targetCol
- anchors.verticalCenter: parent.verticalCenter
- towerType: 3; index: 2
- canBuild: !towerMenu.towerExists
- source: "gfx/dialog-bomb.png"
- onClicked: towerMenu.finish()
- }
- BuildButton {
- row: towerMenu.targetRow; col: towerMenu.targetCol
- anchors.verticalCenter: parent.verticalCenter
- towerType: 4; index: 3
- canBuild: !towerMenu.towerExists
- source: "gfx/dialog-factory.png"
- onClicked: towerMenu.finish()
- }
- }
- }
-
-
- Keys.onPressed: { // Cheat Codes while Testing
- if (event.key == Qt.Key_Up && (event.modifiers & Qt.ShiftModifier))
- grid.coins += 10;
- if (event.key == Qt.Key_Left && (event.modifiers & Qt.ShiftModifier))
- grid.lives += 1;
- if (event.key == Qt.Key_Down && (event.modifiers & Qt.ShiftModifier))
- Logic.gameState.waveProgress += 1000;
- if (event.key == Qt.Key_Right && (event.modifiers & Qt.ShiftModifier))
- Logic.endGame();
- }
-
- Image {
- id: helpButton
- z: 1010
- source: "gfx/button-help.png"
- function goAway() {
- helpMA.enabled = false;
- helpButton.opacity = 0;
- }
- function comeBack() {
- helpMA.enabled = true;
- helpButton.opacity = 1;
- }
- Behavior on opacity { NumberAnimation {} }
- MouseArea {
- id: helpMA
- anchors.fill: parent
- onClicked: {helpImage.visible = true; helpButton.visible = false;}
- }
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 0
- }
-
- Image {
- id: helpImage
- z: 1010
- source: "gfx/help.png"
- anchors.fill: parent
- visible: false
- MouseArea {
- anchors.fill: parent
- onClicked: helpImage.visible = false;
- }
- }
-
-}
diff --git a/examples/quick/demos/maroon/content/GameOverScreen.qml b/examples/quick/demos/maroon/content/GameOverScreen.qml
deleted file mode 100644
index 6de3b13bad..0000000000
--- a/examples/quick/demos/maroon/content/GameOverScreen.qml
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-import "logic.js" as Logic
-
-Item {
- id: gameOverScreen
- width: 320
- height: 400
- property GameCanvas gameCanvas
-
- Image {
- id: img
- source: "gfx/text-gameover.png"
- anchors.centerIn: parent
- }
-
- ParticleSystem {
- anchors.fill: parent
- ImageParticle {
- id: cloud
- source: "gfx/cloud.png"
- alphaVariation: 0.25
- opacity: 0.25
- }
-
- Wander {
- xVariance: 100;
- pace: 1;
- }
-
- Emitter {
- id: cloudLeft
- width: 160
- height: 160
- anchors.right: parent.left
- emitRate: 0.5
- lifeSpan: 12000
- velocity: PointDirection{ x: 64; xVariation: 2; yVariation: 2 }
- size: 160
- }
-
- Emitter {
- id: cloudRight
- width: 160
- height: 160
- anchors.left: parent.right
- emitRate: 0.5
- lifeSpan: 12000
- velocity: PointDirection{ x: -64; xVariation: 2; yVariation: 2 }
- size: 160
- }
- }
-
-
- Text {
- visible: gameCanvas != undefined
- text: "You saved " + gameCanvas.score + " fishes!"
- anchors.top: img.bottom
- anchors.topMargin: 12
- anchors.horizontalCenter: parent.horizontalCenter
- font.bold: true
- color: "#000000"
- opacity: 0.5
- }
-
- Image {
- source: "gfx/button-play.png"
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 0
- MouseArea {
- anchors.fill: parent
- onClicked: gameCanvas.gameOver = false//This will actually trigger the state change in main.qml
- }
- }
-}
diff --git a/examples/quick/demos/maroon/content/InfoBar.qml b/examples/quick/demos/maroon/content/InfoBar.qml
deleted file mode 100644
index 8176b1a37e..0000000000
--- a/examples/quick/demos/maroon/content/InfoBar.qml
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- height: childrenRect.height
-
- // Display the number of lives
- Row {
- anchors.left: parent.left
- anchors.leftMargin: 10
- spacing: 5
- Repeater {
- id: rep
- model: Math.min(10, canvas.lives)
- delegate: Image { source: "gfx/lifes.png" }
- }
- }
-
- // Display the number of fishes saved
- Row {
- anchors.right: points.left
- anchors.rightMargin: 20
- spacing: 5
- Image { source: "gfx/scores.png" }
- Text {
- text: canvas.score
- font.bold: true
- }
- }
-
- // Display the number of coins
- Row {
- id: points
- anchors.right: parent.right
- anchors.rightMargin: 10
- spacing: 5
- Image { source: "gfx/points.png" }
- Text {
- id: pointsLabel
- text: canvas.coins
- font.bold: true
- }
- }
-}
-
diff --git a/examples/quick/demos/maroon/content/NewGameScreen.qml b/examples/quick/demos/maroon/content/NewGameScreen.qml
deleted file mode 100644
index d87e6b36f7..0000000000
--- a/examples/quick/demos/maroon/content/NewGameScreen.qml
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-// This is the first screen.
-// It shows the logo and emit a startButtonClicked signal
-// when the user press the "PLAY" button.
-
-Item {
- id: newGameScreen
- width: 320
- height: 480
-
- signal startButtonClicked
-
- Image {
- source: "gfx/logo.png"
- anchors.top: parent.top
- anchors.topMargin: 60
- }
-
- Image {
- source: "gfx/logo-fish.png"
- anchors.top: parent.top
-
- SequentialAnimation on x {
- loops: Animation.Infinite
- NumberAnimation { from: x + 148; to: x + 25; duration: 2000; easing.type: Easing.InOutQuad }
- NumberAnimation { from: x + 25; to: x + 148; duration: 1600; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on anchors.topMargin {
- loops: Animation.Infinite
- NumberAnimation { from: 100; to: 60; duration: 1600; easing.type: Easing.InOutQuad }
- NumberAnimation { from: 60; to: 100; duration: 2000; easing.type: Easing.InOutQuad }
- }
- }
-
- Image {
- source: "gfx/logo-bubble.png"
- anchors.top: parent.top
-
- SequentialAnimation on x {
- loops: Animation.Infinite
- NumberAnimation { from: x + 140; to: x + 40; duration: 2000; easing.type: Easing.InOutQuad }
- NumberAnimation { from: x + 40; to: x + 140; duration: 1600; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on anchors.topMargin {
- loops: Animation.Infinite
- NumberAnimation { from: 100; to: 60; duration: 1600; easing.type: Easing.InOutQuad }
- NumberAnimation { from: 60; to: 100; duration: 2000; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on width {
- loops: Animation.Infinite
- NumberAnimation { from: 140; to: 160; duration: 1000; easing.type: Easing.InOutQuad }
- NumberAnimation { from: 160; to: 140; duration: 800; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on height {
- loops: Animation.Infinite
- NumberAnimation { from: 150; to: 140; duration: 800; easing.type: Easing.InOutQuad }
- NumberAnimation { from: 140; to: 150; duration: 1000; easing.type: Easing.InOutQuad }
- }
- }
-
- Image {
- source: "gfx/button-play.png"
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 60
- MouseArea {
- anchors.fill: parent
- onClicked: newGameScreen.startButtonClicked()
- }
- }
-}
diff --git a/examples/quick/demos/maroon/content/SoundEffect.qml b/examples/quick/demos/maroon/content/SoundEffect.qml
deleted file mode 100644
index 35a68eb5e0..0000000000
--- a/examples/quick/demos/maroon/content/SoundEffect.qml
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-//Proxies a SoundEffect if QtMultimedia is installed
-Item {
- id: container
- property QtObject effect: Qt.createQmlObject("import QtMultimedia 5.0; SoundEffect{ source: '" + container.source + "'; muted: Qt.application.state != Qt.ApplicationActive }", container);
- property url source: ""
- onSourceChanged: if (effect != null) effect.source = source;
- function play() {
- if (effect != null)
- effect.play();
- }
-}
diff --git a/examples/quick/demos/maroon/content/audio/bomb-action.wav b/examples/quick/demos/maroon/content/audio/bomb-action.wav
deleted file mode 100644
index b334dc1e5b..0000000000
--- a/examples/quick/demos/maroon/content/audio/bomb-action.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/catch-action.wav b/examples/quick/demos/maroon/content/audio/catch-action.wav
deleted file mode 100644
index 3e22124abf..0000000000
--- a/examples/quick/demos/maroon/content/audio/catch-action.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/catch.wav b/examples/quick/demos/maroon/content/audio/catch.wav
deleted file mode 100644
index d3eade87f8..0000000000
--- a/examples/quick/demos/maroon/content/audio/catch.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/currency.wav b/examples/quick/demos/maroon/content/audio/currency.wav
deleted file mode 100644
index 0d9ef2c200..0000000000
--- a/examples/quick/demos/maroon/content/audio/currency.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/factory-action.wav b/examples/quick/demos/maroon/content/audio/factory-action.wav
deleted file mode 100644
index a2ace6c221..0000000000
--- a/examples/quick/demos/maroon/content/audio/factory-action.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/melee-action.wav b/examples/quick/demos/maroon/content/audio/melee-action.wav
deleted file mode 100644
index d325af4700..0000000000
--- a/examples/quick/demos/maroon/content/audio/melee-action.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/projectile-action.wav b/examples/quick/demos/maroon/content/audio/projectile-action.wav
deleted file mode 100644
index 4e2284fceb..0000000000
--- a/examples/quick/demos/maroon/content/audio/projectile-action.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/audio/shooter-action.wav b/examples/quick/demos/maroon/content/audio/shooter-action.wav
deleted file mode 100644
index 3e12b9419a..0000000000
--- a/examples/quick/demos/maroon/content/audio/shooter-action.wav
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/background.png b/examples/quick/demos/maroon/content/gfx/background.png
deleted file mode 100644
index d548b9314e..0000000000
--- a/examples/quick/demos/maroon/content/gfx/background.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/bomb-action.png b/examples/quick/demos/maroon/content/gfx/bomb-action.png
deleted file mode 100644
index 42da5d789f..0000000000
--- a/examples/quick/demos/maroon/content/gfx/bomb-action.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/bomb-idle.png b/examples/quick/demos/maroon/content/gfx/bomb-idle.png
deleted file mode 100644
index 3bd62e261d..0000000000
--- a/examples/quick/demos/maroon/content/gfx/bomb-idle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/bomb.png b/examples/quick/demos/maroon/content/gfx/bomb.png
deleted file mode 100644
index 380da7d1a5..0000000000
--- a/examples/quick/demos/maroon/content/gfx/bomb.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/button-help.png b/examples/quick/demos/maroon/content/gfx/button-help.png
deleted file mode 100644
index aecebc1275..0000000000
--- a/examples/quick/demos/maroon/content/gfx/button-help.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/button-play.png b/examples/quick/demos/maroon/content/gfx/button-play.png
deleted file mode 100644
index 6cdad6c845..0000000000
--- a/examples/quick/demos/maroon/content/gfx/button-play.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/catch-action.png b/examples/quick/demos/maroon/content/gfx/catch-action.png
deleted file mode 100644
index 78ca9fe1cc..0000000000
--- a/examples/quick/demos/maroon/content/gfx/catch-action.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/catch.png b/examples/quick/demos/maroon/content/gfx/catch.png
deleted file mode 100644
index b7620fe3de..0000000000
--- a/examples/quick/demos/maroon/content/gfx/catch.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/cloud.png b/examples/quick/demos/maroon/content/gfx/cloud.png
deleted file mode 100644
index d7c35f8555..0000000000
--- a/examples/quick/demos/maroon/content/gfx/cloud.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/currency.png b/examples/quick/demos/maroon/content/gfx/currency.png
deleted file mode 100644
index 1571341f6c..0000000000
--- a/examples/quick/demos/maroon/content/gfx/currency.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/dialog-bomb.png b/examples/quick/demos/maroon/content/gfx/dialog-bomb.png
deleted file mode 100644
index 708d916ad7..0000000000
--- a/examples/quick/demos/maroon/content/gfx/dialog-bomb.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/dialog-factory.png b/examples/quick/demos/maroon/content/gfx/dialog-factory.png
deleted file mode 100644
index d2e2a48e31..0000000000
--- a/examples/quick/demos/maroon/content/gfx/dialog-factory.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/dialog-melee.png b/examples/quick/demos/maroon/content/gfx/dialog-melee.png
deleted file mode 100644
index 069d18d477..0000000000
--- a/examples/quick/demos/maroon/content/gfx/dialog-melee.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/dialog-pointer.png b/examples/quick/demos/maroon/content/gfx/dialog-pointer.png
deleted file mode 100644
index 9b51a090f9..0000000000
--- a/examples/quick/demos/maroon/content/gfx/dialog-pointer.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/dialog-shooter.png b/examples/quick/demos/maroon/content/gfx/dialog-shooter.png
deleted file mode 100644
index af980caabd..0000000000
--- a/examples/quick/demos/maroon/content/gfx/dialog-shooter.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/dialog.png b/examples/quick/demos/maroon/content/gfx/dialog.png
deleted file mode 100644
index d528ba78d1..0000000000
--- a/examples/quick/demos/maroon/content/gfx/dialog.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/factory-action.png b/examples/quick/demos/maroon/content/gfx/factory-action.png
deleted file mode 100644
index 8981678267..0000000000
--- a/examples/quick/demos/maroon/content/gfx/factory-action.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/factory-idle.png b/examples/quick/demos/maroon/content/gfx/factory-idle.png
deleted file mode 100644
index a145582c8f..0000000000
--- a/examples/quick/demos/maroon/content/gfx/factory-idle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/factory.png b/examples/quick/demos/maroon/content/gfx/factory.png
deleted file mode 100644
index bfb9f3fb79..0000000000
--- a/examples/quick/demos/maroon/content/gfx/factory.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/grid.png b/examples/quick/demos/maroon/content/gfx/grid.png
deleted file mode 100644
index b59555247a..0000000000
--- a/examples/quick/demos/maroon/content/gfx/grid.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/help.png b/examples/quick/demos/maroon/content/gfx/help.png
deleted file mode 100644
index 4654e4c69b..0000000000
--- a/examples/quick/demos/maroon/content/gfx/help.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/lifes.png b/examples/quick/demos/maroon/content/gfx/lifes.png
deleted file mode 100644
index 135310b38c..0000000000
--- a/examples/quick/demos/maroon/content/gfx/lifes.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/logo-bubble.png b/examples/quick/demos/maroon/content/gfx/logo-bubble.png
deleted file mode 100644
index 136151caff..0000000000
--- a/examples/quick/demos/maroon/content/gfx/logo-bubble.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/logo-fish.png b/examples/quick/demos/maroon/content/gfx/logo-fish.png
deleted file mode 100644
index c41833a0c9..0000000000
--- a/examples/quick/demos/maroon/content/gfx/logo-fish.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/logo.png b/examples/quick/demos/maroon/content/gfx/logo.png
deleted file mode 100644
index 787ac99ce8..0000000000
--- a/examples/quick/demos/maroon/content/gfx/logo.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/melee-action.png b/examples/quick/demos/maroon/content/gfx/melee-action.png
deleted file mode 100644
index c53873bfcc..0000000000
--- a/examples/quick/demos/maroon/content/gfx/melee-action.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/melee-idle.png b/examples/quick/demos/maroon/content/gfx/melee-idle.png
deleted file mode 100644
index 621d9dff54..0000000000
--- a/examples/quick/demos/maroon/content/gfx/melee-idle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/melee.png b/examples/quick/demos/maroon/content/gfx/melee.png
deleted file mode 100644
index ab240151f3..0000000000
--- a/examples/quick/demos/maroon/content/gfx/melee.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/mob-idle.png b/examples/quick/demos/maroon/content/gfx/mob-idle.png
deleted file mode 100644
index dedacc7866..0000000000
--- a/examples/quick/demos/maroon/content/gfx/mob-idle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/mob.png b/examples/quick/demos/maroon/content/gfx/mob.png
deleted file mode 100644
index 7569c3525a..0000000000
--- a/examples/quick/demos/maroon/content/gfx/mob.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/points.png b/examples/quick/demos/maroon/content/gfx/points.png
deleted file mode 100644
index 1d2386dbe7..0000000000
--- a/examples/quick/demos/maroon/content/gfx/points.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/projectile-action.png b/examples/quick/demos/maroon/content/gfx/projectile-action.png
deleted file mode 100644
index aa2e650aeb..0000000000
--- a/examples/quick/demos/maroon/content/gfx/projectile-action.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/projectile.png b/examples/quick/demos/maroon/content/gfx/projectile.png
deleted file mode 100644
index c25a0c3890..0000000000
--- a/examples/quick/demos/maroon/content/gfx/projectile.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/scores.png b/examples/quick/demos/maroon/content/gfx/scores.png
deleted file mode 100644
index af757fe64a..0000000000
--- a/examples/quick/demos/maroon/content/gfx/scores.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/shooter-action.png b/examples/quick/demos/maroon/content/gfx/shooter-action.png
deleted file mode 100644
index 08e7e300ca..0000000000
--- a/examples/quick/demos/maroon/content/gfx/shooter-action.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/shooter-idle.png b/examples/quick/demos/maroon/content/gfx/shooter-idle.png
deleted file mode 100644
index 663098d3b0..0000000000
--- a/examples/quick/demos/maroon/content/gfx/shooter-idle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/shooter.png b/examples/quick/demos/maroon/content/gfx/shooter.png
deleted file mode 100644
index d44401e055..0000000000
--- a/examples/quick/demos/maroon/content/gfx/shooter.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/sunlight.png b/examples/quick/demos/maroon/content/gfx/sunlight.png
deleted file mode 100644
index d1c7042117..0000000000
--- a/examples/quick/demos/maroon/content/gfx/sunlight.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/text-1.png b/examples/quick/demos/maroon/content/gfx/text-1.png
deleted file mode 100644
index 3ea399cc90..0000000000
--- a/examples/quick/demos/maroon/content/gfx/text-1.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/text-2.png b/examples/quick/demos/maroon/content/gfx/text-2.png
deleted file mode 100644
index 934a481f3b..0000000000
--- a/examples/quick/demos/maroon/content/gfx/text-2.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/text-3.png b/examples/quick/demos/maroon/content/gfx/text-3.png
deleted file mode 100644
index 47523f55b8..0000000000
--- a/examples/quick/demos/maroon/content/gfx/text-3.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/text-blank.png b/examples/quick/demos/maroon/content/gfx/text-blank.png
deleted file mode 100644
index 4a687b24dc..0000000000
--- a/examples/quick/demos/maroon/content/gfx/text-blank.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/text-gameover.png b/examples/quick/demos/maroon/content/gfx/text-gameover.png
deleted file mode 100644
index 4f53ef0b29..0000000000
--- a/examples/quick/demos/maroon/content/gfx/text-gameover.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/text-go.png b/examples/quick/demos/maroon/content/gfx/text-go.png
deleted file mode 100644
index bfc26f71fc..0000000000
--- a/examples/quick/demos/maroon/content/gfx/text-go.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/gfx/wave.png b/examples/quick/demos/maroon/content/gfx/wave.png
deleted file mode 100644
index f97426c4e7..0000000000
--- a/examples/quick/demos/maroon/content/gfx/wave.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/content/logic.js b/examples/quick/demos/maroon/content/logic.js
deleted file mode 100644
index 3830b5ad63..0000000000
--- a/examples/quick/demos/maroon/content/logic.js
+++ /dev/null
@@ -1,274 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-.pragma library // Shared game state
-.import QtQuick 2.0 as QQ
-
-// Game Stuff
-var gameState // Local reference
-function getGameState() { return gameState; }
-
-var towerData = [ // Name and cost, stats are in the delegate per instance
- { "name": "Melee", "cost": 20 },
- { "name": "Ranged", "cost": 50 },
- { "name": "Bomb", "cost": 75 },
- { "name": "Factory", "cost": 25 }
-]
-
-var waveBaseData = [300, 290, 280, 270, 220, 180, 160, 80, 80, 80, 30, 30, 30, 30];
-var waveData = [];
-
-var towerComponents = new Array(towerData.length);
-var mobComponent = Qt.createComponent("mobs/MobBase.qml");
-
-function endGame()
-{
- gameState.gameRunning = false;
- gameState.gameOver = true;
- for (var i = 0; i < gameState.cols; i++) {
- for (var j = 0; j < gameState.rows; j++) {
- if (gameState.towers[towerIdx(i, j)]) {
- gameState.towers[towerIdx(i, j)].destroy();
- gameState.towers[towerIdx(i, j)] = null;
- }
- }
- for (var j in gameState.mobs[i])
- gameState.mobs[i][j].destroy();
- gameState.mobs[i].splice(0,gameState.mobs[i].length); //Leaves queue reusable
- }
-}
-
-function startGame(gameCanvas)
-{
- waveData = new Array();
- for (var i in waveBaseData)
- waveData[i] = waveBaseData[i];
- gameState.freshState();
- for (var i = 0; i < gameCanvas.cols; i++) {
- for (var j = 0; j < gameCanvas.rows; j++)
- gameState.towers[towerIdx(i, j)] = null;
- gameState.mobs[i] = new Array();
- }
- gameState.towers[towerIdx(0, 0)] = newTower(3, 0, 0);//Start with a starfish in the corner
- gameState.gameRunning = true;
- gameState.gameOver = false;
-}
-
-function newGameState(gameCanvas)
-{
- for (var i = 0; i < towerComponents.length; i++) {
- towerComponents[i] = Qt.createComponent("towers/" + towerData[i].name + ".qml");
- if (towerComponents[i].status == QQ.Component.Error) {
- gameCanvas.errored = true;
- gameCanvas.errorString += "Loading Tower " + towerData[i].name + "\n" + (towerComponents[i].errorString());
- console.log(towerComponents[i].errorString());
- }
- }
- gameState = gameCanvas;
- gameState.freshState();
- gameState.towers = new Array(gameCanvas.rows * gameCanvas.cols);
- gameState.mobs = new Array(gameCanvas.cols);
- return gameState;
-}
-
-function row(y)
-{
- return Math.floor(y / gameState.squareSize);
-}
-
-function col(x)
-{
- return Math.floor(x / gameState.squareSize);
-}
-
-function towerIdx(x, y)
-{
- return y + (x * gameState.rows);
-}
-
-function newMob(col)
-{
- var ret = mobComponent.createObject(gameState.canvas,
- { "col" : col,
- "speed" : (Math.min(2.0, 0.10 * (gameState.waveNumber + 1))),
- "y" : gameState.canvas.height });
- gameState.mobs[col].push(ret);
- return ret;
-}
-
-function newTower(type, row, col)
-{
- var ret = towerComponents[type].createObject(gameState.canvas);
- ret.row = row;
- ret.col = col;
- ret.fireCounter = ret.rof;
- ret.spawn();
- return ret;
-}
-
-function buildTower(type, x, y)
-{
- if (gameState.towers[towerIdx(x,y)] != null) {
- if (type <= 0) {
- gameState.towers[towerIdx(x,y)].sell();
- gameState.towers[towerIdx(x,y)] = null;
- }
- } else {
- if (gameState.coins < towerData[type - 1].cost)
- return;
- gameState.towers[towerIdx(x, y)] = newTower(type - 1, y, x);
- gameState.coins -= towerData[type - 1].cost;
- }
-}
-
-function killMob(col, mob)
-{
- if (!mob)
- return;
- var idx = gameState.mobs[col].indexOf(mob);
- if (idx == -1 || !mob.hp)
- return;
- mob.hp = 0;
- mob.die();
- gameState.mobs[col].splice(idx,1);
-}
-
-function killTower(row, col)
-{
- var tower = gameState.towers[towerIdx(col, row)];
- if (!tower)
- return;
- tower.hp = 0;
- tower.die();
- gameState.towers[towerIdx(col, row)] = null;
-}
-
-function tick()
-{
- if (!gameState.gameRunning)
- return;
-
- // Spawn
- gameState.waveProgress += 1;
- var i = gameState.waveProgress;
- var j = 0;
- while (i > 0 && j < waveData.length)
- i -= waveData[j++];
- if ( i == 0 ) // Spawn a mob
- newMob(Math.floor(Math.random() * gameState.cols));
- if ( j == waveData.length ) { // Next Wave
- gameState.waveNumber += 1;
- gameState.waveProgress = 0;
- var waveModifier = 10; // Constant governing how much faster the next wave is to spawn (not fish speed)
- for (var k in waveData ) // Slightly faster
- if (waveData[k] > waveModifier)
- waveData[k] -= waveModifier;
- }
-
- // Towers Attack
- for (var j in gameState.towers) {
- var tower = gameState.towers[j];
- if (tower == null)
- continue;
- if (tower.fireCounter > 0) {
- tower.fireCounter -= 1;
- continue;
- }
- var column = tower.col;
- for (var k in gameState.mobs[column]) {
- var conflict = gameState.mobs[column][k];
- if (conflict.y <= gameState.canvas.height && conflict.y + conflict.height > tower.y
- && conflict.y - ((tower.row + 1) * gameState.squareSize) < gameState.squareSize * tower.range) { // In Range
- tower.fire();
- tower.fireCounter = tower.rof;
- conflict.hit(tower.damage);
- }
- }
-
- // Income
- if (tower.income) {
- gameState.coins += tower.income;
- tower.fire();
- tower.fireCounter = tower.rof;
- }
- }
-
- // Mobs move
- for (var i = 0; i < gameState.cols; i++) {
- for (var j = 0; j < gameState.mobs[i].length; j++) {
- var mob = gameState.mobs[i][j];
- var newPos = gameState.mobs[i][j].y - gameState.mobs[i][j].speed;
- if (newPos < 0) {
- gameState.lives -= 1;
- killMob(i, mob);
- if (gameState.lives <= 0)
- endGame();
- continue;
- }
- var conflict = gameState.towers[towerIdx(i, row(newPos))];
- if (conflict != null) {
- if (mob.y < conflict.y + gameState.squareSize)
- gameState.mobs[i][j].y += gameState.mobs[i][j].speed * 10; // Moved inside tower, now hurry back out
- if (mob.fireCounter > 0) {
- mob.fireCounter--;
- } else {
- gameState.mobs[i][j].fire();
- conflict.hp -= mob.damage;
- if (conflict.hp <= 0)
- killTower(conflict.row, conflict.col);
- mob.fireCounter = mob.rof;
- }
- } else {
- gameState.mobs[i][j].y = newPos;
- }
- }
- }
-
-}
diff --git a/examples/quick/demos/maroon/content/mobs/MobBase.qml b/examples/quick/demos/maroon/content/mobs/MobBase.qml
deleted file mode 100644
index 584623fa77..0000000000
--- a/examples/quick/demos/maroon/content/mobs/MobBase.qml
+++ /dev/null
@@ -1,272 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "../logic.js" as Logic
-import ".."
-
-Item {
- id: container
- property string name: "Fish"
- property int col: 0
- property real hp: 3
- property real damage: 1
- property real speed: 0.25
- property int rof: 30 //In ticks
- property int fireCounter: 0
- property bool dying: false
- width: parent ? parent.squareSize : 0
- height: parent ? parent.squareSize : 0
- x: col * width
- z: 1001
- function fire() { }
-
- function die() {
- if (dying)
- return;
- dying = true;
- bubble.jumpTo("burst");
- if (fishSprite.currentSprite == "front")
- fishSprite.jumpTo(Math.random() > 0.5 ? "left" : "right" );
- fishSwim.start();
- Logic.gameState.score += 1;
- killedSound.play();
- bubble.scale = 0.9
- destroy(350);
- }
-
- function inked() {
- if (hp > 0)
- ink.jumpTo("dirty");
- }
-
- function hit(dmg) {
- hp -= dmg;
-
- if (hp <= 0)
- Logic.killMob(col, container);
- }
-
- Component.onCompleted: spawnSound.play()
-
- SoundEffect {
- id: spawnSound
- source: "../audio/catch.wav"
- }
- SoundEffect {
- id: killedSound
- source: "../audio/catch-action.wav"
- }
-
- SpriteSequence {
- id: fishSprite
- width: 64
- height: 64
- interpolate: false
- goalSprite: ""
-
- Sprite {
- name: "left"
- source: "../gfx/mob-idle.png"
- frameWidth: 64
- frameHeight: 64
- frameCount: 1
- frameDuration: 800
- frameDurationVariation: 400
- to: { "front" : 1 }
- }
-
- Sprite {
- name: "front"
- source: "../gfx/mob-idle.png"
- frameCount: 1
- frameX: 64
- frameWidth: 64
- frameHeight: 64
- frameDuration: 800
- frameDurationVariation: 400
- to: { "left" : 1, "right" : 1 }
- }
-
- Sprite {
- name: "right"
- source: "../gfx/mob-idle.png"
- frameCount: 1
- frameX: 128
- frameWidth: 64
- frameHeight: 64
- frameDuration: 800
- frameDurationVariation: 400
- to: { "front" : 1 }
- }
-
-
- Sprite { //WORKAROUND: This prevents the triggering of a rendering error which is currently under investigation.
- name: "dummy"
- source: "../gfx/melee-idle.png"
- frameCount: 8
- frameWidth: 64
- frameHeight: 64
- frameX: 0
- frameDuration: 200
- }
-
- NumberAnimation on x {
- id: fishSwim
- running: false
- property bool goingLeft: fishSprite.currentSprite == "right"
- to: goingLeft ? -360 : 360
- duration: 300
- }
- }
-
- SpriteSequence {
- id: bubble
- width: 64
- height: 64
- scale: 0.4 + (0.2 * hp)
- interpolate: false
- goalSprite: ""
-
- Behavior on scale {
- NumberAnimation { duration: 150; easing.type: Easing.OutBack }
- }
-
- Sprite {
- name: "big"
- source: "../gfx/catch.png"
- frameCount: 1
- to: { "burst" : 0 }
- }
-
- Sprite {
- name: "burst"
- source: "../gfx/catch-action.png"
- frameCount: 3
- frameX: 64
- frameDuration: 200
- }
-
- Sprite { //WORKAROUND: This prevents the triggering of a rendering error which is currently under investigation.
- name: "dummy"
- source: "../gfx/melee-idle.png"
- frameCount: 8
- frameWidth: 64
- frameHeight: 64
- frameX: 0
- frameDuration: 200
- }
- SequentialAnimation on width {
- loops: Animation.Infinite
- NumberAnimation { from: width * 1; to: width * 1.1; duration: 800; easing.type: Easing.InOutQuad }
- NumberAnimation { from: width * 1.1; to: width * 1; duration: 1000; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on height {
- loops: Animation.Infinite
- NumberAnimation { from: height * 1; to: height * 1.15; duration: 1200; easing.type: Easing.InOutQuad }
- NumberAnimation { from: height * 1.15; to: height * 1; duration: 1000; easing.type: Easing.InOutQuad }
- }
- }
-
- SpriteSequence {
- id: ink
- width: 64
- height: 64
- scale: bubble.scale
- goalSprite: ""
-
- Sprite {
- name: "clean"
- source: "../gfx/projectile-action.png"
- frameCount: 1
- frameX: 0
- frameWidth: 64
- frameHeight: 64
- }
- Sprite {
- name: "dirty"
- source: "../gfx/projectile-action.png"
- frameCount: 3
- frameX: 64
- frameWidth: 64
- frameHeight: 64
- frameDuration: 150
- to: {"clean":1}
- }
-
- Sprite { //WORKAROUND: This prevents the triggering of a rendering error which is currently under investigation.
- name: "dummy"
- source: "../gfx/melee-idle.png"
- frameCount: 8
- frameWidth: 64
- frameHeight: 64
- frameX: 0
- frameDuration: 200
- }
- SequentialAnimation on width {
- loops: Animation.Infinite
- NumberAnimation { from: width * 1; to: width * 1.1; duration: 800; easing.type: Easing.InOutQuad }
- NumberAnimation { from: width * 1.1; to: width * 1; duration: 1000; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on height {
- loops: Animation.Infinite
- NumberAnimation { from: height * 1; to: height * 1.15; duration: 1200; easing.type: Easing.InOutQuad }
- NumberAnimation { from: height * 1.15; to: height * 1; duration: 1000; easing.type: Easing.InOutQuad }
- }
-
- }
-
- SequentialAnimation on x {
- loops: Animation.Infinite
- NumberAnimation { from: x; to: x - 5; duration: 900; easing.type: Easing.InOutQuad }
- NumberAnimation { from: x - 5; to: x; duration: 900; easing.type: Easing.InOutQuad }
- }
-}
-
diff --git a/examples/quick/demos/maroon/content/towers/Bomb.qml b/examples/quick/demos/maroon/content/towers/Bomb.qml
deleted file mode 100644
index e33d71d2e0..0000000000
--- a/examples/quick/demos/maroon/content/towers/Bomb.qml
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "../logic.js" as Logic
-import ".."
-
-TowerBase {
- id: container
- hp: 10
- range: 0.4
- rof: 10
- property real detonationRange: 2.5
-
- function fire() {
- sound.play()
- sprite.jumpTo("shoot")
- animDelay.start()
- }
-
- function finishFire() {
- var sCol = Math.max(0, col - 1)
- var eCol = Math.min(Logic.gameState.cols - 1, col + 1)
- var killList = new Array()
- for (var i = sCol; i <= eCol; i++) {
- for (var j = 0; j < Logic.gameState.mobs[i].length; j++)
- if (Math.abs(Logic.gameState.mobs[i][j].y - container.y) < Logic.gameState.squareSize * detonationRange)
- killList.push(Logic.gameState.mobs[i][j])
- while (killList.length > 0)
- Logic.killMob(i, killList.pop())
- }
- Logic.killTower(row, col);
- }
-
- Timer {
- id: animDelay
- running: false
- interval: shootState.frameCount * shootState.frameDuration
- onTriggered: finishFire()
- }
-
- function die()
- {
- destroy() // No blink, because we usually meant to die
- }
-
- SoundEffect {
- id: sound
- source: "../audio/bomb-action.wav"
- }
-
- SpriteSequence {
- id: sprite
- width: 64
- height: 64
- interpolate: false
- goalSprite: ""
-
- Sprite {
- name: "idle"
- source: "../gfx/bomb-idle.png"
- frameCount: 4
- frameDuration: 800
- }
-
- Sprite {
- id: shootState
- name: "shoot"
- source: "../gfx/bomb-action.png"
- frameCount: 6
- frameDuration: 155
- to: { "dying" : 1 } // So that if it takes a frame to clean up, it is on the last frame of the explosion
- }
-
- Sprite {
- name: "dying"
- source: "../gfx/bomb-action.png"
- frameCount: 1
- frameX: 64 * 5
- frameWidth: 64
- frameHeight: 64
- frameDuration: 155
- }
-
- SequentialAnimation on x {
- loops: Animation.Infinite
- NumberAnimation { from: x; to: x + 4; duration: 900; easing.type: Easing.InOutQuad }
- NumberAnimation { from: x + 4; to: x; duration: 900; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on y {
- loops: Animation.Infinite
- NumberAnimation { from: y; to: y - 4; duration: 900; easing.type: Easing.InOutQuad }
- NumberAnimation { from: y - 4; to: y; duration: 900; easing.type: Easing.InOutQuad }
- }
- }
-}
diff --git a/examples/quick/demos/maroon/content/towers/Factory.qml b/examples/quick/demos/maroon/content/towers/Factory.qml
deleted file mode 100644
index 6b688e051a..0000000000
--- a/examples/quick/demos/maroon/content/towers/Factory.qml
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "../logic.js" as Logic
-import ".."
-
-TowerBase {
- id: container
- rof: 160
- income: 5
- SpriteSequence {
- id: sprite
- width: 64
- height: 64
- interpolate: false
- goalSprite: ""
-
- Sprite {
- name: "idle"
- source: "../gfx/factory-idle.png"
- frameCount: 4
- frameDuration: 200
- }
-
- Sprite {
- name: "action"
- source: "../gfx/factory-action.png"
- frameCount: 4
- frameDuration: 90
- to: { "idle" : 1 }
- }
-
- SequentialAnimation on x {
- loops: Animation.Infinite
- NumberAnimation { from: x; to: x + 4; duration: 900; easing.type: Easing.InOutQuad }
- NumberAnimation { from: x + 4; to: x; duration: 900; easing.type: Easing.InOutQuad }
- }
- SequentialAnimation on y {
- loops: Animation.Infinite
- NumberAnimation { from: y; to: y - 4; duration: 900; easing.type: Easing.InOutQuad }
- NumberAnimation { from: y - 4; to: y; duration: 900; easing.type: Easing.InOutQuad }
- }
- }
-
- SoundEffect {
- id: actionSound
- source: "../audio/factory-action.wav"
- }
-
- function fire() {
- actionSound.play()
- sprite.jumpTo("action")
- coinLaunch.start()
- }
-
- function spawn() {
- coin.target = Logic.gameState.mapToItem(container, 240, -32)
- }
-
- Image {
- id: coin
- property var target: { "x" : 0, "y" : 0 }
- source: "../gfx/currency.png"
- visible: false
- }
-
- SequentialAnimation {
- id: coinLaunch
- PropertyAction { target: coin; property: "visible"; value: true }
- ParallelAnimation {
- NumberAnimation { target: coin; property: "x"; from: 16; to: coin.target.x }
- NumberAnimation { target: coin; property: "y"; from: 16; to: coin.target.y }
- }
- PropertyAction { target: coin; property: "visible"; value: false }
- }
-}
diff --git a/examples/quick/demos/maroon/content/towers/Melee.qml b/examples/quick/demos/maroon/content/towers/Melee.qml
deleted file mode 100644
index f83bd4c525..0000000000
--- a/examples/quick/demos/maroon/content/towers/Melee.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import ".."
-
-TowerBase {
- hp: 4
- range: 0.1
- damage: 1
- rof: 40
- income: 0
-
- SpriteSequence {
- id: sprite
- width: 64
- height: 64
- interpolate: false
- goalSprite: ""
-
- Sprite {
- name: "idle"
- source: "../gfx/melee-idle.png"
- frameCount: 8
- frameDuration: 250
- }
-
- Sprite {
- name: "shoot"
- source: "../gfx/melee-action.png"
- frameCount: 2
- frameDuration: 200
- to: { "idle" : 1 }
- }
- }
-
- function fire() {
- shootSound.play()
- sprite.jumpTo("shoot")
- }
-
- SoundEffect {
- id: shootSound
- source: "../audio/melee-action.wav"
- }
-}
diff --git a/examples/quick/demos/maroon/content/towers/Ranged.qml b/examples/quick/demos/maroon/content/towers/Ranged.qml
deleted file mode 100644
index 2c1f5d1343..0000000000
--- a/examples/quick/demos/maroon/content/towers/Ranged.qml
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "../logic.js" as Logic
-import ".."
-
-TowerBase {
- id: container
- hp: 2
- range: 6
- damage: 0 // By projectile
- rof: 40
- income: 0
- property var targetMob
- property real realDamage: 1
- function fire() {
- proj.x = 32 - proj.width / 2
- proj.y = 0
- targetMob = Logic.gameState.mobs[col][0]
- projAnim.to = targetMob.y - container.y -10
- projAnim.start()
- shootSound.play()
- sprite.jumpTo("shoot")
- }
-
- Image {
- id: proj
- y: 1000
- SequentialAnimation on y {
- id: projAnim
- running: false
- property real to: 1000
- SmoothedAnimation {
- to: projAnim.to
- velocity: 400
- }
- ScriptAction {
- script: {
- if (targetMob && targetMob.hit) {
- targetMob.hit(realDamage)
- targetMob.inked()
- projSound.play()
- }
- }
- }
- PropertyAction {
- value: 1000;
- }
- }
- source: "../gfx/projectile.png"
- }
-
- SoundEffect {
- id: shootSound
- source: "../audio/shooter-action.wav"
- }
- SoundEffect {
- id: projSound
- source: "../audio/projectile-action.wav"
- }
-
- SpriteSequence {
- id: sprite
- width: 64
- height: 64
- interpolate: false
- goalSprite: ""
-
- Sprite {
- name: "idle"
- source: "../gfx/shooter-idle.png"
- frameCount: 4
- frameDuration: 250
- }
-
- Sprite {
- name: "shoot"
- source: "../gfx/shooter-action.png"
- frameCount: 5
- frameDuration: 90
- to: { "idle" : 1 }
- }
-
- SequentialAnimation on x {
- loops: Animation.Infinite
- NumberAnimation { from: x; to: x - 4; duration: 900; easing.type: Easing.InOutQuad }
- NumberAnimation { from: x - 4; to: x; duration: 900; easing.type: Easing.InOutQuad }
- }
- }
-}
diff --git a/examples/quick/demos/maroon/content/towers/TowerBase.qml b/examples/quick/demos/maroon/content/towers/TowerBase.qml
deleted file mode 100644
index be37d732e4..0000000000
--- a/examples/quick/demos/maroon/content/towers/TowerBase.qml
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- property real hp: 1
- property real range: 0
- property real damage: 0
- property int rof: 100
- property int fireCounter: 0
- property int income: 0
- property int row: 0
- property int col: 0
-
- width: parent ? parent.squareSize : 0
- height: parent ? parent.squareSize : 0
- //This is how it is placed on the gameboard, do not modify/animate the X/Y/Z of a TowerBase please
- x: col * width
- y: row * height
- z: 1000
-
- function fire() { }
- function spawn() { } //After all game properties are set
- function die() { stdDeath.start(); destroy(1000); }
- function sell() { destroy(); }
-
- SequentialAnimation on opacity {
- id: stdDeath
- running: false
- loops: 2
- NumberAnimation { from: 1; to: 0; }
- NumberAnimation { from: 0; to: 1; }
- }
-}
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-1.png b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-1.png
deleted file mode 100644
index 6d41179c23..0000000000
--- a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-1.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-2.png b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-2.png
deleted file mode 100644
index c8f37486f6..0000000000
--- a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-2.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpg
deleted file mode 100644
index a83e282d5f..0000000000
--- a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpg
deleted file mode 100644
index 8a6063b7c7..0000000000
--- a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpg
deleted file mode 100644
index e3e4a2ec89..0000000000
--- a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpg
deleted file mode 100644
index ad6b4bf156..0000000000
--- a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/src/maroon.qdoc b/examples/quick/demos/maroon/doc/src/maroon.qdoc
deleted file mode 100644
index e6f0a25238..0000000000
--- a/examples/quick/demos/maroon/doc/src/maroon.qdoc
+++ /dev/null
@@ -1,889 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Maroon in Trouble
- \ingroup qtquickdemos
- \example demos/maroon
- \brief A Qt Quick game for touch devices that uses SpriteSequence,
- ParticleSystem, Emitter, and Wander types to animate objects and the SoundEffect type to
- play sound effects.
-
- \image qtquick-demo-maroon-med-2.png
-
- \e{Maroon in Trouble} demonstrates QML features that are useful when
- developing games:
-
- \list
- \li Using custom QML types to create different screens for
- different stages of the game.
- \li Using the \l Item and \l Image types to construct a game background.
- \li Using the SequentialAnimation, NumberAnimation, ParticleSystem,
- \l Emitter, and \l Wander types to animate background objects.
- \li Using the \l Timer and \l Repeater types to display a countdown
- sequence before starting the game.
- \li Using a custom QML type with custom properties to construct a game
- board.
- \li Using the SpriteSequence and \l Sprite types to add animated objects
- to the game board.
- \li Using a custom QML type that uses the \l Image type with some custom
- properties to add a menu where the players can buy objects.
- \li Using custom properties with private functions to keep track of game
- statistics and a custom QML type to display them to the players.
- \li Using the \l State type with JavaScript functions to manage game
- states.
- \li Using the \l SoundEffect type to play individual sound effects
- depending on the object type and the action applied to the object.
- \li Using signal handlers to specify keyboard shortcuts for some game
- actions.
- \li Using resource files to package game resources for deployment and
- delivery.
- \endlist
-
- \include examples-run.qdocinc
-
- \section1 Adding Screens
-
- In the Maroon in Trouble app, we use the following custom types that
- are each defined in a separate .qml file to create the game screens:
-
- \list
- \li NewGameScreen.qml
- \li GameCanvas.qml
- \li GameOverScreen.qml
- \endlist
-
- To use the custom types, we add an import statement to the main QML file,
- maroon.qml that imports the folder called \c content where the types are
- located:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto content
- \printuntil "
-
- We use the screen types at different stages of the game. The NewGameScreen
- type is used to create the screen that appears when the players start the
- app. In NewGameScreen.qml, we use an \l{Image} type to create a New Game
- button that the players can press to start a new game.
-
- \image qtquick-demo-maroon-med-1.png
-
- Tapping the button initiates a countdown timer that triggers the creation
- of the game canvas by using the GameCanvas type. Another \l{Timer} type
- spawns mobs of fish inside bubbles that the players must free before they
- reach the surface. The players can tap on the screen to open a menu where
- they can buy different types of weapons (melee, ranged, and bombs) to burst
- the bubbles.
-
- \image qtquick-demo-maroon-med-2.png
-
- When the game finishes, a screen created by using the GameOverScreen type
- appears. On this screen, the players can see their score and start a new
- game.
-
- \image qtquick-demo-maroon-med-3.jpg
-
- The screens are all created on the same background and use some of the same
- images and animations.
-
- \section1 Constructing the Background
-
- In the maroon.qml file, we use an \l{Item} type with the id \c root and a
- fixed width and height to create a main window for the game:
-
- \skipto Item
- \printuntil passedSplash
-
- We declare two custom properties for the root item, \c gameState and
- \c passedSplash that we will use later to manage game states.
-
- We use an \l{Image} item to display the game background image:
-
- \printuntil anchors.bottom
-
- We want to be able to load the background image only once at app startup
- and still use different scenes for the game screens. Therefore,
- background.png is three times the length of the root item and displays a
- scene that stretches from the bottom of sea to the sky above the horizon.
-
- We use the \c anchors.bottom property to anchor the background image to the
- bottom of the \l{Column} layout that we use to position the screens:
-
- \skipto Column
- \printuntil GameOverScreen
-
- We set a negative value for the \c y property to set the first scene at the
- bottom of the sea. We calculate the position by subtracting the height of
- a screen from the \c height property.
-
- Within the column layout, we use an \l{Item} type to add objects to the
- background. Within the item, we use \l{Row} layout objects to position
- \l{Image} objects that display waves on the game canvas and the game over
- screen:
-
- \printuntil }
- \printuntil }
- \dots
- \skipto Row
- \printuntil }
- \printuntil }
-
- The second row of waves is positioned on the y axis with a slight offset to
- the first row. We also use the \c opacity property to make the waves appear
- lighter in color than the first two waves, which gives the background some
- depth.
-
- We use \l{Image} objects to also display sunlight on the new game screen and
- on the game canvas:
-
- \skipto Image
- \printuntil anchors
- \dots
- \skipto Image
- \printuntil anchors
-
- We set the \c opacity property of the images to \c 0.02 and \c 0.04 to give
- some depth to the rays of sunshine. We use the \c y property to position the
- images at fixed locations on the y axis and the
- \c {anchors.horizontalCenter} property to center them horizontally in
- relation to their parent.
-
- We use an \l {Image} type to display an image that adds a deepening shadow
- to the background:
-
- \skipto Image
- \printuntil }
-
- We set the \c opacity property of the image to \c 0.5 to make the background
- visible behind the shadow.
-
- To make the background more interesting, we animate some of the objects we
- added to it.
-
- \section1 Animating Background Objects
-
- We use NumberAnimation to move the waves horizontally across the screen in
- opposite directions and SequentialAnimation with NumberAnimation to move
- them up and down.
-
- We apply the number animation to the \c x property of \c wave as a property
- value source to animate the x value from its current value to the
- \c -(wave.width), over 16 seconds. We set the \c loops property to
- \c {Animation.Infinite} to repeat the animation indefinitely:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto wave.width
- \printuntil }
-
- We apply the sequential animation to the \c y property of the image as a
- property value source to animate the y value. We use one number animation
- to animate the image from the y position of two below the value of y to two
- above it, over 1600 milliseconds. We use another number animation to
- subsequently animate the image in the opposite direction, again over 1600
- milliseconds. The animation is repeated indefinitely:
-
- \skipto SequentialAnimation
- \printuntil }
- \printuntil }
- \printuntil }
-
- We use the easing curve of the type \c {Easing.InOutQuad} for a quintic
- (t^5) function to accelerate the motion until halfway and then decelerate
- it.
-
- We use sequential animation and number animation to animate \c wave2
- similarly to \c wave, but in the opposite direction:
-
- \skipto SequentialAnimation
- \printuntil }
- \printuntil }
- \printuntil }
-
- We use sequential animation to rotate the rays of sunlight in degrees
- clockwise around an origin point that we set to \c {Item.Top} in the
- \c transformOrigin property. The animation is repeated indefinitely:
-
- \skipto transformOrigin
- \printuntil to: -10
- \printuntil }
-
- We use one number animation to rotate the image from \c -10 degrees to
- \c 10 degrees over 8 seconds and another to subsequently rotate it from
- \c 10 degrees to \c -10 degrees over the same duration.
-
- We use the easing curve of the type \c {Easing.InOutSine} for a sinusoidal
- (sin(t)) function to accelerate the motion until halfway and then decelerate
- it.
-
- We use sequential animation and number animation to animate another
- sunlight.png image similarly, but in the opposite direction:
-
- \skipto transformOrigin
- \printuntil to: 10
- \printuntil }
-
- For examples of using SequentialAnimation and NumberAnimation on the \c x
- and \c y properties and the \c width and \c height properties, see
- NewGameScreen.qml.
-
- \section1 Emitting Particles
-
- In addition to animation, we use particles to generate motion on the game
- screens. We use the ParticleSystem QML type in maroon.qml to make bubbles
- appear at the bottom of the new game screen and game canvas and slowly float
- towards the top on varying trajectories.
-
- To use the ParticleSystem type, we must import \l{Qt Quick Particles QML Types}:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto Particles
- \printuntil 0
-
- To have the particles appear on the game background, we place the
- ParticleSystem type within the \l{Image} type that displays the game
- background:
-
- \skipto Image
- \printuntil anchors.fill
-
- In the ParticleSystem, we use an \l{Emitter} type to emit particles from the
- location of the emitter at the rate of two per second with the life span of
- 15 seconds:
-
- \skipto Emitter
- \printuntil sizeVariation
- \printuntil }
-
- The \c acceleration property uses the PointDirection type to
- specify random variation of the x and y coordinates, so that the bubbles
- appear inside a rectangular area around the emitter that is anchored to the
- bottom of the image.
-
- The \c size property sets the base size of the particles at the beginning of
- their life to 24 pixels and the \c sizeVariation property randomly increases
- or decreases the particle size by up to 16 pixels, so that we get bubbles in
- different sizes.
-
- As emitters have no visualization, we use the ImageParticle type to render
- the catch.png image at the particle location:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto ImageParticle
- \printuntil }
-
- A \l{Wander} type applies a random trajectory to the particles, so that the
- bubbles follow random routes from the bottom to the top.
-
- \printuntil }
-
- For another example of using the ParticleSystem type, see the
- GameOverScreen.qml file, where an ImageParticle type is used to make clouds
- move across the sky.
-
- \section1 Using Timers
-
- \image qtquick-demo-maroon-med-4.jpg
-
- In maroon.qml, we use the \l{Timer} type with a \l{Repeater} type to display
- a countdown sequence before using another timer to start a new game. Both
- timers are started simultaneously in the \c "gameOn" state, that is when the
- players tap the New Game button and \c passedSplash is \c true. This is
- explained in more detail in \l{Managing Game States}.
-
- We use the \c countdownTimer to display the countdown sequence:
-
- \skipto Timer
- \printuntil }
-
- The \c onTriggered signal handler is called when the timer is triggered to
- increment the value of the \c countdown custom property.
-
- We set the \c repeat property to \c true to specify that the timer is
- triggered at the interval of 1 second as long as the value of \c countdown
- is less than 5.
-
- The \c countdown property is defined in the root item with an initial value
- of \c 10, so that \c countdownTimer is not running by default:
-
- \skipto countdown:
- \printuntil 10
-
- Each time the timer is triggered, an image from the countdown sequence is
- displayed. We use a \l{Repeater} type to instantiate the \l{Image} delegate
- in the context of the repeater's parent, \c canvasArea item, seeded with
- data from the \c model:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto Repeater
- \printuntil scale
- \printuntil }
- \printuntil }
- \printuntil }
- \printuntil }
-
- We scale the images from \c 0.0 to \c 1.0 and use the \c visible property to
- hide the images for the previous steps as the countdown progresses. We also
- raise the opacity of the image that matches the current countdown step,
- keeping the others nearly transparent.
-
- By animating the changes in the \c opacity and \c scale properties using a
- \l Behavior type, we achieve a countdown sequence where numbers zoom in
- towards the players.
-
- \section1 Constructing the Game Board
-
- To construct the game board, we use the GameCanvas custom type that is
- defined in GameCanvas.qml.
-
- In maroon.qml, we use the GameCanvas type to display the game canvas
- at the position of 32 on the x axis and 20 pixels from the bottom of
- its parent item, \c canvasArea:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto GameCanvas
- \printuntil }
-
- We set the \c focus property to \c true to give \c canvas active focus on
- startup.
-
- In GameCanvas.qml, we use an \l Item type and define custom properties for
- it to create a grid of equally sized squares divided to 4 columns on 6 rows:
-
- \quotefromfile demos/maroon/content/GameCanvas.qml
- \skipto Item
- \printuntil canvas
-
- We use the custom properties to set the \c width and \c height of the
- \c grid item as the amount of columns and rows multiplied by square size:
-
- \skipto width
- \printuntil height
-
- We use an \l{Image} type with a MouseArea type to display a help button
- that the players can tap to view an image that contains instructions for
- playing the game:
-
- \skipuntil endGame
- \skipto Image
- \printuntil bottomMargin
- \printuntil }
-
- We declare the \c goAway() private function to disable the mouse area and
- make the image fully transparent and a \c comeBack() function to enable the
- mouse area and make the button fully opaque. We use a \l {Behavior} type on
- the \c opacity property to apply the default number animation when the value
- of \c opacity changes.
-
- When the players tap the help button, the \c onClicked signal handler is
- called to hide the help button by setting the \c {helpButton.visible}
- property to \c false and to show the help image by setting the
- \c {helpImage.visible} property to \c false.
-
- \image qtquick-demo-maroon-med-6.jpg
-
- We use anchoring to position the help button at the bottom center of the
- game canvas.
-
- We use another \l{Image} type to display the help image:
-
- \printuntil }
- \printuntil }
-
- To hide the help image when the players tap it, the \c onClicked signal
- handler within the MouseArea type is called to set the \c{helpImage.visible}
- property to \c true.
-
- To ensure that the images are placed on top when they are visible, we set
- a high value for their \c z property.
-
- The following sections describe how to use timers to add animated objects to
- the game board and how to create a menu dialog from which the players can
- add more objects to it.
-
- \section1 Animating Objects on the Game Board
-
- We use sprite animation to animate objects on the game board. The Qt Quick
- \l{Sprite Animations}{sprite engine} is a stochastic state machine combined
- with the ability to chop up images containing multiple frames of an
- animation.
-
- \section2 Spawning Fish
-
- We use a \l{Timer} element with the \c tick() function in GameCanvas.qml to
- spawn mobs of fish in waves at an increasing rate, starting at 16
- milliseconds:
-
- \quotefromfile demos/maroon/content/GameCanvas.qml
- \skipto Timer
- \printuntil }
-
- We use the MobBase custom type that is defined in MobBase.qml to
- animate mobs of fish that swim inside bubbles. We use an \l{Item} type with
- custom properties and private functions to create the fish and the bubbles
- and to define the actions that can be applied to them:
-
- \quotefromfile demos/maroon/content/mobs/MobBase.qml
- \skipto Item
- \printuntil }
- \dots
-
- We use a SpriteSequence type to animate the fish:
-
- \skipto SpriteSequence
- \printuntil goalSprite
-
- The SpriteSequence type renders and controls a list of animations
- defined by \l{Sprite} types:
-
- \skipto Sprite {
- \printuntil name: "right"
- \printuntil }
- \printuntil }
-
- In the \c fishSprite sprite sequence, each sprite defines one frame within
- the mob-idle.png file, which shows a fish facing right, front, and left:
-
- \image ../../content/gfx/mob-idle.png
-
- We use the \c frameWidth, \c frameHeight, and \c frameX properties to
- determine that the first 64x64-pixel square of the image is framed in the
- \c "left" sprite, the second in the \c "front" sprite, and the third in the
- \c "right" sprite. For each sprite, the \c frameCount property is set to
- \c 1 to specify that the sprite contains one frame.
-
- We use the \c frameDuration and \c frameDurationVariation properties to
- specify that the duration of an animation can vary from \c 400 to \c 1200
- milliseconds.
-
- The \c to property specifies that the sprites have weighted transitions to
- other sprites. The \c "left" and \c "right" sprites always transfer to the
- \c "front" sprite. When the \c "front" animation finishes, the sprite engine
- chooses \c "left" or \c "right" randomly, but at roughly equal proportions,
- because they both have the weight \c 1.
-
- When the fish are set free, we want them to swim away in the direction they
- are facing until they get off the screen. If they were facing front, we use
- the \c jumpTo method with the JavaScript \c {Math.random()} method in the
- \c die() private function to randomly jump to the \c "left" or \c "right"
- sprite:
-
- \quotefromfile demos/maroon/content/mobs/MobBase.qml
- \skipto die()
- \printuntil }
-
- We then use the \c start() function to run a NumberAnimation that applies a
- number animation to the x value from its current value to \c -360 or \c 360,
- depending on whether the \c goingLeft custom property is \c true, in 300
- milliseconds:
-
- \skipto NumberAnimation
- \printuntil }
-
- \section2 Bursting Bubbles
-
- We use another SpriteSequence to animate the bubbles so that they
- become smaller and finally burst when they are attacked by a shooter or
- a melee. For this effect, we set the value of the \c scale property to
- decrease by \c 0.2 each time the custom \c hp property changes:
-
- \skipto SpriteSequence
- \printuntil goalSprite
-
- We use a \l{Behavior} type to apply a NumberAnimation when the value of
- \c scale changes. We use the \c{Easing.OutBack} easing type for a back
- (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out curve that
- decelerates the motion to zero velocity in 150 milliseconds:
-
- \skipto Behavior
- \printuntil }
- \printuntil }
-
- The SpriteSequence consist of two sprites that display different images. The
- first sprite, \c "big", uses the catch.png image to display an empty bubble:
-
- \skipto Sprite
- \printuntil }
- \printuntil }
-
- We set the \c to property to \c "burst" with the weight \c 0 to make the
- second sprite, \c "burst", a valid goal for the \c jumpTo method that we use
- in the \c die() private function to jump directly to the \c "burst" sprite
- without playing the first sprite.
-
- In the \c "burst" sprite, we set the \c frameCount property to \c 3 and the
- \c frameX property to \c 64 to specify that the animation starts at pixel
- location 64 and loads each frame for the duration of 200 milliseconds.
-
- \skipto Sprite
- \printuntil }
-
- Within the SpriteSequence, we use SequentialAnimation with NumberAnimation
- to animate the transitions between the frames. To create a pulsating effect
- on the bubbles, we apply a sequential animation on the \c width property
- with two number animations to first increase the bubble width from
- \c{* 1} to \c{* 1.1} over 800 milliseconds and then bring it back over 1
- second:
-
- \skipto SequentialAnimation
- \printuntil }
- \printuntil }
- \printuntil }
-
- Similarly, we increase the bubble height from \c{* 1} to \c{* 1.15} over
- 1200 milliseconds and then bring it back over 1 second:
-
- \skipto SequentialAnimation
- \printuntil }
- \printuntil }
- \printuntil }
-
- We use yet another SpriteSequence to display the effect of squid ink on the
- bubbles. For more examples of using sprite sequences, see the QML files in
- the \c towers directory.
-
- \section1 Adding Dialogs
-
- \image qtquick-demo-maroon-med-5.jpg
-
- In GameCanvas.qml, we use an \l{Image} type with some custom properties to
- create a menu where the players can buy tower objects:
-
- \quotefromfile demos/maroon/content/GameCanvas.qml
- \skipto Image
- \printuntil towerExists
-
- We set the \c visible property to \c false to hide the menu by default. The
- \c z property is set to 1500 to ensure that the menu is displayed in front
- of all other items when it is visible.
-
- We use a MouseArea type to open or close the menu when players tap on the
- canvas:
-
- \quotefromfile demos/maroon/content/GameCanvas.qml
- \skipto MouseArea
- \printuntil }
- \printuntil }
-
- We set the \c anchors.fill property to \c parent to allow the players to tap
- anywhere on the game canvas. We use a condition in the \c onClicked
- signal handler to call the \c {finish()} function if the menu is visible
- and the \c {open()} function otherwise.
-
- The \c {finish()} function hides the menu by setting the \c shown custom
- property to \c false:
-
- \skipto finish
- \printuntil }
-
- The \c {open()} function displays the menu at the x and y position of the
- mouse pointer:
-
- \printuntil }
-
- If \c gameRunning is \c true, we call the JavaScript \c row() function to
- calculate the value of the \c targetRow custom property and the \c col()
- function to calculate the value of the \c targetCol custom property. If
- the value of \c targetRow equals \c 0, the y position is set to one square
- above the mouse pointer. Otherwise, it is set to one square below the mouse
- pointer.
-
- We use the \c towerIdx() function to set the value of the \c towerExists
- custom property.
-
- We set the \c shown custom property to \c true to show the menu and call the
- \c {helpButton.goAway()} function to hide the help button when the menu
- opens.
-
- We use states and transitions to display the menu when the \c shown
- property is \c true and the \c gameOver property is \c false:
-
- \printuntil OutElastic
- \printuntil }
-
- To set the visibility of the menu to \c "visible" without animating the
- property change, we use a PropertyAction type. We do want to animate the
- changes in opacity and scale, though, so we use number animation to
- animate the value of the \c scale property from \c 0.9 to \c 1 and the
- value of \c opacity property from \c 0.7 to \c 1, over 500 milliseconds.
- We use the \c {Easing.outElastic} easing type for an elastic (exponentially
- decaying sine wave) function easing curve that decelerates from zero
- velocity.
-
- To construct the menu, we use a BuildButton custom type that is defined in
- BuildButton.qml. In GameCanvas.qml, we create one build button for each
- tower object that the players can buy and position them in a \l{Row} layout
- in front of the menu background image, dialog.png:
-
- \printuntil dialog-factory.png
- \printuntil }
- \printuntil }
- \printuntil }
-
- For each build button, we set the values of \c towerType and \c index custom
- properties that we define in BuildButton.qml.
-
- We use the \c canBuild custom property to prevent players from adding tower
- objects in locations where tower objects already exist.
-
- We use the \c source property to display the image for the tower type.
-
- The \c onClicked signal handler is called to execute the \c finish()
- function that closes the menu when the players tap an enabled build button.
-
- Build buttons are enabled when the players have enough coins to buy the
- tower objects. We use an \l {Image} type in BuildButton.qml to display
- images on the buttons:
-
- \quotefromfile demos/maroon/content/BuildButton.qml
- \skipto Image
- \printuntil }
-
- We use the \c opacity property to make the buttons appear enabled. If
- \c canBuild is \c true and the value of the \c gameCanvas.coins property
- is larger than or equal to the cost of a tower object, the images are fully
- opaque, otherwise their opacity is set to \c 0.4.
-
- We use a \l{Text} type to display the cost of each tower item, as specified
- by the \c towerData variable, depending on \c towerType:
-
- \skipto Text
- \printuntil }
-
- To display a pointer on the screen at the position where the tower object
- will be added, we use the \l {Image} type. We use the \c visible property
- to determine whether the dialog-pointer.png image should be positioned below
- or above the menu. When the value of the \c col property equals the \c index
- and the value or the \c row property is not \c 0, we anchor the image to the
- bottom of its parent, BuildButton.
-
- When the value or the \c row property is \c 0, we anchor the image to the
- top of BuildButton to position the pointer above the menu and use the
- \c rotation property to rotate it by 180 degrees, so that it points upwards:
-
- \skipto Image
- \printuntil }
- \printuntil }
-
- \section1 Keeping Track of Game Statistics
-
- To keep track of the game statistics, we use the InfoBar custom type (that
- is defined in InfoBar.qml) in maroon.qml:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto InfoBar
- \printuntil }
-
- We use the \c {anchors.bottom} and \c {anchors.bottomMargin} properties to
- position the info bar at 6 points from the top of the game canvas. We bind
- the \c width property of the info bar to that of its parent.
-
- In InfoBar.qml, we use an \l{Item} type to create the info bar. Within it,
- we use a \l{Row} layout type to display the number of lives the players have
- left, the number of fish that have been saved, and the amount of coins that
- are available for use.
-
- We use the \c anchors property to position the rows in relationship to their
- parent and to each other. In the first \l{Row} object, we use the
- \c {anchors.left} and \c {anchors.leftMargin} properties to position the
- heart icons at 10 points from the left border of the parent item:
-
- \quotefromfile demos/maroon/content/InfoBar.qml
- \skipto Item
- \printuntil }
- \printuntil }
- \printuntil }
-
- We use a \l{Repeater} type with a \c model and a \c delegate to display as
- many hearts as the players have lives left. We use the \c spacing property
- to leave 5 pixels between the displayed icons.
-
- In the second \l{Row} object, we use the \c {anchors.right} and
- \c {anchors.rightMargin} properties to position the number of fish saved at
- 20 points left of the third \l{Row} object that displays the number of coins
- available (and has the id \c points):
-
- \skipto Row
- \printuntil /^\}/
-
- In these objects, we set spacing to 5 pixels to separate the icons from the
- numbers that we display by using a \l{Text} type.
-
- In GameCanvas.qml, we define custom properties to hold the game statistics:
-
- \quotefromfile demos/maroon/content/GameCanvas.qml
- \skipto score
- \printuntil lives
-
- We declare the \c freshState() function to set the initial game statistics
- when a new game starts:
-
- \skipto freshState()
- \printuntil }
-
- We use the \c {Logic.gameState.score} variable in the \c die() function
- that we declare in MobBase.qml to increase the score by one when the players
- set a fish free:
-
- \quotefromfile demos/maroon/content/mobs/MobBase.qml
- \skipto score
- \printuntil ;
-
- \section1 Managing Game States
-
- In maroon.qml, we use a \l{State} type and JavaScript to switch between
- screens according to the game state. The logic.js file contains definitions
- for the functions. To use the functions in a QML file, we import logic.js as
- the \c Logic namespace in that file:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto logic.js
- \printuntil Logic
-
- The base state displays the new game screen when the application starts.
- In addition, we call the Component.onCompleted signal handler to initialize
- a new game:
-
- \skipto newGameState
- \printuntil ;
-
- In NewGameScreen.qml we use the \c onClicked signal handler to emit the
- \c startButtonClicked() signal when the players tap the New Game button:
-
- \quotefromfile demos/maroon/content/NewGameScreen.qml
- \skipto to: 150
- \skipto Image
- \printuntil }
-
- In maroon.qml, we use the \c onStartButtonClicked signal handler to set the
- \c passedSplash property of the \c root item to \c true:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto NewGameScreen
- \printuntil }
-
- We then use the \c passedSplash property in the \c when property of the
- \c gameOn state to trigger the \c gameStarter timer:
-
- \skipto State {
- \printuntil gameStarter
- \printuntil }
-
- We also switch to the \c "gameOn" state and move to the y position
- \c {-(height - 960)} to display the game canvas.
-
- In the \c gameStarter \l{Timer} object we use the \c onTriggered signal
- handler to call the \c startGame() function that starts a new game:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto property int
- \skipto Timer
- \printuntil }
-
- The game continues until \c gameState.gameOver is set to \c true and
- \c gameState.gameRunning is set to \c false by calling the \c endGame()
- function when the value of the \c gameState.lives property becomes less
- than or equal to \c 0.
-
- In GameOverScreen.qml, we use a MouseArea type and an \c onClicked signal
- handler within an \l{Image} type to return to the game canvas when the
- players tap the New Game button:
-
- \quotefromfile demos/maroon/content/GameOverScreen.qml
- \skipto opacity: 0.5
- \skipto Image
- \printuntil }
- \printuntil }
-
- The \c onClicked signal handler triggers a state change in maroon.qml to
- display the game canvas:
-
- \quotefromfile demos/maroon/maroon.qml
- \skipto target: gameStarter
- \skipto State
- \printuntil }
- \printuntil }
-
- \section1 Playing Sound Effects
-
- The app can play sound effects if the \l{Qt Multimedia} module is installed.
- In the SoundEffect.qml file, we proxy a SoundEffect type:
-
- \quotefromfile demos/maroon/content/SoundEffect.qml
- \skipto Item
- \printuntil }
- \printuntil }
-
- We add the \c qtHaveModule() qmake command to the app .pro file, maroon.pro,
- to check whether the \l{Qt Multimedia} module is present:
-
- \quotefromfile demos/maroon/maroon.pro
- \skipto QT
- \printuntil multimedia
-
- In each QML file that defines a custom type used on the game canvas, we
- use a SoundEffect type to specify the audio file to play for that type
- of objects. For example, in Bomb.qml, we specify the sound that a bomb
- makes when it explodes:
-
- \quotefromfile demos/maroon/content/towers/Bomb.qml
- \skipto SoundEffect
- \printuntil }
-
- To play the sound effect when a bomb explodes, we call the \c sound.play()
- function that we declare as a member of the private \c fire() function
- within the TowerBase custom type:
-
- \quotefromfile demos/maroon/content/towers/Bomb.qml
- \skipto fire()
- \printuntil }
-
- For more examples of playing sound effects, see the QML files in the
- \c towers directory and MobBase.qml.
-
- \section1 Adding Keyboard Shortcuts
-
- This is a touch example, so you should not really need to handle key
- presses. However, we do not want you to have to spend more time playing the
- game than you want to while testing it, so we use the \c {Keys.onPressed}
- signal handler to specify keyboard shortcuts. You can press Shift+Up to
- increment the values of the \c coins property to add coins, Shift+Left to
- increment the value of \c lives, Shift+Down to increment the value of the
- \c waveProgress property to spawn mobs of fish faster, and Shift+Right to
- call the \c endGame() function to quit the game:
-
- \quotefromfile demos/maroon/content/GameCanvas.qml
- \skipto Keys
- \printuntil }
-
- \section1 Packaging Resources for Deployment
-
- To be able to run the app on mobile devices, we package all QML, JavaScript,
- image, and sound files into a Qt resource file (.qrc). For more information,
- see \l{The Qt Resource System}.
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/maroon/main.cpp b/examples/quick/demos/maroon/main.cpp
deleted file mode 100644
index f6590fc32e..0000000000
--- a/examples/quick/demos/maroon/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/maroon/maroon)
diff --git a/examples/quick/demos/maroon/maroon.pro b/examples/quick/demos/maroon/maroon.pro
deleted file mode 100644
index ada16d047a..0000000000
--- a/examples/quick/demos/maroon/maroon.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick
-qtHaveModule(multimedia): QT += multimedia
-SOURCES += main.cpp
-RESOURCES += maroon.qrc
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/maroon
-INSTALLS += target
diff --git a/examples/quick/demos/maroon/maroon.qml b/examples/quick/demos/maroon/maroon.qml
deleted file mode 100644
index d05ef57b64..0000000000
--- a/examples/quick/demos/maroon/maroon.qml
+++ /dev/null
@@ -1,245 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-import "content"
-import "content/logic.js" as Logic
-
-Item {
- id: root
- width: 320
- height: 480
- property var gameState
- property bool passedSplash: false
-
- Image {
- source:"content/gfx/background.png"
- anchors.bottom: view.bottom
-
- ParticleSystem {
- id: particles
- anchors.fill: parent
-
- ImageParticle {
- id: bubble
- anchors.fill: parent
- source: "content/gfx/catch.png"
- opacity: 0.25
- }
-
- Wander {
- xVariance: 25;
- pace: 25;
- }
-
- Emitter {
- width: parent.width
- height: 150
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 3
- startTime: 15000
-
- emitRate: 2
- lifeSpan: 15000
-
- acceleration: PointDirection{ y: -6; xVariation: 2; yVariation: 2 }
-
- size: 24
- sizeVariation: 16
- }
- }
- }
-
- Column {
- id: view
- y: -(height - 480)
- width: 320
-
- GameOverScreen { gameCanvas: canvas }
-
- Item {
- id: canvasArea
- width: 320
- height: 480
-
- Row {
- height: childrenRect.height
- Image {
- id: wave
- y: 30
- source:"content/gfx/wave.png"
- }
- Image {
- y: 30
- source:"content/gfx/wave.png"
- }
- NumberAnimation on x { from: 0; to: -(wave.width); duration: 16000; loops: Animation.Infinite }
- SequentialAnimation on y {
- loops: Animation.Infinite
- NumberAnimation { from: y - 2; to: y + 2; duration: 1600; easing.type: Easing.InOutQuad }
- NumberAnimation { from: y + 2; to: y - 2; duration: 1600; easing.type: Easing.InOutQuad }
- }
- }
-
- Row {
- opacity: 0.5
- Image {
- id: wave2
- y: 25
- source: "content/gfx/wave.png"
- }
- Image {
- y: 25
- source: "content/gfx/wave.png"
- }
- NumberAnimation on x { from: -(wave2.width); to: 0; duration: 32000; loops: Animation.Infinite }
- SequentialAnimation on y {
- loops: Animation.Infinite
- NumberAnimation { from: y + 2; to: y - 2; duration: 1600; easing.type: Easing.InOutQuad }
- NumberAnimation { from: y - 2; to: y + 2; duration: 1600; easing.type: Easing.InOutQuad }
- }
- }
-
- Image {
- source: "content/gfx/sunlight.png"
- opacity: 0.02
- y: 0
- anchors.horizontalCenter: parent.horizontalCenter
- transformOrigin: Item.Top
- SequentialAnimation on rotation {
- loops: Animation.Infinite
- NumberAnimation { from: -10; to: 10; duration: 8000; easing.type: Easing.InOutSine }
- NumberAnimation { from: 10; to: -10; duration: 8000; easing.type: Easing.InOutSine }
- }
- }
-
- Image {
- source: "content/gfx/sunlight.png"
- opacity: 0.04
- y: 20
- anchors.horizontalCenter: parent.horizontalCenter
- transformOrigin: Item.Top
- SequentialAnimation on rotation {
- loops: Animation.Infinite
- NumberAnimation { from: 10; to: -10; duration: 8000; easing.type: Easing.InOutSine }
- NumberAnimation { from: -10; to: 10; duration: 8000; easing.type: Easing.InOutSine }
- }
- }
-
- Image {
- source: "content/gfx/grid.png"
- opacity: 0.5
- }
-
- GameCanvas {
- id: canvas
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 20
- x: 32
- focus: true
- }
-
- InfoBar { anchors.bottom: canvas.top; anchors.bottomMargin: 6; width: parent.width }
-
- //3..2..1..go
- Timer {
- id: countdownTimer
- interval: 1000
- running: root.countdown < 5
- repeat: true
- onTriggered: root.countdown++
- }
- Repeater {
- model: ["content/gfx/text-blank.png", "content/gfx/text-3.png", "content/gfx/text-2.png", "content/gfx/text-1.png", "content/gfx/text-go.png"]
- delegate: Image {
- visible: root.countdown <= index
- opacity: root.countdown == index ? 0.5 : 0.1
- scale: root.countdown >= index ? 1.0 : 0.0
- source: modelData
- Behavior on opacity { NumberAnimation {} }
- Behavior on scale { NumberAnimation {} }
- }
- }
- }
-
- NewGameScreen {
- onStartButtonClicked: root.passedSplash = true
- }
- }
-
- property int countdown: 10
- Timer {
- id: gameStarter
- interval: 4000
- running: false
- repeat: false
- onTriggered: Logic.startGame(canvas);
- }
-
- states: [
- State {
- name: "gameOn"; when: gameState.gameOver == false && passedSplash
- PropertyChanges { target: view; y: -(height - 960) }
- StateChangeScript { script: root.countdown = 0; }
- PropertyChanges { target: gameStarter; running: true }
- },
- State {
- name: "gameOver"; when: gameState.gameOver == true
- PropertyChanges { target: view; y: 0 }
- }
- ]
-
- transitions: Transition {
- NumberAnimation { properties: "x,y"; duration: 1200; easing.type: Easing.OutQuad }
- }
-
- Component.onCompleted: gameState = Logic.newGameState(canvas);
-}
diff --git a/examples/quick/demos/maroon/maroon.qmlproject b/examples/quick/demos/maroon/maroon.qmlproject
deleted file mode 100644
index 752666114f..0000000000
--- a/examples/quick/demos/maroon/maroon.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "maroon.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
-}
diff --git a/examples/quick/demos/maroon/maroon.qrc b/examples/quick/demos/maroon/maroon.qrc
deleted file mode 100644
index 52c2a4e513..0000000000
--- a/examples/quick/demos/maroon/maroon.qrc
+++ /dev/null
@@ -1,71 +0,0 @@
-<RCC>
- <qresource prefix="/demos/maroon">
- <file>maroon.qml</file>
- <file>content/BuildButton.qml</file>
- <file>content/GameCanvas.qml</file>
- <file>content/GameOverScreen.qml</file>
- <file>content/InfoBar.qml</file>
- <file>content/logic.js</file>
- <file>content/NewGameScreen.qml</file>
- <file>content/SoundEffect.qml</file>
- <file>content/audio/bomb-action.wav</file>
- <file>content/audio/catch-action.wav</file>
- <file>content/audio/catch.wav</file>
- <file>content/audio/currency.wav</file>
- <file>content/audio/factory-action.wav</file>
- <file>content/audio/melee-action.wav</file>
- <file>content/audio/projectile-action.wav</file>
- <file>content/audio/shooter-action.wav</file>
- <file>content/gfx/background.png</file>
- <file>content/gfx/bomb-action.png</file>
- <file>content/gfx/bomb-idle.png</file>
- <file>content/gfx/bomb.png</file>
- <file>content/gfx/button-help.png</file>
- <file>content/gfx/button-play.png</file>
- <file>content/gfx/catch-action.png</file>
- <file>content/gfx/catch.png</file>
- <file>content/gfx/cloud.png</file>
- <file>content/gfx/currency.png</file>
- <file>content/gfx/dialog-bomb.png</file>
- <file>content/gfx/dialog-factory.png</file>
- <file>content/gfx/dialog-melee.png</file>
- <file>content/gfx/dialog-pointer.png</file>
- <file>content/gfx/dialog-shooter.png</file>
- <file>content/gfx/dialog.png</file>
- <file>content/gfx/factory-action.png</file>
- <file>content/gfx/factory-idle.png</file>
- <file>content/gfx/factory.png</file>
- <file>content/gfx/grid.png</file>
- <file>content/gfx/help.png</file>
- <file>content/gfx/lifes.png</file>
- <file>content/gfx/logo-bubble.png</file>
- <file>content/gfx/logo-fish.png</file>
- <file>content/gfx/logo.png</file>
- <file>content/gfx/melee-action.png</file>
- <file>content/gfx/melee-idle.png</file>
- <file>content/gfx/melee.png</file>
- <file>content/gfx/mob-idle.png</file>
- <file>content/gfx/mob.png</file>
- <file>content/gfx/points.png</file>
- <file>content/gfx/projectile-action.png</file>
- <file>content/gfx/projectile.png</file>
- <file>content/gfx/scores.png</file>
- <file>content/gfx/shooter-action.png</file>
- <file>content/gfx/shooter-idle.png</file>
- <file>content/gfx/shooter.png</file>
- <file>content/gfx/sunlight.png</file>
- <file>content/gfx/text-1.png</file>
- <file>content/gfx/text-2.png</file>
- <file>content/gfx/text-3.png</file>
- <file>content/gfx/text-blank.png</file>
- <file>content/gfx/text-gameover.png</file>
- <file>content/gfx/text-go.png</file>
- <file>content/gfx/wave.png</file>
- <file>content/mobs/MobBase.qml</file>
- <file>content/towers/Bomb.qml</file>
- <file>content/towers/Factory.qml</file>
- <file>content/towers/Melee.qml</file>
- <file>content/towers/Ranged.qml</file>
- <file>content/towers/TowerBase.qml</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/photosurface/doc/images/qtquick-demo-photosurface-small.png b/examples/quick/demos/photosurface/doc/images/qtquick-demo-photosurface-small.png
deleted file mode 100644
index a0cd823999..0000000000
--- a/examples/quick/demos/photosurface/doc/images/qtquick-demo-photosurface-small.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photosurface/doc/src/photosurface.qdoc b/examples/quick/demos/photosurface/doc/src/photosurface.qdoc
deleted file mode 100644
index dd1b2fe79f..0000000000
--- a/examples/quick/demos/photosurface/doc/src/photosurface.qdoc
+++ /dev/null
@@ -1,157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Photo Surface
- \ingroup qtquickdemos
- \example demos/photosurface
- \brief A QML app for touch devices that uses a Repeater with a
- FolderListModel to access content in a folder, and a PinchArea that contains
- a MouseArea to handle pinch gestures on the fetched content.
- \image qtquick-demo-photosurface-small.png
-
- \e{Photo Surface} demonstrates how to use a \l{Repeater} with a
- FolderListModel and a FileDialog to access images from a folder selected
- by a user and how to handle dragging, rotation and pinch zooming within the
- same item using a \l PinchArea that contains a \l MouseArea.
-
- All the app code is contained in one QML file, photosurface.qml. Inline
- JavaScript code is used to place, rotate, and scale images on the photo
- surface.
-
- \include examples-run.qdocinc
-
- \section1 Creating the Main Window
-
- To create the main window for the Photo Surface app, we use the \l{Window}
- QML type as the root item. It automatically sets up the window for use with
- \l{Qt Quick} graphical types:
-
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto Window {
- \printuntil currentFrame
-
- To use the \l{Window} type, we must import it:
-
- \code
- import QtQuick.Window 2.1
- \endcode
-
- \section1 Accessing Folder Contents
-
- We use a \l{Repeater} QML type together with the FolderListModel to display
- GIF, JPG, and PNG images located in a folder:
-
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto Repeater
- \printuntil }
-
- To use the FolderListModel type, we must import it:
-
- \code
- import Qt.labs.folderlistmodel 1.0
- \endcode
-
- We use a FileDialog to enable users to select the folder that contains
- the images:
-
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto FileDialog
- \printuntil }
-
- To use the FileDialog type, we must import \l{Qt Quick Dialogs}:
-
- \code
- import QtQuick.Dialogs 1.0
- \endcode
-
- We use the \c {fileDialog.open()} function to open the file dialog when the
- app starts:
-
- \code
- Component.onCompleted: fileDialog.open()
- \endcode
-
- Users can also click the file dialog icon to open the file dialog. We use
- an \l{Image} QML type to display the icon. Inside the \l{Image} type, we
- use a MouseArea with the \c onClicked signal handler to call the
- \c {fileDialog.open()} function:
-
- \quotefromfile demos/photosurface/photosurface.qml
- \skipuntil Image {
- \skipto Image {
- \printuntil }
- \printuntil }
-
- \section1 Displaying Images on the Photo Surface
-
- We use a \l{Rectangle} as a delegate for a \l{Repeater} to provide a frame
- for each image that the FolderListModel finds in the selected folder. We use
- JavaScript \c Math() methods to place the frames randomly on the photo
- surface and to rotate them at random angles, as well as to scale the images:
-
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto Rectangle
- \printuntil Component.onCompleted
- \printuntil }
-
- \section1 Handling Pinch Gestures
-
- We use a PinchArea that contains a MouseArea in the photo frames to handle
- dragging, rotation and pinch zooming of the frame:
-
- \skipto PinchArea
- \printuntil onPinchStarted
-
- We use the \c pinch group property to control how the photo frames react to
- pinch gestures. The \c pinch.target sets \c photoFrame as the item to
- manipulate. The rotation properties specify that the frames can be rotated
- at all angles and the scale properties specify that they can be scaled
- between \c 0.1 and \c 10.
-
- In the MouseArea's \c onPressed signal handler, we raise the selected photo
- frame to the top by increasing the value of its \c z property. The root item
- stores the z value of the top-most frame. The border color of the photo
- frame is controlled in the \c onEntered signal handler to highlight the
- selected image:
-
- \skipto MouseArea
- \printuntil onEntered
-
- To enable you to test the example on the desktop, we use the MouseArea's
- \c onWheel signal handler to simulate pinch gestures by using a mouse:
-
- \printuntil photoFrame.scale
- \printuntil }
- \printuntil }
-
- The \c onWheel signal handler is called in response to mouse wheel gestures.
- Use the vertical wheel to zoom and Ctrl and the vertical wheel to rotate
- frames. If the mouse has a horizontal wheel, use it to rotate frames.
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/photosurface/main.cpp b/examples/quick/demos/photosurface/main.cpp
deleted file mode 100644
index d1522bd09c..0000000000
--- a/examples/quick/demos/photosurface/main.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifdef QT_WIDGETS_LIB
-#include <QtWidgets/QApplication>
-#else
-#include <QtGui/QGuiApplication>
-#endif
-#include <QtQml/QQmlApplicationEngine>
-#include <QtQml/QQmlContext>
-#include <QtQuick/QQuickWindow>
-#include <QtGui/QImageReader>
-#include <QtCore/QCommandLineParser>
-#include <QtCore/QCommandLineOption>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QMimeDatabase>
-#include <QtCore/QStandardPaths>
-#include <QtCore/QUrl>
-
-static QStringList imageNameFilters()
-{
- QStringList result;
- QMimeDatabase mimeDatabase;
- const auto supportedMimeTypes = QImageReader::supportedMimeTypes();
- for (const QByteArray &m : supportedMimeTypes) {
- const auto suffixes = mimeDatabase.mimeTypeForName(m).suffixes();
- for (const QString &suffix : suffixes)
- result.append(QLatin1String("*.") + suffix);
- }
- return result;
-}
-
-int main(int argc, char* argv[])
-{
- // The reason to use QApplication is that QWidget-based dialogs
- // are the native dialogs on Qt-based platforms like KDE,
- // but they cannot be instantiated if this is a QGuiApplication.
-#ifdef QT_WIDGETS_LIB
- QApplication app(argc, argv);
-#else
- QGuiApplication app(argc, argv);
-#endif
- QQuickWindow::setDefaultAlphaBuffer(true);
-
- QCoreApplication::setApplicationName(QStringLiteral("Photosurface"));
- QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
- QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
- QCommandLineParser parser;
- parser.setApplicationDescription(QStringLiteral("Qt Quick Demo - Photo Surface"));
- parser.addHelpOption();
- parser.addVersionOption();
- parser.addPositionalArgument(QStringLiteral("directory"),
- QStringLiteral("The image directory or URL to show."));
- parser.process(app);
-
- QUrl initialUrl;
- if (!parser.positionalArguments().isEmpty()) {
- initialUrl = QUrl::fromUserInput(parser.positionalArguments().first(),
- QDir::currentPath(), QUrl::AssumeLocalFile);
- if (!initialUrl.isValid()) {
- qWarning().nospace() << "Invalid argument: \""
- << parser.positionalArguments().first() << "\": " << initialUrl.errorString();
- return 1;
- }
- }
-
- const QStringList nameFilters = imageNameFilters();
-
- QQmlApplicationEngine engine;
- QQmlContext *context = engine.rootContext();
-
- QUrl picturesLocationUrl = QUrl::fromLocalFile(QDir::homePath());
- const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
- if (!picturesLocations.isEmpty()) {
- picturesLocationUrl = QUrl::fromLocalFile(picturesLocations.first());
- if (initialUrl.isEmpty()
- && !QDir(picturesLocations.first()).entryInfoList(nameFilters, QDir::Files).isEmpty()) {
- initialUrl = picturesLocationUrl;
- }
- }
-
- context->setContextProperty(QStringLiteral("contextPicturesLocation"), picturesLocationUrl);
- context->setContextProperty(QStringLiteral("contextInitialUrl"), initialUrl);
- context->setContextProperty(QStringLiteral("contextImageNameFilters"), nameFilters);
-
- engine.load(QUrl("qrc:///photosurface.qml"));
- if (engine.rootObjects().isEmpty())
- return -1;
-
- return app.exec();
-}
diff --git a/examples/quick/demos/photosurface/photosurface.pro b/examples/quick/demos/photosurface/photosurface.pro
deleted file mode 100644
index 5e5b0f0815..0000000000
--- a/examples/quick/demos/photosurface/photosurface.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick
-qtHaveModule(widgets): QT += widgets
-SOURCES += main.cpp
-RESOURCES += photosurface.qrc
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/photosurface
-INSTALLS += target
-ICON = resources/icon.png
-macx: ICON = resources/photosurface.icns
-win32: RC_FILE = resources/photosurface.rc
-
diff --git a/examples/quick/demos/photosurface/photosurface.qml b/examples/quick/demos/photosurface/photosurface.qml
deleted file mode 100644
index 5d1445d776..0000000000
--- a/examples/quick/demos/photosurface/photosurface.qml
+++ /dev/null
@@ -1,286 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-import QtQuick 2.6
-import QtQuick.Dialogs 1.0
-import QtQuick.Window 2.1
-import Qt.labs.folderlistmodel 1.0
-
-Window {
- id: root
- visible: true
- width: 1024; height: 600
- color: "black"
- property int highestZ: 0
- property real defaultSize: 200
- property var currentFrame: undefined
- property real surfaceViewportRatio: 1.5
-
- FileDialog {
- id: fileDialog
- title: "Choose a folder with some images"
- selectFolder: true
- folder: picturesLocation
- onAccepted: folderModel.folder = fileUrl + "/"
- }
-
- Flickable {
- id: flick
- anchors.fill: parent
- contentWidth: width * surfaceViewportRatio
- contentHeight: height * surfaceViewportRatio
- Repeater {
- model: FolderListModel {
- id: folderModel
- objectName: "folderModel"
- showDirs: false
- nameFilters: imageNameFilters
- }
- Rectangle {
- id: photoFrame
- width: image.width * (1 + 0.10 * image.height / image.width)
- height: image.height * 1.10
- scale: defaultSize / Math.max(image.sourceSize.width, image.sourceSize.height)
- Behavior on scale { NumberAnimation { duration: 200 } }
- Behavior on x { NumberAnimation { duration: 200 } }
- Behavior on y { NumberAnimation { duration: 200 } }
- border.color: "black"
- border.width: 2
- smooth: true
- antialiasing: true
- Component.onCompleted: {
- x = Math.random() * root.width - width / 2
- y = Math.random() * root.height - height / 2
- rotation = Math.random() * 13 - 6
- }
- Image {
- id: image
- anchors.centerIn: parent
- fillMode: Image.PreserveAspectFit
- source: folderModel.folder + fileName
- antialiasing: true
- }
- PinchArea {
- anchors.fill: parent
- pinch.target: photoFrame
- pinch.minimumRotation: -360
- pinch.maximumRotation: 360
- pinch.minimumScale: 0.1
- pinch.maximumScale: 10
- pinch.dragAxis: Pinch.XAndYAxis
- onPinchStarted: setFrameColor();
- property real zRestore: 0
- onSmartZoom: {
- if (pinch.scale > 0) {
- photoFrame.rotation = 0;
- photoFrame.scale = Math.min(root.width, root.height) / Math.max(image.sourceSize.width, image.sourceSize.height) * 0.85
- photoFrame.x = flick.contentX + (flick.width - photoFrame.width) / 2
- photoFrame.y = flick.contentY + (flick.height - photoFrame.height) / 2
- zRestore = photoFrame.z
- photoFrame.z = ++root.highestZ;
- } else {
- photoFrame.rotation = pinch.previousAngle
- photoFrame.scale = pinch.previousScale
- photoFrame.x = pinch.previousCenter.x - photoFrame.width / 2
- photoFrame.y = pinch.previousCenter.y - photoFrame.height / 2
- photoFrame.z = zRestore
- --root.highestZ
- }
- }
-
- MouseArea {
- id: dragArea
- hoverEnabled: true
- anchors.fill: parent
- drag.target: photoFrame
- scrollGestureEnabled: false // 2-finger-flick gesture should pass through to the Flickable
- onPressed: {
- photoFrame.z = ++root.highestZ;
- parent.setFrameColor();
- }
- onEntered: parent.setFrameColor();
- onWheel: {
- if (wheel.modifiers & Qt.ControlModifier) {
- photoFrame.rotation += wheel.angleDelta.y / 120 * 5;
- if (Math.abs(photoFrame.rotation) < 4)
- photoFrame.rotation = 0;
- } else {
- photoFrame.rotation += wheel.angleDelta.x / 120;
- if (Math.abs(photoFrame.rotation) < 0.6)
- photoFrame.rotation = 0;
- var scaleBefore = photoFrame.scale;
- photoFrame.scale += photoFrame.scale * wheel.angleDelta.y / 120 / 10;
- }
- }
- }
- function setFrameColor() {
- if (currentFrame)
- currentFrame.border.color = "black";
- currentFrame = photoFrame;
- currentFrame.border.color = "red";
- }
- }
- }
- }
- }
-
- Rectangle {
- id: verticalScrollDecorator
- anchors.right: parent.right
- anchors.margins: 2
- color: "cyan"
- border.color: "black"
- border.width: 1
- width: 5
- radius: 2
- antialiasing: true
- height: flick.height * (flick.height / flick.contentHeight) - (width - anchors.margins) * 2
- y: (flick.contentY - flick.originY) * (flick.height / flick.contentHeight)
- NumberAnimation on opacity { id: vfade; to: 0; duration: 500 }
- onYChanged: { opacity = 1.0; scrollFadeTimer.restart() }
- }
-
- Rectangle {
- id: horizontalScrollDecorator
- anchors.bottom: parent.bottom
- anchors.margins: 2
- color: "cyan"
- border.color: "black"
- border.width: 1
- height: 5
- radius: 2
- antialiasing: true
- width: flick.width * (flick.width / flick.contentWidth) - (height - anchors.margins) * 2
- x: (flick.contentX - flick.originY) * (flick.width / flick.contentWidth)
- NumberAnimation on opacity { id: hfade; to: 0; duration: 500 }
- onXChanged: { opacity = 1.0; scrollFadeTimer.restart() }
- }
-
- Timer { id: scrollFadeTimer; interval: 1000; onTriggered: { hfade.start(); vfade.start() } }
-
- Image {
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.margins: 10
- source: "resources/folder.png"
- MouseArea {
- anchors.fill: parent
- anchors.margins: -10
- onClicked: fileDialog.open()
- hoverEnabled: true
- onPositionChanged: {
- tooltip.visible = false
- hoverTimer.start()
- }
- onExited: {
- tooltip.visible = false
- hoverTimer.stop()
- }
- Timer {
- id: hoverTimer
- interval: 1000
- onTriggered: {
- tooltip.x = parent.mouseX
- tooltip.y = parent.mouseY
- tooltip.visible = true
- }
- }
- Rectangle {
- id: tooltip
- border.color: "black"
- color: "beige"
- width: tooltipText.implicitWidth + 8
- height: tooltipText.implicitHeight + 8
- visible: false
- Text {
- id: tooltipText
- anchors.centerIn: parent
- text: "Open an image directory (" + openShortcut.sequenceString + ")"
- }
- }
- }
- Shortcut {
- id: openShortcut
- sequence: StandardKey.Open
- onActivated: fileDialog.open()
- }
- }
-
- Text {
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: 10
- color: "darkgrey"
- wrapMode: Text.WordWrap
- font.pointSize: 8
- text: "On a touchscreen: use two fingers to zoom and rotate, one finger to drag\n" +
- "With a mouse: drag normally, use the vertical wheel to zoom, horizontal wheel to rotate, or hold Ctrl while using the vertical wheel to rotate"
- }
-
- Shortcut { sequence: StandardKey.Quit; onActivated: Qt.quit() }
-
- Component.onCompleted: {
- if (typeof contextInitialUrl !== 'undefined') {
- // Launched from C++ with context properties set.
- imageNameFilters = contextImageNameFilters;
- picturesLocation = contextPicturesLocation;
- if (contextInitialUrl == "")
- fileDialog.open();
- else
- folderModel.folder = contextInitialUrl + "/";
- } else {
- // Launched via QML viewer without context properties set.
- fileDialog.open();
- }
- }
-
- property var imageNameFilters : ["*.png", "*.jpg", "*.gif"];
- property string picturesLocation : "";
-}
diff --git a/examples/quick/demos/photosurface/photosurface.qmlproject b/examples/quick/demos/photosurface/photosurface.qmlproject
deleted file mode 100644
index ae2065f59c..0000000000
--- a/examples/quick/demos/photosurface/photosurface.qmlproject
+++ /dev/null
@@ -1,20 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "photosurface.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
- Files {
- filter: "*.ts"
- directory: "i18n"
- }
-}
diff --git a/examples/quick/demos/photosurface/photosurface.qrc b/examples/quick/demos/photosurface/photosurface.qrc
deleted file mode 100644
index f8fafbb1ff..0000000000
--- a/examples/quick/demos/photosurface/photosurface.qrc
+++ /dev/null
@@ -1,6 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>photosurface.qml</file>
- <file>resources/folder.png</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/photosurface/resources/folder.png b/examples/quick/demos/photosurface/resources/folder.png
deleted file mode 100644
index 2aec3b6ebf..0000000000
--- a/examples/quick/demos/photosurface/resources/folder.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photosurface/resources/icon.png b/examples/quick/demos/photosurface/resources/icon.png
deleted file mode 100644
index f8ff553fcb..0000000000
--- a/examples/quick/demos/photosurface/resources/icon.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photosurface/resources/photosurface.icns b/examples/quick/demos/photosurface/resources/photosurface.icns
deleted file mode 100644
index c69ec41c4e..0000000000
--- a/examples/quick/demos/photosurface/resources/photosurface.icns
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photosurface/resources/photosurface.ico b/examples/quick/demos/photosurface/resources/photosurface.ico
deleted file mode 100644
index 03bb7ee367..0000000000
--- a/examples/quick/demos/photosurface/resources/photosurface.ico
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photosurface/resources/photosurface.rc b/examples/quick/demos/photosurface/resources/photosurface.rc
deleted file mode 100644
index 3267bd033f..0000000000
--- a/examples/quick/demos/photosurface/resources/photosurface.rc
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "winver.h"
-
-IDI_ICON1 ICON DISCARDABLE "photosurface.ico"
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,0
- PRODUCTVERSION 1,0,0,0
- FILEFLAGS 0x0L
- FILEFLAGSMASK 0x3fL
- FILEOS 0x00040004L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "000004b0"
- BEGIN
- VALUE "CompanyName", "The Qt Company Ltd"
- VALUE "FileDescription", "Photo Surface Demo"
- VALUE "FileVersion", "1.0.0.0"
- VALUE "LegalCopyright", "Copyright (C) 2015 The Qt Company Ltd."
- VALUE "InternalName", "photosurface"
- VALUE "OriginalFilename", "photosurface.exe"
- VALUE "ProductName", "Photo Surface Demo"
- VALUE "ProductVersion", "1.0.0.0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0, 1200
- END
-END
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
deleted file mode 100644
index ea72302d74..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
+++ /dev/null
@@ -1,157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-import QtQml.Models 2.1
-
-Component {
- id: albumDelegate
- Package {
-
- Item {
- Package.name: 'browser'
- GridView {
- id: photosGridView; model: visualModel.parts.grid; width: mainWindow.width; height: mainWindow.height - 21
- x: 0; y: 21; cellWidth: 160; cellHeight: 153; interactive: false
- onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
- }
- }
-
- Item {
- Package.name: 'fullscreen'
- ListView {
- id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
- width: mainWindow.width; height: mainWindow.height; interactive: false
- onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
- highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
- }
- }
-
- Item {
- Package.name: 'album'
- id: albumWrapper; width: 210; height: 220
-
- DelegateModel {
- id: visualModel; delegate: PhotoDelegate { }
- model: RssModel { id: rssModel; tags: tag }
- }
-
- BusyIndicator {
- id: busyIndicator
- anchors { centerIn: parent; verticalCenterOffset: -20 }
- on: rssModel.status != XmlListModel.Ready
- }
-
- PathView {
- id: photosPathView; model: visualModel.parts.stack; pathItemCount: 5
- visible: !busyIndicator.visible
- anchors.centerIn: parent; anchors.verticalCenterOffset: -30
- path: Path {
- PathAttribute { name: 'z'; value: 9999.0 }
- PathLine { x: 1; y: 1 }
- PathAttribute { name: 'z'; value: 0.0 }
- }
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked: mainWindow.editMode ? photosModel.remove(index) : albumWrapper.state = 'inGrid'
- }
-
- Tag {
- anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 10 }
- frontLabel: tag; backLabel: qsTr("Remove"); flipped: mainWindow.editMode
- onTagChanged: rssModel.tags = tag
- onBackClicked: if (mainWindow.editMode) photosModel.remove(index);
- }
-
- states: [
- State {
- name: 'inGrid'
- PropertyChanges { target: photosGridView; interactive: true }
- PropertyChanges { target: albumsShade; opacity: 1 }
- PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 }
- },
- State {
- name: 'fullscreen'; extend: 'inGrid'
- PropertyChanges { target: photosGridView; interactive: false }
- PropertyChanges { target: photosListView; interactive: true }
- PropertyChanges { target: photosShade; opacity: 1 }
- PropertyChanges { target: backButton; y: -backButton.height - 8 }
- }
- ]
-
- GridView.onAdd: NumberAnimation {
- target: albumWrapper; properties: "scale"; from: 0.0; to: 1.0; easing.type: Easing.OutQuad
- }
- GridView.onRemove: SequentialAnimation {
- PropertyAction { target: albumWrapper; property: "GridView.delayRemove"; value: true }
- NumberAnimation { target: albumWrapper; property: "scale"; from: 1.0; to: 0.0; easing.type: Easing.OutQuad }
- PropertyAction { target: albumWrapper; property: "GridView.delayRemove"; value: false }
- }
-
- transitions: [
- Transition {
- from: '*'; to: 'inGrid'
- SequentialAnimation {
- NumberAnimation { properties: 'opacity'; duration: 250 }
- PauseAnimation { duration: 350 }
- NumberAnimation { target: backButton; properties: "y"; duration: 200; easing.type: Easing.OutQuad }
- }
- },
- Transition {
- from: 'inGrid'; to: '*'
- NumberAnimation { properties: "y,opacity"; easing.type: Easing.OutQuad; duration: 300 }
- }
- ]
- }
- }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml
deleted file mode 100644
index 836abdf6a9..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Image {
- id: container
- property bool on: false
-
- source: "images/busy.png"; visible: container.on
- NumberAnimation on rotation { running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200 }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/Button.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/Button.qml
deleted file mode 100644
index cd575f6d99..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/Button.qml
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: container
-
- property alias label: labelText.text
- property color tint: "transparent"
- signal clicked
-
- width: labelText.width + 70 ; height: labelText.height + 18
-
- BorderImage {
- anchors { fill: container; leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 }
- source: 'images/box-shadow.png'
- border.left: 10; border.top: 10; border.right: 10; border.bottom: 10
- }
-
- Image { anchors.fill: parent; source: "images/cardboard.png"; antialiasing: true }
-
- Rectangle {
- anchors.fill: container; color: container.tint; visible: container.tint != ""
- opacity: 0.25
- }
-
- Text { id: labelText; font.pixelSize: 15; anchors.centerIn: parent }
-
- MouseArea {
- anchors { fill: parent; leftMargin: -20; topMargin: -20; rightMargin: -20; bottomMargin: -20 }
- onClicked: container.clicked()
- }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/EditableButton.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/EditableButton.qml
deleted file mode 100644
index 35df4107eb..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/EditableButton.qml
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: container
-
- property string label
- signal clicked
-
- width: textInput.width + 70 ; height: textInput.height + 18
-
- BorderImage {
- anchors { fill: container; leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 }
- source: 'images/box-shadow.png';
- border.left: 10; border.top: 10; border.right: 10; border.bottom: 10
- }
-
- Image { anchors.fill: parent; source: "images/cardboard.png"; antialiasing: true }
-
- TextInput {
- id: textInput; text: label; font.pixelSize: 15; anchors.centerIn: parent
- Keys.onReturnPressed: {
- container.label = textInput.text
- container.focus = true
- }
- Keys.onEnterPressed: {
- container.label = textInput.text
- container.focus = true
- }
- Keys.onEscapePressed: {
- textInput.text = container.label
- container.focus = true
- }
- }
-
- Rectangle {
- anchors.fill: container; border.color: "steelblue"; border.width: 4
- color: "transparent"; visible: textInput.focus; antialiasing: true
- }
-
- MouseArea {
- anchors { fill: parent; leftMargin: -20; topMargin: -20; rightMargin: -20; bottomMargin: -20 }
- onClicked: { textInput.forceActiveFocus(); Qt.inputMethod.show(); }
- }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
deleted file mode 100644
index 2dcfc6158e..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
+++ /dev/null
@@ -1,198 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "script/script.js" as Script
-
-Package {
- Item { id: stackItem; Package.name: 'stack'; width: 160; height: 153; z: stackItem.PathView.z }
- Item { id: listItem; Package.name: 'list'; width: mainWindow.width + 40; height: 153 }
- Item { id: gridItem; Package.name: 'grid'; width: 160; height: 153 }
-
- Item {
- width: 160; height: 153
-
- Item {
- id: photoWrapper
-
- property double randomAngle: Math.random() * (2 * 6 + 1) - 6
- property double randomAngle2: Math.random() * (2 * 6 + 1) - 6
-
- x: 0; y: 0; width: 140; height: 133
- z: stackItem.PathView.z; rotation: photoWrapper.randomAngle
-
- BorderImage {
- anchors {
- fill: originalImage.status == Image.Ready ? border : placeHolder
- leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8
- }
- source: 'images/box-shadow.png'
- border.left: 10; border.top: 10; border.right: 10; border.bottom: 10
- }
- Rectangle {
- id: placeHolder
-
- property int w: Script.getWidth(content)
- property int h: Script.getHeight(content)
- property double s: Script.calculateScale(w, h, photoWrapper.width)
-
- color: 'white'; anchors.centerIn: parent; antialiasing: true
- width: w * s; height: h * s; visible: originalImage.status != Image.Ready
- Rectangle {
- color: "#878787"; antialiasing: true
- anchors { fill: parent; topMargin: 3; bottomMargin: 3; leftMargin: 3; rightMargin: 3 }
- }
- }
- Rectangle {
- id: border; color: 'white'; anchors.centerIn: parent; antialiasing: true
- width: originalImage.paintedWidth + 6; height: originalImage.paintedHeight + 6
- visible: !placeHolder.visible
- }
- BusyIndicator { anchors.centerIn: parent; on: originalImage.status != Image.Ready }
- Image {
- id: originalImage; antialiasing: true;
- source: "http://" + Script.getImagePath(content); cache: false
- fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height
- }
- Image {
- id: hqImage; antialiasing: true; source: ""; visible: false; cache: false
- fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height
- }
- Binding {
- target: mainWindow; property: "downloadProgress"; value: hqImage.progress
- when: listItem.ListView.isCurrentItem
- }
- Binding {
- target: mainWindow; property: "imageLoading"
- value: (hqImage.status == Image.Loading) ? 1 : 0; when: listItem.ListView.isCurrentItem
- }
- MouseArea {
- width: originalImage.paintedWidth; height: originalImage.paintedHeight; anchors.centerIn: originalImage
- onClicked: {
- if (albumWrapper.state == 'inGrid') {
- gridItem.GridView.view.currentIndex = index;
- albumWrapper.state = 'fullscreen'
- } else {
- gridItem.GridView.view.currentIndex = index;
- albumWrapper.state = 'inGrid'
- }
- }
- }
-
- states: [
- State {
- name: 'stacked'; when: albumWrapper.state == ''
- ParentChange { target: photoWrapper; parent: stackItem; x: 10; y: 10 }
- PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 }
- },
- State {
- name: 'inGrid'; when: albumWrapper.state == 'inGrid'
- ParentChange { target: photoWrapper; parent: gridItem; x: 10; y: 10; rotation: photoWrapper.randomAngle2 }
- },
- State {
- name: 'fullscreen'; when: albumWrapper.state == 'fullscreen'
- ParentChange {
- target: photoWrapper; parent: listItem; x: 0; y: 0; rotation: 0
- width: mainWindow.width; height: mainWindow.height
- }
- PropertyChanges { target: border; opacity: 0 }
- PropertyChanges { target: hqImage; source: listItem.ListView.isCurrentItem ? hq : ""; visible: true }
- }
- ]
-
- transitions: [
- Transition {
- from: 'stacked'; to: 'inGrid'
- SequentialAnimation {
- PauseAnimation { duration: 10 * index }
- ParentAnimation {
- target: photoWrapper; via: foreground
- NumberAnimation {
- target: photoWrapper; properties: 'x,y,rotation,opacity'; duration: 600; easing.type: 'OutQuart'
- }
- }
- }
- },
- Transition {
- from: 'inGrid'; to: 'stacked'
- ParentAnimation {
- target: photoWrapper; via: foreground
- NumberAnimation { properties: 'x,y,rotation,opacity'; duration: 600; easing.type: 'OutQuart' }
- }
- },
- Transition {
- from: 'inGrid'; to: 'fullscreen'
- SequentialAnimation {
- PauseAnimation { duration: gridItem.GridView.isCurrentItem ? 0 : 600 }
- ParentAnimation {
- target: photoWrapper; via: foreground
- NumberAnimation {
- targets: [ photoWrapper, border ]
- properties: 'x,y,width,height,opacity,rotation'
- duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart'
- }
- }
- }
- },
- Transition {
- from: 'fullscreen'; to: 'inGrid'
- ParentAnimation {
- target: photoWrapper; via: foreground
- NumberAnimation {
- targets: [ photoWrapper, border ]
- properties: 'x,y,width,height,rotation,opacity'
- duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart'
- }
- }
- }
- ]
- }
- }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/ProgressBar.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/ProgressBar.qml
deleted file mode 100644
index 73f7f10ace..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/ProgressBar.qml
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: container
-
- property real progress: 0
-
- Behavior on opacity { NumberAnimation { duration: 600 } }
-
- Rectangle { anchors.fill: parent; color: "black"; opacity: 0.5 }
-
- Rectangle {
- id: fill; color: "white"; height: container.height
- width: container.width * container.progress
- }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/RssModel.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/RssModel.qml
deleted file mode 100644
index 5808090250..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/RssModel.qml
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- property string tags : ""
-
- function encodeTags(x) { return encodeURIComponent(x.replace(' ',',')); }
-
- source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+encodeTags(tags)+"&" : "")
- query: "/feed/entry"
- namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
-
- XmlRole { name: "title"; query: "title/string()" }
- XmlRole { name: "content"; query: "content/string()" }
- XmlRole { name: "hq"; query: "link[@rel='enclosure']/@href/string()" }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/Tag.qml b/examples/quick/demos/photoviewer/PhotoViewerCore/Tag.qml
deleted file mode 100644
index aff9f6fb3b..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/Tag.qml
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Flipable {
- id: flipable
-
- property alias frontLabel: frontButton.label
- property alias backLabel: backButton.label
-
- property int angle: 0
- property int randomAngle: Math.random() * (2 * 6 + 1) - 6
- property bool flipped: false
-
- signal frontClicked
- signal backClicked
- signal tagChanged(string tag)
-
- front: EditableButton {
- id: frontButton; rotation: flipable.randomAngle
- anchors { centerIn: parent; verticalCenterOffset: -20 }
- onClicked: flipable.frontClicked()
- onLabelChanged: flipable.tagChanged(label)
- }
-
- back: Button {
- id: backButton; tint: "red"; rotation: flipable.randomAngle
- anchors { centerIn: parent; verticalCenterOffset: -20 }
- onClicked: flipable.backClicked()
- }
-
- transform: Rotation {
- origin.x: flipable.width / 2; origin.y: flipable.height / 2
- axis.x: 0; axis.y: 1; axis.z: 0
- angle: flipable.angle
- }
-
- states: State {
- name: "back"; when: flipable.flipped
- PropertyChanges { target: flipable; angle: 180 }
- }
-
- transitions: Transition {
- ParallelAnimation {
- NumberAnimation { properties: "angle"; duration: 400 }
- SequentialAnimation {
- NumberAnimation { target: flipable; property: "scale"; to: 0.8; duration: 200 }
- NumberAnimation { target: flipable; property: "scale"; to: 1.0; duration: 200 }
- }
- }
- }
-}
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/images/box-shadow.png b/examples/quick/demos/photoviewer/PhotoViewerCore/images/box-shadow.png
deleted file mode 100644
index 23c011d0ff..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/images/box-shadow.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/images/busy.png b/examples/quick/demos/photoviewer/PhotoViewerCore/images/busy.png
deleted file mode 100644
index fc65122d26..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/images/busy.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/images/cardboard.png b/examples/quick/demos/photoviewer/PhotoViewerCore/images/cardboard.png
deleted file mode 100644
index a8a9c6079d..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/images/cardboard.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photoviewer/PhotoViewerCore/script/script.js b/examples/quick/demos/photoviewer/PhotoViewerCore/script/script.js
deleted file mode 100644
index e8ef93a847..0000000000
--- a/examples/quick/demos/photoviewer/PhotoViewerCore/script/script.js
+++ /dev/null
@@ -1,27 +0,0 @@
-.pragma library
-
-function getWidth(string) {
- return (string.match(/width=\"([0-9]+)\"/))[1]
-}
-
-function getHeight(string) {
- return (string.match(/height=\"([0-9]+)\"/))[1]
-}
-
-function getImagePath(string) {
- var pattern = /src=\"http:\/\/(\S+)\"/
- return (string.match(pattern))[1]
-}
-
-function calculateScale(width, height, cellSize) {
- var widthScale = (cellSize * 1.0) / width
- var heightScale = (cellSize * 1.0) / height
- var scale = 0
-
- if (widthScale <= heightScale) {
- scale = widthScale;
- } else if (heightScale < widthScale) {
- scale = heightScale;
- }
- return scale;
-}
diff --git a/examples/quick/demos/photoviewer/doc/images/qtquick-demo-photoviewer-small.png b/examples/quick/demos/photoviewer/doc/images/qtquick-demo-photoviewer-small.png
deleted file mode 100644
index d872310a3e..0000000000
--- a/examples/quick/demos/photoviewer/doc/images/qtquick-demo-photoviewer-small.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc b/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc
deleted file mode 100644
index da9029f817..0000000000
--- a/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc
+++ /dev/null
@@ -1,326 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Photo Viewer
- \ingroup qtquickdemos
- \example demos/photoviewer
- \brief A QML photo viewer that that uses XmlListModel and XmlRole to
- download Flickr feeds, and Package to display the photos in different views.
-
- \image qtquick-demo-photoviewer-small.png
-
- \e{Photo Viewer} demonstrates the following \l{Qt Quick} features:
-
- \list
- \li Using custom types to create screens and screen controls.
- \li Using Qt Quick Controls to create an application window.
- \li Using the \l Package type with a \l DelegateModel to provide
- delegates with a shared context to multiple views.
- \li Using XML list models to download Flickr feeds.
- \li Using the \l Flipable type to create labels with different text on
- the front and back.
- \li Using the PathView, \l Path, PathAttribute, and PathLine types to
- lay out photos on a path.
- \li Providing feedback to users while data is loading.
- \li Localizing applications.
- \endlist
-
- \include examples-run.qdocinc
-
- \section1 Using Custom Types
-
- In the Photo Viewer app, we use the following custom types that are each
- defined in a separate .qml file:
-
- \list
- \li \c AlbumDelegate.qml
- \li \c BusyIndicator.qml
- \li \c Button.qml
- \li \c EditableButton.qml
- \li \c PhotoDelegate.qml
- \li \c ProgressBar.qml
- \li \c RssModel.qml
- \li \c Tag.qml
- \endlist
-
- To use the custom types, we add an import statement to the main QML file,
- main.qml, that imports the folder called \c PhotoViewerCore where the types
- are located:
-
- \quotefromfile demos/photoviewer/main.qml
- \skipto PhotoViewerCore
- \printuntil "
-
- \section1 Creating the Main Window
-
- In main.qml, we use the ApplicationWindow Qt Quick Control to create the app
- main window:
-
- \printuntil visible
-
- We use a ListModel type with \l ListElement types to display photo albums:
-
- \skipto ListModel
- \printuntil Prague
- \printuntil }
-
- List elements are defined like other QML types except that they contain a
- collection of \e role definitions instead of properties. Roles both define
- how the data is accessed and include the data itself. For each list element,
- we use the \c tag role to specify the photos to download.
-
- A DelegateModel type is used together with the \l Package type to provide
- delegates to multiple views. The \c model property holds the model providing
- data for the delegate model and the \c delegate property specifies the
- template defining each item instantiated by a view:
-
- \printuntil DelegateModel
-
- We use a GridView type to lay out the albums as a grid:
-
- \printuntil }
-
- The \c model property references the package name \c album that we specify
- in AlbumDelegate.qml. We use the \l Package type to allow the photos to move
- between different views. The \l Package contains the named items \c browser,
- \c fullscreen, and \c album:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
- \skipto Package
- \printuntil albumWrapper
-
- The named items are used as the delegates by the views that reference the
- special DelegateModel::parts property to select the model that provides
- the chosen delegate.
-
- We use a ListView type to lay out albums in other views:
-
- \quotefromfile demos/photoviewer/main.qml
- \skipto ListView
- \printuntil }
- \skipto ListView
- \printuntil }
-
- \section1 Displaying Photos
-
- We use the PhotoDelegate custom type that is specified in PhotoDelegate.qml
- to display photos. We use a \l Package type to lay out the photos either in
- a stack, list, or a grid:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
- \skipto Package
- \printuntil gridItem
-
- The photos are rotated at random angles by using the \c Math.random()
- JavaScript method:
-
- \printuntil stackItem
-
- We use a BorderImage type to create borders for the images:
-
- \printuntil border.left
- \printuntil }
-
- \section1 Downloading Flickr Feeds
-
- In AlbumDelegate.qml, we use the DelegateModel to provide the
- PhotoDelegate delegate to the RssModel model:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
- \skipto DelegateModel
- \printuntil RssModel
- \printuntil }
-
- In RssModel.qml, we use an XmlListModel type as a data source for
- \l Package objects to download photos from the selected feeds:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/RssModel.qml
- \skipto XmlListModel
- \printuntil encodeTags
-
- We use the \c tags custom property to specify which photos to download. The
- \c encodeTags custom function uses the \c encodeURIComponent JavaScript
- method to ensure that the requests to the server are correctly formatted.
-
- We use the \c source property to fetch photos that have the specified tags
- attached from public Flickr feeds:
-
- \printuntil namespaceDeclarations
-
- The \c query property specifies that the XmlListModel generates a model item
- for each feed entry.
-
- The \c namespaceDeclarations property specifies that the requested document
- uses the namespace \c{http://www.w3.org/2005/Atom}, which is declared as the
- default namespace.
-
- We use the XmlRole type to specify the model item attributes. Each model
- item has the \c title, \c content, and \c hq attributes that match the
- values of the corresponding feed entry:
-
- \printuntil hq
-
- \section1 Creating Flipable Labels
-
- When users select the \b Edit button, the album labels are flipped from
- their front side to their back side and the text on them changes from album
- name to \b Remove.
-
- In AlbumDelegate.qml, we use the Tag custom type to specify the text to
- display on the front and back sides of album labels:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
- \skipto Tag
- \printuntil onBackClicked
- \printuntil }
-
- The \c onTagChanged signal handler is used to change the tag based on
- which the model is populated. The \c onBackClicked signal handler is used to
- remove the album.
-
- In Tag.qml, we use a \l Flipable type with custom properties and signals to
- create the labels:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/Tag.qml
- \skipto Flipable
- \printuntil tagChanged
-
- The \c front property holds the EditableButton custom type that enables
- users to edit the label text:
-
- \printuntil onLabelChanged
- \printuntil }
-
- The \c back property holds the \c Button custom type that is used to remove
- the album:
-
- \printuntil onClicked
- \printuntil }
-
- \section1 Laying Out Photos on a Path
-
- In AlbumDelegate.qml, we use a PathView type to lay out the photos provided
- by the \c visualModel.parts.stack model on a path that has the form of a
- stack:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
- \skipto PathView
- \printuntil 0.0
- \printuntil }
- \printuntil }
-
- The \c path property holds the \l Path type that defines the path used by
- the PathView. The PathAttribute types are used to set a range of
- \c 0 to \c 9999 for the \c z attribute. This way, the path creates a stack
- of album photos. Because each PhotoDelegate is slightly rotated at a random
- angle, this results in a realistic-looking stack of photos.
-
- \section1 Providing Feedback to Users
-
- We use a busy indicator and a progress bar to indicate activity while
- Flickr feeds and photos are being loaded.
-
- In AlbumDelegate.qml, we use the \c BusyIndicator custom type and the
- \c on custom property to display a rotating image while the Flickr feed is
- being loaded:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
- \skipto BusyIndicator
- \printuntil rssModel
- \printuntil }
-
- In PhotoDelegate.qml, we use them to indicate activity while a photo is
- being loaded:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
- \skipto BusyIndicator
- \printuntil }
-
- We define the \c BusyIndicator type in \c BusyIndicator.qml. We use an
- \l Image type to display an image and apply a NumberAnimation to its
- \c rotation property to rotate the image in an infinite loop:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/BusyIndicator.qml
- \skipto Image
- \printuntil }
- \printuntil }
-
- In your apps, you can also use the BusyIndicator type from the
- \l {Qt Quick Controls} module.
-
- In main.qml, we use the \c ProgressBar custom type to indicate progress
- while a high quality version of a photo is being opened on full screen:
-
- \quotefromfile demos/photoviewer/main.qml
- \skipto ProgressBar
- \printuntil }
-
- We define the \c ProgressBar type in \c ProgressBar.qml. We use a
- \l Rectangle type to create the progress bar and apply a NumberAnimation to
- its \c opacity property to change the color of the bar from black to white
- as data loading proceeds:
-
- \quotefromfile demos/photoviewer/PhotoViewerCore/ProgressBar.qml
- \skipto Item
- \printuntil /^\}/
-
- In your apps, you can also use the ProgressBar type from the
- \l {Qt Quick Controls} module.
-
- \section1 Localizing Applications
-
- The example application is translated into German and French. The translated
- strings are loaded at runtime according to the current locale.
-
- We use a \l Column type in main.qml to position buttons for adding and
- editing albums and exiting the application:
-
- \quotefromfile demos/photoviewer/main.qml
- \skipto Column
- \printuntil quit()
- \printuntil }
- \printuntil }
-
- We use the \l[QML]{Qt::}{qsTr()} command to mark the button labels translatable.
-
- We use the \c lupdate() tool to generate the translation source files and
- the \c lrelease() tool to convert the translated strings to the QM files used
- by the application at runtime. These files are stored in the \c i18n
- directory.
-
- To make the application aware of the translations, we add code to the
- \c main() function in the main.cpp file. The code creates a \l QTranslator
- object, loads a translation according to the current locale at runtime, and
- installs the translator object into the application:
-
- \quotefromfile demos/photoviewer/main.cpp
- \skipto main
- \printuntil app.installTranslator
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/photoviewer/i18n/qml_de.qm b/examples/quick/demos/photoviewer/i18n/qml_de.qm
deleted file mode 100644
index 8186e7309f..0000000000
--- a/examples/quick/demos/photoviewer/i18n/qml_de.qm
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photoviewer/i18n/qml_de.ts b/examples/quick/demos/photoviewer/i18n/qml_de.ts
deleted file mode 100644
index c36f169c6a..0000000000
--- a/examples/quick/demos/photoviewer/i18n/qml_de.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="de_DE">
-<context>
- <name>AlbumDelegate</name>
- <message>
- <location filename="../PhotoViewerCore/AlbumDelegate.qml" line="111"/>
- <source>Remove</source>
- <translation>Entfernen</translation>
- </message>
-</context>
-<context>
- <name>main</name>
- <message>
- <location filename="../main.qml" line="93"/>
- <source>Add</source>
- <translation>Zufügen</translation>
- </message>
- <message>
- <location filename="../main.qml" line="102"/>
- <source>Edit</source>
- <translation>Bearbeiten</translation>
- </message>
- <message>
- <location filename="../main.qml" line="107"/>
- <source>Quit</source>
- <translation>Verlassen</translation>
- </message>
- <message>
- <location filename="../main.qml" line="122"/>
- <source>Back</source>
- <translation>Zurück</translation>
- </message>
-</context>
-</TS>
diff --git a/examples/quick/demos/photoviewer/i18n/qml_fr.qm b/examples/quick/demos/photoviewer/i18n/qml_fr.qm
deleted file mode 100644
index e4257d4073..0000000000
--- a/examples/quick/demos/photoviewer/i18n/qml_fr.qm
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/photoviewer/i18n/qml_fr.ts b/examples/quick/demos/photoviewer/i18n/qml_fr.ts
deleted file mode 100644
index 353082569a..0000000000
--- a/examples/quick/demos/photoviewer/i18n/qml_fr.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="fr_FR">
-<context>
- <name>AlbumDelegate</name>
- <message>
- <location filename="../PhotoViewerCore/AlbumDelegate.qml" line="111"/>
- <source>Remove</source>
- <translation>Supprimer</translation>
- </message>
-</context>
-<context>
- <name>main</name>
- <message>
- <location filename="../main.qml" line="93"/>
- <source>Add</source>
- <translation>Ajouter</translation>
- </message>
- <message>
- <location filename="../main.qml" line="102"/>
- <source>Edit</source>
- <translation>Éditer</translation>
- </message>
- <message>
- <location filename="../main.qml" line="107"/>
- <source>Quit</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../main.qml" line="122"/>
- <source>Back</source>
- <translation>Retour</translation>
- </message>
-</context>
-</TS>
diff --git a/examples/quick/demos/photoviewer/main.qml b/examples/quick/demos/photoviewer/main.qml
deleted file mode 100644
index 2e2b8e4ee2..0000000000
--- a/examples/quick/demos/photoviewer/main.qml
+++ /dev/null
@@ -1,139 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQml.Models 2.1
-import "PhotoViewerCore"
-
-ApplicationWindow {
- id: mainWindow
-
- visible: true
-
- Rectangle {
- focus: true
-
- Keys.onBackPressed: {
- event.accepted = true
- backButton.clicked()
- }
- }
-
- property real downloadProgress: 0
- property bool imageLoading: false
- property bool editMode: false
-
- width: 800; height: 480; color: "#d5d6d8"
-
- ListModel {
- id: photosModel
- ListElement { tag: "Flowers" }
- ListElement { tag: "Wildlife" }
- ListElement { tag: "Prague" }
- }
-
- DelegateModel { id: albumVisualModel; model: photosModel; delegate: AlbumDelegate {} }
-
- GridView {
- id: albumView; width: parent.width; height: parent.height; cellWidth: 210; cellHeight: 220
- model: albumVisualModel.parts.album; visible: albumsShade.opacity != 1.0
- }
-
- Column {
- spacing: 20; anchors { bottom: parent.bottom; right: parent.right; rightMargin: 20; bottomMargin: 20 }
- Button {
- id: newButton; label: qsTr("Add"); rotation: 3
- anchors.horizontalCenter: parent.horizontalCenter
- onClicked: {
- mainWindow.editMode = false
- photosModel.append( { tag: "" } )
- albumView.positionViewAtIndex(albumView.count - 1, GridView.Contain)
- }
- }
- Button {
- id: deleteButton; label: qsTr("Edit"); rotation: -2;
- onClicked: mainWindow.editMode = !mainWindow.editMode
- anchors.horizontalCenter: parent.horizontalCenter
- }
- Button {
- id: quitButton; label: qsTr("Quit"); rotation: -2;
- onClicked: Qt.quit()
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
-
- Rectangle {
- id: albumsShade; color: mainWindow.color
- width: parent.width; height: parent.height; opacity: 0.0
- }
-
- ListView { anchors.fill: parent; model: albumVisualModel.parts.browser; interactive: false }
-
- Button {
- id: backButton
- label: qsTr("Back")
- rotation: 3
- x: parent.width - backButton.width - 6
- y: -backButton.height - 8
- visible: Qt.platform.os !== "android"
- }
-
- Rectangle { id: photosShade; color: 'black'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
-
- ListView { anchors.fill: parent; model: albumVisualModel.parts.fullscreen; interactive: false }
-
- Item { id: foreground; anchors.fill: parent }
-
- ProgressBar {
- progress: mainWindow.downloadProgress; width: parent.width; height: 4
- anchors.bottom: parent.bottom; opacity: mainWindow.imageLoading; visible: opacity != 0.0
- }
-}
diff --git a/examples/quick/demos/photoviewer/photoviewer.pro b/examples/quick/demos/photoviewer/photoviewer.pro
deleted file mode 100644
index 885b81b4ad..0000000000
--- a/examples/quick/demos/photoviewer/photoviewer.pro
+++ /dev/null
@@ -1,20 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick xmlpatterns
-
-SOURCES += main.cpp
-
-lupdate_only{
-SOURCES = *.qml \
- PhotoViewerCore/*.qml \
- PhotoViewerCore/script/*.js
-}
-
-TRANSLATIONS += i18n/qml_en.ts \
- i18n/qml_fr.ts \
- i18n/qml_de.ts
-
-RESOURCES += qml.qrc
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/photoviewer
-INSTALLS += target
diff --git a/examples/quick/demos/photoviewer/qml.qrc b/examples/quick/demos/photoviewer/qml.qrc
deleted file mode 100644
index 49f0b27e50..0000000000
--- a/examples/quick/demos/photoviewer/qml.qrc
+++ /dev/null
@@ -1,20 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>main.qml</file>
- <file>PhotoViewerCore/AlbumDelegate.qml</file>
- <file>PhotoViewerCore/BusyIndicator.qml</file>
- <file>PhotoViewerCore/Button.qml</file>
- <file>PhotoViewerCore/EditableButton.qml</file>
- <file>PhotoViewerCore/PhotoDelegate.qml</file>
- <file>PhotoViewerCore/ProgressBar.qml</file>
- <file>PhotoViewerCore/RssModel.qml</file>
- <file>PhotoViewerCore/Tag.qml</file>
- <file>PhotoViewerCore/images/box-shadow.png</file>
- <file>PhotoViewerCore/images/busy.png</file>
- <file>PhotoViewerCore/images/cardboard.png</file>
- <file>PhotoViewerCore/script/script.js</file>
- <file>i18n/qml_fr.qm</file>
- <file>i18n/qml_de.qm</file>
- <file>i18n/qml_en.qm</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/rssnews/content/BusyIndicator.qml b/examples/quick/demos/rssnews/content/BusyIndicator.qml
deleted file mode 100644
index 44b796bdfe..0000000000
--- a/examples/quick/demos/rssnews/content/BusyIndicator.qml
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-
-Image {
- id: container
-
- source: "images/busy.png";
-
- NumberAnimation on rotation {
- running: container.visible
- from: 0; to: 360;
- loops: Animation.Infinite;
- duration: 1200
- }
-}
diff --git a/examples/quick/demos/rssnews/content/NewsDelegate.qml b/examples/quick/demos/rssnews/content/NewsDelegate.qml
deleted file mode 100644
index ed0c2bd977..0000000000
--- a/examples/quick/demos/rssnews/content/NewsDelegate.qml
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-
-Column {
- id: delegate
- width: delegate.ListView.view.width
- spacing: 8
-
- // Returns a string representing how long ago an event occurred
- function timeSinceEvent(pubDate) {
- var result = pubDate;
-
- // We need to modify the pubDate read from the RSS feed
- // so the JavaScript Date object can interpret it
- var d = pubDate.replace(',','').split(' ');
- if (d.length != 6)
- return result;
-
- var date = new Date([d[0], d[2], d[1], d[3], d[4], 'GMT' + d[5]].join(' '));
-
- if (!isNaN(date.getDate())) {
- var age = new Date() - date;
- var minutes = Math.floor(Number(age) / 60000);
- if (minutes < 1440) {
- if (minutes < 2)
- result = qsTr("Just now");
- else if (minutes < 60)
- result = '' + minutes + ' ' + qsTr("minutes ago")
- else if (minutes < 120)
- result = qsTr("1 hour ago");
- else
- result = '' + Math.floor(minutes/60) + ' ' + qsTr("hours ago");
- }
- else {
- result = date.toDateString();
- }
- }
- return result;
- }
-
- Item { height: 8; width: delegate.width }
-
- Row {
- width: parent.width
- spacing: 8
-
- Column {
- Item {
- width: 4
- height: titleText.font.pixelSize / 4
- }
-
- Image {
- id: titleImage
- source: image
- }
- }
-
- Text {
- id: titleText
-
- text: title
- width: delegate.width - titleImage.width
- wrapMode: Text.WordWrap
- font.pixelSize: 26
- font.bold: true
- }
- }
-
- Text {
- width: delegate.width
- font.pixelSize: 12
- textFormat: Text.RichText
- font.italic: true
- text: timeSinceEvent(pubDate) + " (<a href=\"" + link + "\">Link</a>)"
- onLinkActivated: {
- Qt.openUrlExternally(link)
- }
- }
-
- Text {
- id: descriptionText
-
- text: description
- width: parent.width
- wrapMode: Text.WordWrap
- font.pixelSize: 14
- textFormat: Text.StyledText
- horizontalAlignment: Qt.AlignLeft
- }
-}
diff --git a/examples/quick/demos/rssnews/content/RssFeeds.qml b/examples/quick/demos/rssnews/content/RssFeeds.qml
deleted file mode 100644
index 46a6c875c8..0000000000
--- a/examples/quick/demos/rssnews/content/RssFeeds.qml
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-
-ListModel {
- ListElement { name: "Top Stories"; feed: "news.yahoo.com/rss/topstories"; image: "images/TopStories.jpg" }
- ListElement { name: "World"; feed: "news.yahoo.com/rss/world"; image: "images/World.jpg" }
- ListElement { name: "Europe"; feed: "news.yahoo.com/rss/europe"; image: "images/Europe.jpg" }
- ListElement { name: "Asia"; feed: "news.yahoo.com/rss/asia"; image: "images/Asia.jpg" }
- ListElement { name: "U.S. National"; feed: "news.yahoo.com/rss/us"; image: "images/USNational.jpg" }
- ListElement { name: "Politics"; feed: "news.yahoo.com/rss/politics"; image: "images/Politics.jpg" }
- ListElement { name: "Business"; feed: "news.yahoo.com/rss/business"; image: "images/Business.jpg" }
- ListElement { name: "Technology"; feed: "news.yahoo.com/rss/tech"; image: "images/Technology.jpg" }
- ListElement { name: "Entertainment"; feed: "news.yahoo.com/rss/entertainment"; image: "images/Entertainment.jpg" }
- ListElement { name: "Health"; feed: "news.yahoo.com/rss/health"; image: "images/Health.jpg" }
- ListElement { name: "Science"; feed: "news.yahoo.com/rss/science"; image: "images/Science.jpg" }
- ListElement { name: "Sports"; feed: "news.yahoo.com/rss/sports"; image: "images/Sports.jpg" }
-}
diff --git a/examples/quick/demos/rssnews/content/ScrollBar.qml b/examples/quick/demos/rssnews/content/ScrollBar.qml
deleted file mode 100644
index bd774188c8..0000000000
--- a/examples/quick/demos/rssnews/content/ScrollBar.qml
+++ /dev/null
@@ -1,126 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-
-Item {
- id: container
-
- property variant scrollArea
- property int orientation: Qt.Vertical
-
- opacity: 0
-
- function position()
- {
- var ny = 0;
- if (container.orientation == Qt.Vertical)
- ny = scrollArea.visibleArea.yPosition * container.height;
- else
- ny = scrollArea.visibleArea.xPosition * container.width;
-
- if (ny > 2)
- return ny;
- else
- return 2;
- }
-
- function size()
- {
- var nh, ny;
-
- if (container.orientation == Qt.Vertical)
- nh = scrollArea.visibleArea.heightRatio * container.height;
- else
- nh = scrollArea.visibleArea.widthRatio * container.width;
-
- if (container.orientation == Qt.Vertical)
- ny = scrollArea.visibleArea.yPosition * container.height;
- else
- ny = scrollArea.visibleArea.xPosition * container.width;
-
- if (ny > 3) {
- var t;
- if (container.orientation == Qt.Vertical)
- t = Math.ceil(container.height - 3 - ny);
- else
- t = Math.ceil(container.width - 3 - ny);
- if (nh > t)
- return t;
- else
- return nh;
- } else
- return nh + ny;
- }
-
- Rectangle { anchors.fill: parent; color: "Black"; opacity: 0.3 }
-
- BorderImage {
- source: "images/scrollbar.png"
- border { left: 1; right: 1; top: 1; bottom: 1 }
- x: container.orientation == Qt.Vertical ? 2 : position()
- y: container.orientation == Qt.Vertical ? position() : 2
- width: container.orientation == Qt.Vertical ? container.width - 4 : size()
- height: container.orientation == Qt.Vertical ? size() : container.height - 4
- }
-
- states: State {
- name: "visible"
- when: container.orientation == Qt.Vertical ?
- scrollArea.movingVertically :
- scrollArea.movingHorizontally
- PropertyChanges { target: container; opacity: 1.0 }
- }
-
- transitions: Transition {
- from: "visible"; to: ""
- NumberAnimation { properties: "opacity"; duration: 600 }
- }
-}
diff --git a/examples/quick/demos/rssnews/content/images/Asia.jpg b/examples/quick/demos/rssnews/content/images/Asia.jpg
deleted file mode 100644
index a609557a08..0000000000
--- a/examples/quick/demos/rssnews/content/images/Asia.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Business.jpg b/examples/quick/demos/rssnews/content/images/Business.jpg
deleted file mode 100644
index b2c1d92138..0000000000
--- a/examples/quick/demos/rssnews/content/images/Business.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Entertainment.jpg b/examples/quick/demos/rssnews/content/images/Entertainment.jpg
deleted file mode 100644
index 2c69fc04d7..0000000000
--- a/examples/quick/demos/rssnews/content/images/Entertainment.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Europe.jpg b/examples/quick/demos/rssnews/content/images/Europe.jpg
deleted file mode 100644
index bf524e13d0..0000000000
--- a/examples/quick/demos/rssnews/content/images/Europe.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Health.jpg b/examples/quick/demos/rssnews/content/images/Health.jpg
deleted file mode 100644
index 0e8c71f0c9..0000000000
--- a/examples/quick/demos/rssnews/content/images/Health.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Politics.jpg b/examples/quick/demos/rssnews/content/images/Politics.jpg
deleted file mode 100644
index 0b1800c97e..0000000000
--- a/examples/quick/demos/rssnews/content/images/Politics.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Science.jpg b/examples/quick/demos/rssnews/content/images/Science.jpg
deleted file mode 100644
index 7faccbbb97..0000000000
--- a/examples/quick/demos/rssnews/content/images/Science.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Sports.jpg b/examples/quick/demos/rssnews/content/images/Sports.jpg
deleted file mode 100644
index 0ab3bd3ce7..0000000000
--- a/examples/quick/demos/rssnews/content/images/Sports.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Technology.jpg b/examples/quick/demos/rssnews/content/images/Technology.jpg
deleted file mode 100644
index db553028fb..0000000000
--- a/examples/quick/demos/rssnews/content/images/Technology.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/TopStories.jpg b/examples/quick/demos/rssnews/content/images/TopStories.jpg
deleted file mode 100644
index e35bd67f20..0000000000
--- a/examples/quick/demos/rssnews/content/images/TopStories.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/USNational.jpg b/examples/quick/demos/rssnews/content/images/USNational.jpg
deleted file mode 100644
index 82c78228c1..0000000000
--- a/examples/quick/demos/rssnews/content/images/USNational.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/World.jpg b/examples/quick/demos/rssnews/content/images/World.jpg
deleted file mode 100644
index 7a0a806fd4..0000000000
--- a/examples/quick/demos/rssnews/content/images/World.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/btn_close.png b/examples/quick/demos/rssnews/content/images/btn_close.png
deleted file mode 100644
index 1a3dc44380..0000000000
--- a/examples/quick/demos/rssnews/content/images/btn_close.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/busy.png b/examples/quick/demos/rssnews/content/images/busy.png
deleted file mode 100644
index fc65122d26..0000000000
--- a/examples/quick/demos/rssnews/content/images/busy.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/scrollbar.png b/examples/quick/demos/rssnews/content/images/scrollbar.png
deleted file mode 100644
index c2425dd0df..0000000000
--- a/examples/quick/demos/rssnews/content/images/scrollbar.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png b/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png
deleted file mode 100644
index 9d324ceb70..0000000000
--- a/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/rssnews/doc/src/rssnews.qdoc b/examples/quick/demos/rssnews/doc/src/rssnews.qdoc
deleted file mode 100644
index 4ba874cd70..0000000000
--- a/examples/quick/demos/rssnews/doc/src/rssnews.qdoc
+++ /dev/null
@@ -1,372 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - RSS News
- \ingroup qtquickdemos
- \example demos/rssnews
- \brief A QML RSS news reader that uses XmlListModel and XmlRole to download
- XML data, ListModel and ListElement to create a category list, and ListView
- to display the data.
-
- \image qtquick-demo-rssnews-small.png
-
- \e{RSS News} demonstrates the following \l{Qt Quick} features:
-
- \list
- \li Using custom types to create screens and screen controls.
- \li Using list models and list elements to represent data.
- \li Using XML list models to download XML data.
- \li Using list views to display data.
- \li Using the \l Component type to create a footer for the news item
- list view.
- \li Using the \l Image type to create a button for closing the app.
- \endlist
-
- \include examples-run.qdocinc
-
- \section1 Using Custom Types
-
- In the RSS News app, we use the following custom types that are each defined
- in a separate .qml file:
-
- \list
- \li \c BusyIndicator.qml
- \li \c CategoryDelegate.qml
- \li \c NewsDelegate.qml
- \li \c RssFeeds.qml
- \li \c ScrollBar.qml
- \endlist
-
- To use the custom types, we add an import statement to the main QML file,
- rssnews.qml that imports the folder called \c content where the types are
- located:
-
- \quotefromfile demos/rssnews/rssnews.qml
- \skipto content
- \printuntil "
-
- \section1 Creating the Main Window
-
- In rssnews.qml, we use a \l{Rectangle} type with custom properties to create
- the app main window:
-
- \printuntil isPortrait
-
- We will use the custom properties later for loading XML data and for
- adjusting the screen layout depending on its orientation.
-
- \section1 Creating a Category List
-
- In rssnews.qml, we use the RssFeeds custom type that we specify in
- RssFeeds.qml to create a list of feed categories:
-
- \skipto RssFeeds
- \printuntil }
-
- In RssFeeds.qml, we use a ListModel type with a ListElement type to
- create a category list where list elements represent feed categories:
-
- \quotefromfile demos/rssnews/content/RssFeeds.qml
- \skipto ListModel
- \printuntil /^\}/
-
- List elements are defined like other QML types except that they contain a
- collection of \e role definitions instead of properties. Roles both define
- how the data is accessed and include the data itself.
-
- For each list element, we use the \c name role to specify the category name,
- the \c feed role to specify the URL to load the data from, and the \c image
- role to display an image for the category.
-
- In rssnews.qml, we use a ListView type to display the category list:
-
- \quotefromfile demos/rssnews/rssnews.qml
- \skipto ListView
- \printuntil }
- \printuntil }
-
- To lay out the category list horizontally at the top of the window in
- portrait orientation and vertically on the left side in landscape
- orientation, we use the \c orientation property. Based on the orientation,
- we bind either the width or the height of the list to a fixed value
- (\c itemWidth).
-
- We use the \c anchors.top property to position the list view at the top of
- the screen in both orientations.
-
- We use the \c model property to load XML data from the \c rssFeeds model,
- and \c CategoryDelegate as the delegate to instantiate each item in the
- list.
-
- \section1 Creating List Elements
-
- In CategoryDelegate.qml, we use the \l Rectangle type with custom properties
- to create list elements:
-
- \quotefromfile demos/rssnews/content/CategoryDelegate.qml
- \skipto Rectangle
- \printuntil selected
-
- We set the \c selected property to the \c ListView.isCurrentItem attached
- property to specify that \c selected is \c true if \c delegate is the
- current item.
-
- We use the \l Image type \c source property to display the image, centered
- in the delegate, specified for the list element by the \c image role in the
- \c rssFeeds list model:
-
- \skipto Image
- \printuntil }
-
- We use a \l Text type to add titles to list elements:
-
- \printuntil Behavior
- \printuntil }
-
- We use the \c anchors property to position the title at the top of the list
- element, with a 20-pixel margin. We use \c font properties to adjust font
- size and text formatting.
-
- We use the \c color property to brighten the text and to scale it slightly
- larger when the list item is the current item. By applying a \l Behavior to
- the property, we animate the actions of selecting and deselecting list
- items.
-
- We use a MouseArea type to download XML data when users tap a category list
- element:
-
- \skipto MouseArea
- \printuntil }
- \printuntil }
-
- The \c anchors.fill property is set to \c delegate to enable users to tap
- anywhere within the list element.
-
- We use the \c onClicked signal handler to load the XML data for the category
- list. If the tapped category is already current, the \c reload() function
- is called to reload the data.
-
- \section1 Downloading XML Data
-
- In rssnews.qml, we use an XmlListModel type as a data source for ListView
- elements to display news items in the selected category:
-
- \quotefromfile demos/rssnews/rssnews.qml
- \skipto XmlListModel {
- \printuntil namespaceDeclarations
-
- We use the \c source property and the \c window.currentFeed custom property
- to fetch news items for the selected category.
-
- The \c query property specifies that the XmlListModel generates a model item
- for each \c <item> in the XML document.
-
- We use the XmlRole type to specify the model item attributes. Each model
- item has the \c title, \c description, \c image, \c link, and \c pubDate
- attributes that match the values of the corresponding \c <item> in the XML
- document:
-
- \printuntil pubDate
- \printuntil }
-
- We use the \c feedModel model in a ListView type to display the data:
-
- \skipuntil ScrollBar
- \skipto ListView
- \printuntil }
- \printuntil }
-
- To list the news items below the category list in portrait orientation and
- to its right in landscape orientation, we use the \c isPortrait custom
- property to anchor the top of the news items list to the left of \c window
- and bottom of \c categories in portrait orientation and to the right of
- \c categories and bottom of \c window in landscape orientation.
-
- We use the \c anchors.bottom property to anchor the bottom of the list view
- to the bottom of the window in both orientations.
-
- In portrait orientation, we clip the painting of the news items to the
- bounding rectangle of the list view to avoid graphical artifacts when news
- items are scrolled over other items. In landscape, this is not required,
- because the list spans the entire screen vertically.
-
- We use the \c model property to load XML data from the \c feedModel model,
- and use \c NewsDelegate as the delegate to instantiate each item in the
- list.
-
- In NewsDelegate.qml, we use a \l Column type to lay out the XML data:
-
- \quotefromfile demos/rssnews/content/NewsDelegate.qml
- \skipto Column
- \printuntil spacing
-
- Within the column, we use a \l Row and another column to position images and
- title text:
-
- \skipto Row
- \printuntil font.bold
- \printuntil }
- \printuntil }
-
- We generate a textual representation of how long ago the item was posted
- using the \c timeSinceEvent() JavaScript function:
-
- \printuntil }
- \printuntil }
-
- We use the \c onLinkActivated signal handler to open the URL in an external
- browser when users select the link.
-
- \section1 Providing Feedback to Users
-
- In CategoryDelegate.qml, we use the \c BusyIndicator custom type to indicate
- activity while the XML data is being loaded:
-
- \quotefromfile demos/rssnews/content/CategoryDelegate.qml
- \skipto BusyIndicator
- \printuntil }
-
- We use the \c scale property to reduce the indicator size to \c 0.8. We bind
- the \c visible property to the \c isCurrentItem attached property of the
- \c delegate list view and \c loading property of the main window to display
- the indicator image when a category list item is the current item and XML
- data is being loaded.
-
- We define the \c BusyIndicator type in \c BusyIndicator.qml. We use an
- \l Image type to display an image and apply a NumberAnimation to its
- \c rotation property to rotate the image in an infinite loop:
-
- \quotefromfile demos/rssnews/content/BusyIndicator.qml
- \skipto Image
- \printuntil }
- \printuntil }
-
- In your apps, you can also use the BusyIndicator type from the
- \l {Qt Quick Controls} module.
-
- \section1 Creating Scroll Bars
-
- In rssnews.qml, we use our own custom \c ScrollBar type to create scroll
- bars in the category and news item list views. In your apps, you can also
- use the ScrollView type from the \l {Qt Quick Controls} module.
-
- First, we create a scroll bar in the category list view. We bind the
- \c orientation property to the \c isPortrait property and to the
- \c Horizontal value of the \c Qt::Orientation enum type to display a
- horizontal scroll bar in portrait orientation and to the \c Vertical value
- to display a vertical scroll bar in landscape orientation:
-
- \quotefromfile demos/rssnews/rssnews.qml
- \skipto ScrollBar
- \printuntil }
-
- Same as with the \c categories list view, we adjust the width and height of
- the scroll bar based on the \c isPortrait property.
-
- We use the \c scrollArea property to display the scroll bar in the
- \c categories list view.
-
- We use the \c anchors.right property to anchor the scroll bar to the right
- side of the category list.
-
- \skipto ScrollBar
- \printuntil }
-
- Second, we create another scroll bar in the news item list view. We want a
- vertical scroll bar to appear on the right side of the view regardless of
- screen orientation, so we can set the \c width property to \c 8 and bind the
- \c anchors.right property to the \c window.right property. We use the
- \c anchors.top property to anchor the scroll bar top to the bottom of the
- category list in portrait orientation and to the top of the news item list
- in landscape orientation. We use the \c anchors.bottom property to anchor
- the scroll bar bottom to the list view bottom in both orientations.
-
- We define the \c ScrollBar type in \c ScrollBar.qml. We use an \l Item type
- with custom properties to create a container for the scroll bar:
-
- \quotefromfile demos/rssnews/content/ScrollBar.qml
- \skipto Item
- \printuntil opacity
-
- We use a BorderImage type to display the scroll bar thumb at the x and y
- position that we calculate by using the \c position() function:
-
- \skipto BorderImage
- \printuntil height
- \printuntil }
-
- We use the \c size function to calculate the thumb width and height
- depending on the screen orientation.
-
- We use \c states to make the scroll bar visible when the users move the
- scroll area:
-
- \printuntil }
- \printuntil }
-
- We use \c transitions to apply a NumberAnimation to the \c "opacity"
- property when the state changes from "visible" to the default state:
-
- \printuntil /^\}/
-
- \section1 Creating Footers
-
- In rssnews.qml, we use a \l Component type with a \l Rectangle type to
- create a footer for the news list view:
-
- \quotefromfile demos/rssnews/rssnews.qml
- \skipto Component
- \printuntil }
- \printuntil }
- \printuntil }
-
- We bind the \c width of the footer to the width of the component and the
- \c height to the of close button to align them when no news items are
- displayed.
-
- \section1 Creating Buttons
-
- In rssnews.qml, we use an \l Image type to create a simple push button that
- users can tap to close the app:
-
- \printuntil Qt.quit()
- \printuntil }
- \printuntil }
- \printuntil }
-
- We use \c anchors to position the close button in the top right corner of
- the news list view, with 4-pixel margins. Because the close button overlaps
- the category list in portrait orientation, we animate the \c opacity
- property to make the button almost fully transparent when users are
- scrolling the category list.
-
- We use the \c onClicked signal handler within a MouseArea to call the
- \c quit() function when users select the close button.
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/rssnews/main.cpp b/examples/quick/demos/rssnews/main.cpp
deleted file mode 100644
index a0d621bbb6..0000000000
--- a/examples/quick/demos/rssnews/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/rssnews/rssnews)
diff --git a/examples/quick/demos/rssnews/rssnews.pro b/examples/quick/demos/rssnews/rssnews.pro
deleted file mode 100644
index c67c5a6558..0000000000
--- a/examples/quick/demos/rssnews/rssnews.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-TEMPLATE = app
-
-QT += quick qml xml xmlpatterns
-SOURCES += main.cpp
-RESOURCES += rssnews.qrc
-
-OTHER_FILES = rssnews.qml \
- content/*.qml \
- content/*.js \
- content/images/*
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/rssnews
-INSTALLS += target
diff --git a/examples/quick/demos/rssnews/rssnews.qml b/examples/quick/demos/rssnews/rssnews.qml
deleted file mode 100644
index 263154f956..0000000000
--- a/examples/quick/demos/rssnews/rssnews.qml
+++ /dev/null
@@ -1,169 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.2
-import QtQuick.XmlListModel 2.0
-import QtQuick.Window 2.1
-import "./content"
-
-Rectangle {
- id: window
-
- width: 800
- height: 480
-
- property string currentFeed: rssFeeds.get(0).feed
- property bool loading: feedModel.status === XmlListModel.Loading
- property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation
-
- onLoadingChanged: {
- if (feedModel.status == XmlListModel.Ready)
- list.positionViewAtBeginning()
- }
-
- RssFeeds { id: rssFeeds }
-
- XmlListModel {
- id: feedModel
-
- source: "http://" + window.currentFeed
- query: "/rss/channel/item[child::media:content]"
- namespaceDeclarations: "declare namespace media = 'http://search.yahoo.com/mrss/';"
-
- XmlRole { name: "title"; query: "title/string()" }
- // Remove any links from the description
- XmlRole { name: "description"; query: "fn:replace(description/string(), '\&lt;a href=.*\/a\&gt;', '')" }
- XmlRole { name: "image"; query: "media:content/@url/string()" }
- XmlRole { name: "link"; query: "link/string()" }
- XmlRole { name: "pubDate"; query: "pubDate/string()" }
- }
-
- ListView {
- id: categories
- property int itemWidth: 190
-
- width: isPortrait ? parent.width : itemWidth
- height: isPortrait ? itemWidth : parent.height
- orientation: isPortrait ? ListView.Horizontal : ListView.Vertical
- anchors.top: parent.top
- model: rssFeeds
- delegate: CategoryDelegate { itemSize: categories.itemWidth }
- spacing: 3
- }
-
- ScrollBar {
- id: listScrollBar
-
- orientation: isPortrait ? Qt.Horizontal : Qt.Vertical
- height: isPortrait ? 8 : categories.height;
- width: isPortrait ? categories.width : 8
- scrollArea: categories;
- anchors.right: categories.right
- }
-
- ListView {
- id: list
-
- anchors.left: isPortrait ? window.left : categories.right
- anchors.right: closeButton.left
- anchors.top: isPortrait ? categories.bottom : window.top
- anchors.bottom: window.bottom
- anchors.leftMargin: 30
- anchors.rightMargin: 4
- clip: isPortrait
- model: feedModel
- footer: footerText
- delegate: NewsDelegate {}
- }
-
- ScrollBar {
- scrollArea: list
- width: 8
- anchors.right: window.right
- anchors.top: isPortrait ? categories.bottom : window.top
- anchors.bottom: window.bottom
- }
-
- Component {
- id: footerText
-
- Rectangle {
- width: parent.width
- height: closeButton.height
- color: "lightgray"
-
- Text {
- text: "RSS Feed from Yahoo News"
- anchors.centerIn: parent
- font.pixelSize: 14
- }
- }
- }
-
- Image {
- id: closeButton
- source: "content/images/btn_close.png"
- scale: 0.8
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.margins: 4
- opacity: (isPortrait && categories.moving) ? 0.2 : 1.0
- Behavior on opacity {
- NumberAnimation { duration: 300; easing.type: Easing.OutSine }
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked: {
- Qt.quit()
- }
- }
- }
-}
diff --git a/examples/quick/demos/rssnews/rssnews.qmlproject b/examples/quick/demos/rssnews/rssnews.qmlproject
deleted file mode 100644
index 5becbdaed0..0000000000
--- a/examples/quick/demos/rssnews/rssnews.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "rssnews.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
-}
diff --git a/examples/quick/demos/rssnews/rssnews.qrc b/examples/quick/demos/rssnews/rssnews.qrc
deleted file mode 100644
index 1208d44fd7..0000000000
--- a/examples/quick/demos/rssnews/rssnews.qrc
+++ /dev/null
@@ -1,25 +0,0 @@
-<RCC>
- <qresource prefix="/demos/rssnews">
- <file>rssnews.qml</file>
- <file>content/BusyIndicator.qml</file>
- <file>content/CategoryDelegate.qml</file>
- <file>content/NewsDelegate.qml</file>
- <file>content/RssFeeds.qml</file>
- <file>content/ScrollBar.qml</file>
- <file>content/images/btn_close.png</file>
- <file>content/images/Business.jpg</file>
- <file>content/images/busy.png</file>
- <file>content/images/Entertainment.jpg</file>
- <file>content/images/Europe.jpg</file>
- <file>content/images/Health.jpg</file>
- <file>content/images/Asia.jpg</file>
- <file>content/images/Politics.jpg</file>
- <file>content/images/Science.jpg</file>
- <file>content/images/scrollbar.png</file>
- <file>content/images/Sports.jpg</file>
- <file>content/images/Technology.jpg</file>
- <file>content/images/TopStories.jpg</file>
- <file>content/images/USNational.jpg</file>
- <file>content/images/World.jpg</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/samegame/content/Block.qml b/examples/quick/demos/samegame/content/Block.qml
deleted file mode 100644
index 5c6e584e37..0000000000
--- a/examples/quick/demos/samegame/content/Block.qml
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- id: block
- property bool dying: false
- property bool spawned: false
- property int type: 0
- property ParticleSystem particleSystem
-
- Behavior on x {
- enabled: spawned;
- SpringAnimation{ spring: 2; damping: 0.2 }
- }
- Behavior on y {
- SpringAnimation{ spring: 2; damping: 0.2 }
- }
-
- Image {
- id: img
- source: {
- if (type == 0){
- "gfx/red.png";
- } else if (type == 1) {
- "gfx/blue.png";
- } else if (type == 2) {
- "gfx/green.png";
- } else {
- "gfx/yellow.png";
- }
- }
- opacity: 0
- Behavior on opacity { NumberAnimation { duration: 200 } }
- anchors.fill: parent
- }
-
- //Foreground particles
- BlockEmitter {
- id: particles
- system: particleSystem
- group: {
- if (type == 0){
- "red";
- } else if (type == 1) {
- "blue";
- } else if (type == 2) {
- "green";
- } else {
- "yellow";
- }
- }
- anchors.fill: parent
- }
-
- //Paint particles on the background
- PaintEmitter {
- id: particles2
- system: particleSystem
- }
-
- states: [
- State {
- name: "AliveState"; when: spawned == true && dying == false
- PropertyChanges { target: img; opacity: 1 }
- },
-
- State {
- name: "DeathState"; when: dying == true
- StateChangeScript { script: {particleSystem.paused = false; particles.pulse(100); particles2.pulse(100);} }
- PropertyChanges { target: img; opacity: 0 }
- StateChangeScript { script: block.destroy(1000); }
- }
- ]
-}
diff --git a/examples/quick/demos/samegame/content/BlockEmitter.qml b/examples/quick/demos/samegame/content/BlockEmitter.qml
deleted file mode 100644
index cbcc5df99f..0000000000
--- a/examples/quick/demos/samegame/content/BlockEmitter.qml
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-// Needed for singletons QTBUG-34418
-import "."
-
-Emitter {
- property Item block: parent
- velocity: TargetDirection{targetX: block.width/2; targetY: block.height/2; magnitude: -40; magnitudeVariation: 40}
- acceleration: TargetDirection{targetX: block.width/2; targetY: block.height/2; magnitude: -100;}
- shape: EllipseShape{fill:true}
- enabled: false;
- lifeSpan: 700; lifeSpanVariation: 100
- emitRate: 1000
- maximumEmitted: 100 //only fires 0.1s bursts (still 2x old number)
- size: Settings.blockSize * 0.85
- endSize: Settings.blockSize * 0.85 /2
-}
diff --git a/examples/quick/demos/samegame/content/Button.qml b/examples/quick/demos/samegame/content/Button.qml
deleted file mode 100644
index baaa7c73b0..0000000000
--- a/examples/quick/demos/samegame/content/Button.qml
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- property alias imgSrc: image.source
- property alias system: emitter.system
- property alias group: emitter.group
- signal clicked
- property bool rotatedButton: false
-
- width: image.width
- height: image.sourceSize.height
- Image {
- id: image
- height: parent.height
- width: height/sourceSize.height * sourceSize.width
-
- anchors.horizontalCenter: parent.horizontalCenter
- rotation: rotatedButton ? ((Math.random() * 3 + 2) * (Math.random() <= 0.5 ? -1 : 1)) : 0
- MenuEmitter {
- id: emitter
- anchors.fill: parent
- //shape: MaskShape {source: image.source}
- }
- }
- MouseArea {
- anchors.fill: parent
- onClicked: {parent.clicked(); emitter.burst(400);}
- }
-}
diff --git a/examples/quick/demos/samegame/content/GameArea.qml b/examples/quick/demos/samegame/content/GameArea.qml
deleted file mode 100644
index 0f51fcf002..0000000000
--- a/examples/quick/demos/samegame/content/GameArea.qml
+++ /dev/null
@@ -1,238 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-import "samegame.js" as Logic
-import "."
-
-Item {
- id: gameCanvas
- property bool gameOver: true
- property int score: 0
- property int highScore: 0
- property int moves: 0
- property string mode: ""
- property ParticleSystem ps: particleSystem
- //For easy theming
- property alias backgroundVisible: bg.visible
- property string background: "gfx/background.png"
- property string blockFile: "Block.qml"
- property int blockSize: Settings.blockSize
- onBlockFileChanged: Logic.changeBlock(blockFile);
- property alias particlePack: auxLoader.source
- //For multiplayer
- property int score2: 0
- property int curTurn: 1
- property bool autoTurnChange: false
- signal swapPlayers
- property bool swapping: false
- //onSwapPlayers: if (autoTurnChange) Logic.turnChange();//Now implemented below
- //For puzzle
- property url level
- property bool puzzleWon: false
- signal puzzleLost //Since root is tracking the puzzle progress
- function showPuzzleEnd (won) {
- if (won) {
- smokeParticle.color = Qt.rgba(0,1,0,0);
- puzzleWin.play();
- } else {
- smokeParticle.color = Qt.rgba(1,0,0,0);
- puzzleFail.play();
- puzzleLost();
- }
- }
- function showPuzzleGoal (str) {
- puzzleTextBubble.opacity = 1;
- puzzleTextLabel.text = str;
- }
- Image {
- id: bg
- z: -1
- anchors.fill: parent
- source: background;
- fillMode: Image.PreserveAspectCrop
- }
-
- MouseArea {
- anchors.fill: parent; onClicked: {
- if (puzzleTextBubble.opacity == 1) {
- puzzleTextBubble.opacity = 0;
- Logic.finishLoadingMap();
- } else if (!swapping) {
- Logic.handleClick(mouse.x,mouse.y);
- }
- }
- }
-
- Image {
- id: highScoreTextBubble
- opacity: mode == "arcade" && gameOver && gameCanvas.score == gameCanvas.highScore ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
- anchors.centerIn: parent
- z: 10
- source: "gfx/bubble-highscore.png"
- Image {
- anchors.centerIn: parent
- source: "gfx/text-highscore-new.png"
- rotation: -10
- }
- }
-
- Image {
- id: puzzleTextBubble
- anchors.centerIn: parent
- opacity: 0
- Behavior on opacity { NumberAnimation {} }
- z: 10
- source: "gfx/bubble-puzzle.png"
- Connections {
- target: gameCanvas
- onModeChanged: if (mode != "puzzle" && puzzleTextBubble.opacity > 0) puzzleTextBubble.opacity = 0;
- }
- Text {
- id: puzzleTextLabel
- width: parent.width - 24
- anchors.centerIn: parent
- horizontalAlignment: Text.AlignHCenter
- color: "white"
- font.pixelSize: 24
- font.bold: true
- wrapMode: Text.WordWrap
- }
- }
- onModeChanged: {
- p1WonImg.opacity = 0;
- p2WonImg.opacity = 0;
- }
- SmokeText { id: puzzleWin; source: "gfx/icon-ok.png"; system: particleSystem }
- SmokeText { id: puzzleFail; source: "gfx/icon-fail.png"; system: particleSystem }
-
- onSwapPlayers: {
- smokeParticle.color = "yellow"
- Logic.turnChange();
- if (curTurn == 1) {
- p1Text.play();
- } else {
- p2Text.play();
- }
- clickDelay.running = true;
- }
- SequentialAnimation {
- id: clickDelay
- ScriptAction { script: gameCanvas.swapping = true; }
- PauseAnimation { duration: 750 }
- ScriptAction { script: gameCanvas.swapping = false; }
- }
-
- SmokeText {
- id: p1Text; source: "gfx/text-p1-go.png";
- system: particleSystem; playerNum: 1
- opacity: p1WonImg.opacity + p2WonImg.opacity > 0 ? 0 : 1
- }
-
- SmokeText {
- id: p2Text; source: "gfx/text-p2-go.png";
- system: particleSystem; playerNum: 2
- opacity: p1WonImg.opacity + p2WonImg.opacity > 0 ? 0 : 1
- }
-
- onGameOverChanged: {
- if (gameCanvas.mode == "multiplayer") {
- if (gameCanvas.score >= gameCanvas.score2) {
- p1WonImg.opacity = 1;
- } else {
- p2WonImg.opacity = 1;
- }
- }
- }
- Image {
- id: p1WonImg
- source: "gfx/text-p1-won.png"
- anchors.centerIn: parent
- opacity: 0
- Behavior on opacity { NumberAnimation {} }
- z: 10
- }
- Image {
- id: p2WonImg
- source: "gfx/text-p2-won.png"
- anchors.centerIn: parent
- opacity: 0
- Behavior on opacity { NumberAnimation {} }
- z: 10
- }
-
- ParticleSystem{
- id: particleSystem;
- anchors.fill: parent
- z: 5
- ImageParticle {
- id: smokeParticle
- groups: ["smoke"]
- source: "gfx/particle-smoke.png"
- alpha: 0.1
- alphaVariation: 0.1
- color: "yellow"
- }
- Loader {
- id: auxLoader
- anchors.fill: parent
- source: "PrimaryPack.qml"
- onItemChanged: {
- if (item && "particleSystem" in item)
- item.particleSystem = particleSystem
- if (item && "gameArea" in item)
- item.gameArea = gameCanvas
- }
- }
- }
-}
-
diff --git a/examples/quick/demos/samegame/content/LogoAnimation.qml b/examples/quick/demos/samegame/content/LogoAnimation.qml
deleted file mode 100644
index fd89ea8167..0000000000
--- a/examples/quick/demos/samegame/content/LogoAnimation.qml
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- id: container //Positioned where the 48x48 S/G should be
- property alias running: mainAnim.running
- property ParticleSystem particleSystem
- property int dur: 500
- signal boomTime
- Image {
- id: s1
- source: "gfx/logo-s.png"
- y: 0
- }
- Image {
- id: g1
- source: "gfx/logo-g.png"
- y: -128
- }
- Column {
- Repeater {
- model: 2
- Item {
- width: 48
- height: 48
- BlockEmitter {
- id: emitter
- anchors.fill: parent
- group: "red"
- system: particleSystem
- Connections {
- target: container
- onBoomTime: emitter.pulse(100);
- }
- }
- }
- }
- }
- SequentialAnimation {
- id: mainAnim
- running: true
- loops: -1
- PropertyAction { target: g1; property: "y"; value: -128}
- PropertyAction { target: g1; property: "opacity"; value: 1}
- PropertyAction { target: s1; property: "y"; value: 0}
- PropertyAction { target: s1; property: "opacity"; value: 1}
- NumberAnimation { target: g1; property: "y"; from: -96; to: -48; duration: dur}
- ParallelAnimation {
- NumberAnimation { target: g1; property: "y"; from: -48; to: 0; duration: dur}
- NumberAnimation { target: s1; property: "y"; from: 0; to: 48; duration: dur }
- }
- PauseAnimation { duration: dur }
- ScriptAction { script: container.boomTime(); }
- ParallelAnimation {
- NumberAnimation { target: g1; property: "opacity"; to: 0; duration: dur }
- NumberAnimation { target: s1; property: "opacity"; to: 0; duration: dur }
- }
- PropertyAction { target: s1; property: "y"; value: -128}
- PropertyAction { target: s1; property: "opacity"; value: 1}
- NumberAnimation { target: s1; property: "y"; from: -96; to: 0; duration: dur * 2}
- }
-}
diff --git a/examples/quick/demos/samegame/content/MenuEmitter.qml b/examples/quick/demos/samegame/content/MenuEmitter.qml
deleted file mode 100644
index 20cbb2c1a6..0000000000
--- a/examples/quick/demos/samegame/content/MenuEmitter.qml
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Emitter {
- anchors.fill: parent
- velocity: AngleDirection{angleVariation: 360; magnitude: 140; magnitudeVariation: 40}
- enabled: false;
- lifeSpan: 500;
- emitRate: 1
- size: 28
- endSize: 14
- group: "yellow"
-}
diff --git a/examples/quick/demos/samegame/content/PaintEmitter.qml b/examples/quick/demos/samegame/content/PaintEmitter.qml
deleted file mode 100644
index dd67c966a2..0000000000
--- a/examples/quick/demos/samegame/content/PaintEmitter.qml
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-import "."
-
-Emitter {
- property Item block: parent
- anchors.fill: parent
- shape: EllipseShape { fill: true }
- group: {
- if (block.type == 0){
- "redspots";
- } else if (block.type == 1) {
- "bluespots";
- } else if (block.type == 2) {
- "greenspots";
- } else {
- "yellowspots";
- }
- }
- size: Settings.blockSize * 2
- endSize: Settings.blockSize/2
- lifeSpan: 30000
- enabled: false
- emitRate: 60
- maximumEmitted: 60
- velocity: PointDirection{ y: 4; yVariation: 4 }
- /* Possibly better, but dependent on gerrit change,28212
- property real mainIntensity: 0.8
- property real subIntensity: 0.1
- property real colorVariation: 0.005
- onEmitParticles: {//One group, many colors, for better stacking
- for (var i=0; i<particles.length; i++) {
- var particle = particles[i];
- if (block.type == 0) {
- particle.red = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.green = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.blue = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- } else if (block.type == 1) {
- particle.red = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.green = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.blue = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- } else if (block.type == 2) {
- particle.red = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.green = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.blue = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- } else if (block.type == 3) {
- particle.red = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.green = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.blue = subIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- } else {
- particle.red = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.green = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- particle.blue = mainIntensity + (Math.random() * colorVariation * 2 - colorVariation);
- }
- }
- }
- */
-}
diff --git a/examples/quick/demos/samegame/content/PrimaryPack.qml b/examples/quick/demos/samegame/content/PrimaryPack.qml
deleted file mode 100644
index 0e3b77087c..0000000000
--- a/examples/quick/demos/samegame/content/PrimaryPack.qml
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- id: container
- property ParticleSystem particleSystem
- property GameArea gameArea
- onGameAreaChanged: bgstacker.parent = gameArea;//Move to direct child of game canvas
- Item {
- id: bgstacker
- z: 0
- ImageParticle {
- groups: ["yellowspots"]
- color: Qt.darker("yellow");//Actually want desaturated...
- system: particleSystem
- source: "gfx/particle-paint.png"
- colorVariation: 0.2
- alpha: 0.2
- entryEffect: ImageParticle.None
- }
- ImageParticle {
- groups: ["redspots"]
- system: particleSystem
- color: Qt.darker("red");//Actually want desaturated...
- source: "gfx/particle-paint.png"
- colorVariation: 0.2
- alpha: 0.2
- entryEffect: ImageParticle.None
- }
- ImageParticle {
- groups: ["greenspots"]
- system: particleSystem
- color: Qt.darker("green");//Actually want desaturated...
- source: "gfx/particle-paint.png"
- colorVariation: 0.2
- alpha: 0.2
- entryEffect: ImageParticle.None
- }
- ImageParticle {
- groups: ["bluespots"]
- system: particleSystem
- color: Qt.darker("blue");//Actually want desaturated...
- source: "gfx/particle-paint.png"
- colorVariation: 0.2
- alpha: 0.2
- entryEffect: ImageParticle.None
- }
- }
- ImageParticle {
- groups: ["yellow"]
- system: particleSystem
- color: Qt.darker("yellow");//Actually want desaturated...
- source: "gfx/particle-brick.png"
- colorVariation: 0.4
- alpha: 0.1
- }
- ImageParticle {
- groups: ["red"]
- system: particleSystem
- color: Qt.darker("red");//Actually want desaturated...
- source: "gfx/particle-brick.png"
- colorVariation: 0.4
- alpha: 0.1
- }
- ImageParticle {
- groups: ["green"]
- system: particleSystem
- color: Qt.darker("green");//Actually want desaturated...
- source: "gfx/particle-brick.png"
- colorVariation: 0.4
- alpha: 0.1
- }
- ImageParticle {
- groups: ["blue"]
- system: particleSystem
- color: Qt.darker("blue");//Actually want desaturated...
- source: "gfx/particle-brick.png"
- colorVariation: 0.4
- alpha: 0.1
- }
-}
diff --git a/examples/quick/demos/samegame/content/PuzzleBlock.qml b/examples/quick/demos/samegame/content/PuzzleBlock.qml
deleted file mode 100644
index f65b79d516..0000000000
--- a/examples/quick/demos/samegame/content/PuzzleBlock.qml
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- id: block
- property bool dying: false
- property bool spawned: false
- property int type: 0
- property ParticleSystem particleSystem
-
- Behavior on x {
- enabled: spawned;
- NumberAnimation{ easing.type: Easing.OutBounce }
- }
- Behavior on y {
- NumberAnimation{ easing.type: Easing.InQuad }
- }
-
- Image {
- id: img
- source: {
- if (type == 0){
- "gfx/red-puzzle.png";
- } else if (type == 1) {
- "gfx/blue-puzzle.png";
- } else if (type == 2) {
- "gfx/green-puzzle.png";
- } else {
- "gfx/yellow-puzzle.png";
- }
- }
- opacity: 0
- Behavior on opacity { NumberAnimation { duration: 200 } }
- anchors.centerIn: parent
- anchors.verticalCenterOffset: -4
- anchors.horizontalCenterOffset: 4
- }
-
- //Foreground particles
- BlockEmitter {
- id: particles
- system: particleSystem
- group: {
- if (type == 0){
- "red";
- } else if (type == 1) {
- "blue";
- } else if (type == 2) {
- "green";
- } else {
- "yellow";
- }
- }
- anchors.fill: parent
- }
-
- states: [
- State {
- name: "AliveState"; when: spawned == true && dying == false
- PropertyChanges { target: img; opacity: 1 }
- },
-
- State {
- name: "DeathState"; when: dying == true
- PropertyChanges { target: img; scale: 2 }
- StateChangeScript { script: particles.pulse(200); }
- PropertyChanges { target: img; opacity: 0 }
- StateChangeScript { script: block.destroy(1000); }
- }
- ]
-}
diff --git a/examples/quick/demos/samegame/content/SamegameText.qml b/examples/quick/demos/samegame/content/SamegameText.qml
deleted file mode 100644
index c69272bad3..0000000000
--- a/examples/quick/demos/samegame/content/SamegameText.qml
+++ /dev/null
@@ -1,59 +0,0 @@
-/***************************************************************************
-**
-** Copyright (C) 2012 Research In Motion
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "."
-
-Text {
- font.pixelSize: Settings.fontPixelSize;
- color: "white";
- textFormat: Text.StyledText;
- Behavior on opacity { NumberAnimation {} }
-}
diff --git a/examples/quick/demos/samegame/content/SimpleBlock.qml b/examples/quick/demos/samegame/content/SimpleBlock.qml
deleted file mode 100644
index eb2c458d4f..0000000000
--- a/examples/quick/demos/samegame/content/SimpleBlock.qml
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- id: block
- property bool dying: false
- property bool spawned: false
- property int type: 0
- property ParticleSystem particleSystem
-
- Behavior on x {
- enabled: spawned;
- SpringAnimation{ spring: 2; damping: 0.2 }
- }
- Behavior on y {
- SpringAnimation{ spring: 2; damping: 0.2 }
- }
-
- Image {
- id: img
- source: {
- if (type == 0){
- "gfx/red.png";
- } else if (type == 1) {
- "gfx/blue.png";
- } else if (type == 2) {
- "gfx/green.png";
- } else {
- "gfx/yellow.png";
- }
- }
- opacity: 0
- Behavior on opacity { NumberAnimation { duration: 200 } }
- anchors.fill: parent
- }
-
- //Foreground particles
- BlockEmitter {
- id: particles
- system: particleSystem
- group: {
- if (type == 0){
- "red";
- } else if (type == 1) {
- "blue";
- } else if (type == 2) {
- "green";
- } else {
- "yellow";
- }
- }
- anchors.fill: parent
- }
-
- states: [
- State {
- name: "AliveState"; when: spawned == true && dying == false
- PropertyChanges { target: img; opacity: 1 }
- },
-
- State {
- name: "DeathState"; when: dying == true
- StateChangeScript { script: {particleSystem.paused = false; particles.pulse(100); } }
- PropertyChanges { target: img; opacity: 0 }
- StateChangeScript { script: block.destroy(1000); }
- }
- ]
-}
diff --git a/examples/quick/demos/samegame/content/SmokeText.qml b/examples/quick/demos/samegame/content/SmokeText.qml
deleted file mode 100644
index 1fc72010db..0000000000
--- a/examples/quick/demos/samegame/content/SmokeText.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-
-Item {
- z: 10
- property alias source: img.source
- property alias system: emitter.system
- property int playerNum: 1
- function play() {
- anim.running = true;
- }
- anchors.centerIn: parent
- Image {
- opacity: 0
- id: img
- anchors.centerIn: parent
- rotation: playerNum == 1 ? -8 : -5
- Emitter {
- id: emitter
- group: "smoke"
- anchors.fill: parent
- shape: MaskShape { source: img.source }
- enabled: false
- emitRate: 1000
- lifeSpan: 600
- size: 64
- endSize: 32
- velocity: AngleDirection { angleVariation: 360; magnitudeVariation: 160 }
- }
- }
- SequentialAnimation {
- id: anim
- running: false
- PauseAnimation { duration: 500}
- ParallelAnimation {
- NumberAnimation { target: img; property: "opacity"; from: 0.1; to: 1.0 }
- NumberAnimation { target: img; property: "scale"; from: 0.1; to: 1.0 }
- }
- PauseAnimation { duration: 250}
- ScriptAction { script: emitter.pulse(100); }
- NumberAnimation { target: img; property: "opacity"; from: 1.0; to: 0.0 }
- }
-}
diff --git a/examples/quick/demos/samegame/content/gfx/background-puzzle.png b/examples/quick/demos/samegame/content/gfx/background-puzzle.png
deleted file mode 100644
index c2eca5f5dc..0000000000
--- a/examples/quick/demos/samegame/content/gfx/background-puzzle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/background.png b/examples/quick/demos/samegame/content/gfx/background.png
deleted file mode 100644
index 60f57b650f..0000000000
--- a/examples/quick/demos/samegame/content/gfx/background.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/bar.png b/examples/quick/demos/samegame/content/gfx/bar.png
deleted file mode 100644
index 4953cd6221..0000000000
--- a/examples/quick/demos/samegame/content/gfx/bar.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/blue-puzzle.png b/examples/quick/demos/samegame/content/gfx/blue-puzzle.png
deleted file mode 100644
index e550d5935b..0000000000
--- a/examples/quick/demos/samegame/content/gfx/blue-puzzle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/blue.png b/examples/quick/demos/samegame/content/gfx/blue.png
deleted file mode 100644
index b8161c0f70..0000000000
--- a/examples/quick/demos/samegame/content/gfx/blue.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/bubble-highscore.png b/examples/quick/demos/samegame/content/gfx/bubble-highscore.png
deleted file mode 100644
index c4e38df824..0000000000
--- a/examples/quick/demos/samegame/content/gfx/bubble-highscore.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/bubble-puzzle.png b/examples/quick/demos/samegame/content/gfx/bubble-puzzle.png
deleted file mode 100644
index 278556bc8d..0000000000
--- a/examples/quick/demos/samegame/content/gfx/bubble-puzzle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-game-1.png b/examples/quick/demos/samegame/content/gfx/but-game-1.png
deleted file mode 100644
index 3343b7ff13..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-game-1.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-game-2.png b/examples/quick/demos/samegame/content/gfx/but-game-2.png
deleted file mode 100644
index afba106962..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-game-2.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-game-3.png b/examples/quick/demos/samegame/content/gfx/but-game-3.png
deleted file mode 100644
index adea77a687..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-game-3.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-game-4.png b/examples/quick/demos/samegame/content/gfx/but-game-4.png
deleted file mode 100644
index 18c922ba45..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-game-4.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-game-new.png b/examples/quick/demos/samegame/content/gfx/but-game-new.png
deleted file mode 100644
index 257e182585..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-game-new.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-menu.png b/examples/quick/demos/samegame/content/gfx/but-menu.png
deleted file mode 100644
index 8440e87759..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-menu.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-puzzle-next.png b/examples/quick/demos/samegame/content/gfx/but-puzzle-next.png
deleted file mode 100644
index 7e3ed417d0..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-puzzle-next.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/but-quit.png b/examples/quick/demos/samegame/content/gfx/but-quit.png
deleted file mode 100644
index 95c77ced94..0000000000
--- a/examples/quick/demos/samegame/content/gfx/but-quit.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/green-puzzle.png b/examples/quick/demos/samegame/content/gfx/green-puzzle.png
deleted file mode 100644
index 581f76fd8d..0000000000
--- a/examples/quick/demos/samegame/content/gfx/green-puzzle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/green.png b/examples/quick/demos/samegame/content/gfx/green.png
deleted file mode 100644
index da4cca5e7f..0000000000
--- a/examples/quick/demos/samegame/content/gfx/green.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/icon-fail.png b/examples/quick/demos/samegame/content/gfx/icon-fail.png
deleted file mode 100644
index 40726118a9..0000000000
--- a/examples/quick/demos/samegame/content/gfx/icon-fail.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/icon-ok.png b/examples/quick/demos/samegame/content/gfx/icon-ok.png
deleted file mode 100644
index 15a8442e94..0000000000
--- a/examples/quick/demos/samegame/content/gfx/icon-ok.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/icon-time.png b/examples/quick/demos/samegame/content/gfx/icon-time.png
deleted file mode 100644
index 9490e49e90..0000000000
--- a/examples/quick/demos/samegame/content/gfx/icon-time.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/logo-a.png b/examples/quick/demos/samegame/content/gfx/logo-a.png
deleted file mode 100644
index 20c20ba480..0000000000
--- a/examples/quick/demos/samegame/content/gfx/logo-a.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/logo-e.png b/examples/quick/demos/samegame/content/gfx/logo-e.png
deleted file mode 100644
index dd663f114a..0000000000
--- a/examples/quick/demos/samegame/content/gfx/logo-e.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/logo-g.png b/examples/quick/demos/samegame/content/gfx/logo-g.png
deleted file mode 100644
index a319bf9ffa..0000000000
--- a/examples/quick/demos/samegame/content/gfx/logo-g.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/logo-m.png b/examples/quick/demos/samegame/content/gfx/logo-m.png
deleted file mode 100644
index 6a029b3267..0000000000
--- a/examples/quick/demos/samegame/content/gfx/logo-m.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/logo-s.png b/examples/quick/demos/samegame/content/gfx/logo-s.png
deleted file mode 100644
index 963b17546a..0000000000
--- a/examples/quick/demos/samegame/content/gfx/logo-s.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/logo.png b/examples/quick/demos/samegame/content/gfx/logo.png
deleted file mode 100644
index e900eddb2f..0000000000
--- a/examples/quick/demos/samegame/content/gfx/logo.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/particle-brick.png b/examples/quick/demos/samegame/content/gfx/particle-brick.png
deleted file mode 100644
index 5c83896d22..0000000000
--- a/examples/quick/demos/samegame/content/gfx/particle-brick.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/particle-paint.png b/examples/quick/demos/samegame/content/gfx/particle-paint.png
deleted file mode 100644
index 9bd0a2a13f..0000000000
--- a/examples/quick/demos/samegame/content/gfx/particle-paint.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/particle-smoke.png b/examples/quick/demos/samegame/content/gfx/particle-smoke.png
deleted file mode 100644
index b27f954a79..0000000000
--- a/examples/quick/demos/samegame/content/gfx/particle-smoke.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/red-puzzle.png b/examples/quick/demos/samegame/content/gfx/red-puzzle.png
deleted file mode 100644
index 9ceb17e4d0..0000000000
--- a/examples/quick/demos/samegame/content/gfx/red-puzzle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/red.png b/examples/quick/demos/samegame/content/gfx/red.png
deleted file mode 100644
index 681810fe3b..0000000000
--- a/examples/quick/demos/samegame/content/gfx/red.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-highscore-new.png b/examples/quick/demos/samegame/content/gfx/text-highscore-new.png
deleted file mode 100644
index 50f7fcd0f6..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-highscore-new.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-highscore.png b/examples/quick/demos/samegame/content/gfx/text-highscore.png
deleted file mode 100644
index 7198c277b8..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-highscore.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-no-winner.png b/examples/quick/demos/samegame/content/gfx/text-no-winner.png
deleted file mode 100644
index b4a6685111..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-no-winner.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-p1-go.png b/examples/quick/demos/samegame/content/gfx/text-p1-go.png
deleted file mode 100644
index c7bd2a5e75..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-p1-go.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-p1-won.png b/examples/quick/demos/samegame/content/gfx/text-p1-won.png
deleted file mode 100644
index 41c2eb7c98..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-p1-won.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-p1.png b/examples/quick/demos/samegame/content/gfx/text-p1.png
deleted file mode 100644
index b59c87b977..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-p1.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-p2-go.png b/examples/quick/demos/samegame/content/gfx/text-p2-go.png
deleted file mode 100644
index f03cd93afa..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-p2-go.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-p2-won.png b/examples/quick/demos/samegame/content/gfx/text-p2-won.png
deleted file mode 100644
index 116b7f2e7a..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-p2-won.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/text-p2.png b/examples/quick/demos/samegame/content/gfx/text-p2.png
deleted file mode 100644
index d4f2bc7335..0000000000
--- a/examples/quick/demos/samegame/content/gfx/text-p2.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/yellow-puzzle.png b/examples/quick/demos/samegame/content/gfx/yellow-puzzle.png
deleted file mode 100644
index 66044c81b4..0000000000
--- a/examples/quick/demos/samegame/content/gfx/yellow-puzzle.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/gfx/yellow.png b/examples/quick/demos/samegame/content/gfx/yellow.png
deleted file mode 100644
index 6bc5d385e3..0000000000
--- a/examples/quick/demos/samegame/content/gfx/yellow.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/content/levels/TemplateBase.qml b/examples/quick/demos/samegame/content/levels/TemplateBase.qml
deleted file mode 100644
index 6501f277eb..0000000000
--- a/examples/quick/demos/samegame/content/levels/TemplateBase.qml
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Rectangle{
- id: control
- property int scoreTarget: -1
- property int timeTarget: -1
- property int moveTarget: -1
- property bool mustClear: true
- property string goalText: "Clear the level..."
-
- property var startingGrid //If this isn't an array of ints, we will refuse to load the level.
- /* Ints are 0-4. If not enough ints are there it will be prepadded with 0s to fill the grid
- (which ruins everything if you have the wrong number of rows).
- 0 - No block
- 1 - Red
- 2 - Blue
- 3 - Green
- 4 - Yellow
- Ideas for future colors, but not supported in this version:
- 5 - Purple
- 6 - Cyan
- 7 - Gray
- 8 - Black
- 9 - White
- */
-
- width: 320
- height: 416
- color: "white" //TODO: Theme support for both setting themes per level, and seeing it in the control!
-}
diff --git a/examples/quick/demos/samegame/content/levels/level0.qml b/examples/quick/demos/samegame/content/levels/level0.qml
deleted file mode 100644
index 3c09b1f3d3..0000000000
--- a/examples/quick/demos/samegame/content/levels/level0.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- moveTarget: 3
- goalText: "1 of 10<br><br>Clear in three moves..."
- startingGrid: [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 ,
- 0 , 0 , 0 , 0 , 0 , 1 , 1 , 2 , 1 , 1 ,
- 0 , 0 , 0 , 1 , 1 , 3 , 3 , 3 , 3 , 3 ,
- 0 , 1 , 1 , 3 , 3 , 3 , 1 , 3 , 1 , 1 ,
- 1 , 2 , 3 , 3 , 1 , 1 , 3 , 3 , 3 , 3 ,
- 1 , 3 , 3 , 2 , 3 , 3 , 3 , 3 , 1 , 1 ,
- 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level1.qml b/examples/quick/demos/samegame/content/levels/level1.qml
deleted file mode 100644
index 29ad09cf0e..0000000000
--- a/examples/quick/demos/samegame/content/levels/level1.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- timeTarget: 10
- goalText: "2 of 10<br><br>Clear in 10 seconds..."
- startingGrid: [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 1 , 3 , 3 , 3 , 1 , 1 , 1 , 1 , 2 , 2 ,
- 1 , 2 , 3 , 3 , 3 , 1 , 1 , 1 , 1 , 2 ,
- 2 , 2 , 1 , 3 , 3 , 3 , 1 , 1 , 1 , 2 ,
- 2 , 1 , 1 , 1 , 3 , 3 , 3 , 1 , 2 , 2 ,
- 1 , 1 , 1 , 1 , 1 , 3 , 3 , 3 , 2 , 1 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level2.qml b/examples/quick/demos/samegame/content/levels/level2.qml
deleted file mode 100644
index 830776223c..0000000000
--- a/examples/quick/demos/samegame/content/levels/level2.qml
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- scoreTarget: 1200
- timeTarget: 60
- goalText: "3 of 10<br><br>Score over 1200 points in one minute..."
- mustClear: false
- startingGrid: [ 3 , 1 , 2 , 1 , 1 , 2 , 1 , 1 , 3 , 3 ,
- 1 , 3 , 3 , 2 , 3 , 3 , 1 , 1 , 3 , 1 ,
- 3 , 1 , 3 , 3 , 2 , 3 , 3 , 3 , 1 , 2 ,
- 3 , 2 , 2 , 1 , 3 , 3 , 2 , 1 , 1 , 2 ,
- 3 , 1 , 2 , 2 , 2 , 2 , 2 , 1 , 3 , 1 ,
- 2 , 3 , 1 , 2 , 2 , 3 , 3 , 1 , 3 , 2 ,
- 3 , 2 , 1 , 1 , 3 , 3 , 3 , 2 , 2 , 1 ,
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 3 , 1 , 1 ,
- 1 , 3 , 3 , 3 , 1 , 2 , 2 , 3 , 3 , 1 ,
- 3 , 3 , 2 , 1 , 2 , 2 , 1 , 1 , 1 , 3 ,
- 2 , 1 , 3 , 2 , 3 , 2 , 3 , 2 , 2 , 1 ,
- 1 , 3 , 1 , 2 , 1 , 2 , 3 , 1 , 2 , 2 ,
- 1 , 2 , 2 , 2 , 1 , 1 , 2 , 3 , 1 , 2 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level4.qml b/examples/quick/demos/samegame/content/levels/level4.qml
deleted file mode 100644
index 589d386845..0000000000
--- a/examples/quick/demos/samegame/content/levels/level4.qml
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- goalText: "5 of 10<br><br>Clear the level..."
- startingGrid: [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 1 , 3 , 2 , 1 , 1 , 1 , 1 , 3 , 2 , 3 ,
- 1 , 2 , 3 , 1 , 3 , 2 , 2 , 1 , 1 , 2 ,
- 3 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 3 , 3 ,
- 2 , 1 , 1 , 3 , 2 , 1 , 1 , 2 , 1 , 3 ,
- 1 , 3 , 3 , 1 , 2 , 1 , 2 , 1 , 3 , 3 ,
- 1 , 3 , 2 , 2 , 2 , 1 , 1 , 3 , 2 , 3 ,
- 1 , 1 , 3 , 2 , 3 , 3 , 2 , 1 , 1 , 1 ,
- 1 , 2 , 2 , 3 , 2 , 2 , 1 , 3 , 1 , 3 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level5.qml b/examples/quick/demos/samegame/content/levels/level5.qml
deleted file mode 100644
index 78ee6eb355..0000000000
--- a/examples/quick/demos/samegame/content/levels/level5.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- moveTarget: 4
- goalText: "6 of 10<br><br>Clear in four or less moves..."
- startingGrid: [ 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
- 4 , 2 , 2 , 2 , 4 , 3 , 3 , 3 , 4 , 4 ,
- 4 , 2 , 4 , 4 , 4 , 3 , 2 , 3 , 4 , 4 ,
- 4 , 2 , 2 , 2 , 4 , 3 , 3 , 3 , 4 , 4 ,
- 4 , 4 , 4 , 2 , 4 , 3 , 4 , 3 , 4 , 4 ,
- 4 , 2 , 2 , 2 , 4 , 3 , 4 , 3 , 4 , 4 ,
- 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
- 4 , 3 , 4 , 3 , 4 , 2 , 2 , 2 , 4 , 3 ,
- 4 , 3 , 3 , 3 , 4 , 2 , 4 , 4 , 4 , 3 ,
- 4 , 3 , 3 , 3 , 4 , 2 , 2 , 2 , 4 , 3 ,
- 4 , 3 , 4 , 3 , 4 , 2 , 4 , 4 , 4 , 4 ,
- 4 , 3 , 4 , 3 , 4 , 2 , 2 , 2 , 4 , 3 ,
- 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level6.qml b/examples/quick/demos/samegame/content/levels/level6.qml
deleted file mode 100644
index 3e56808dc7..0000000000
--- a/examples/quick/demos/samegame/content/levels/level6.qml
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- moveTarget: 20
- timeTarget: 40
- goalText: "7 of 10<br><br>Clear with 20 moves in 40 seconds (or better)."
- startingGrid: [ 1 , 3 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 2 ,
- 2 , 1 , 2 , 3 , 3 , 1 , 3 , 1 , 1 , 3 ,
- 3 , 1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 1 ,
- 1 , 3 , 1 , 1 , 3 , 1 , 1 , 1 , 2 , 3 ,
- 2 , 1 , 1 , 1 , 3 , 2 , 3 , 3 , 2 , 3 ,
- 3 , 3 , 3 , 3 , 2 , 2 , 3 , 1 , 3 , 2 ,
- 2 , 2 , 3 , 2 , 2 , 3 , 2 , 2 , 2 , 2 ,
- 1 , 2 , 1 , 2 , 1 , 3 , 2 , 3 , 2 , 3 ,
- 1 , 1 , 2 , 3 , 3 , 3 , 3 , 1 , 1 , 2 ,
- 3 , 3 , 2 , 2 , 2 , 2 , 3 , 1 , 3 , 1 ,
- 1 , 2 , 3 , 3 , 3 , 1 , 3 , 2 , 1 , 2 ,
- 1 , 2 , 1 , 1 , 2 , 3 , 1 , 2 , 1 , 3 ,
- 3 , 1 , 2 , 2 , 1 , 3 , 3 , 1 , 3 , 2 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level7.qml b/examples/quick/demos/samegame/content/levels/level7.qml
deleted file mode 100644
index 2e412a0c79..0000000000
--- a/examples/quick/demos/samegame/content/levels/level7.qml
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- goalText: "8 of 10<br><br>Clear the grid."
- startingGrid: [ 2 , 4 , 3 , 2 , 3 , 2 , 3 , 3 , 4 , 3 ,
- 2 , 2 , 3 , 3 , 1 , 4 , 3 , 3 , 3 , 2 ,
- 1 , 4 , 2 , 3 , 4 , 3 , 3 , 1 , 1 , 1 ,
- 2 , 1 , 2 , 4 , 4 , 2 , 2 , 3 , 2 , 1 ,
- 3 , 4 , 4 , 1 , 3 , 2 , 4 , 2 , 1 , 1 ,
- 2 , 2 , 3 , 1 , 2 , 4 , 1 , 2 , 1 , 2 ,
- 1 , 2 , 3 , 2 , 4 , 4 , 3 , 1 , 1 , 2 ,
- 4 , 4 , 2 , 1 , 2 , 4 , 2 , 2 , 4 , 3 ,
- 4 , 2 , 4 , 1 , 3 , 4 , 1 , 4 , 2 , 4 ,
- 4 , 3 , 4 , 1 , 4 , 3 , 1 , 3 , 1 , 1 ,
- 3 , 3 , 2 , 3 , 2 , 4 , 1 , 2 , 4 , 4 ,
- 3 , 4 , 2 , 2 , 4 , 3 , 4 , 1 , 3 , 2 ,
- 4 , 3 , 3 , 4 , 2 , 4 , 1 , 2 , 3 , 2 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level8.qml b/examples/quick/demos/samegame/content/levels/level8.qml
deleted file mode 100644
index 18daa76286..0000000000
--- a/examples/quick/demos/samegame/content/levels/level8.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- scoreTarget: 1000
- goalText: "9 of 10<br><br>Score over 1000 points"
- startingGrid: [ 1 , 4 , 4 , 3 , 2 , 1 , 4 , 2 , 4 , 2 ,
- 2 , 3 , 4 , 4 , 1 , 1 , 1 , 4 , 4 , 4 ,
- 1 , 3 , 1 , 2 , 2 , 1 , 2 , 1 , 4 , 2 ,
- 4 , 3 , 4 , 2 , 1 , 4 , 1 , 2 , 2 , 3 ,
- 3 , 4 , 2 , 4 , 4 , 3 , 2 , 2 , 2 , 1 ,
- 4 , 4 , 3 , 2 , 4 , 4 , 2 , 1 , 1 , 1 ,
- 1 , 2 , 1 , 3 , 4 , 1 , 1 , 3 , 2 , 3 ,
- 3 , 4 , 2 , 2 , 1 , 3 , 2 , 2 , 4 , 2 ,
- 2 , 4 , 1 , 2 , 2 , 4 , 3 , 3 , 3 , 1 ,
- 1 , 2 , 2 , 4 , 1 , 2 , 2 , 3 , 3 , 3 ,
- 4 , 4 , 1 , 4 , 3 , 1 , 3 , 3 , 3 , 4 ,
- 1 , 2 , 4 , 1 , 2 , 1 , 1 , 4 , 2 , 1 ,
- 1 , 2 , 3 , 4 , 2 , 4 , 4 , 2 , 1 , 3 ]
-}
diff --git a/examples/quick/demos/samegame/content/levels/level9.qml b/examples/quick/demos/samegame/content/levels/level9.qml
deleted file mode 100644
index 38d6673189..0000000000
--- a/examples/quick/demos/samegame/content/levels/level9.qml
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-TemplateBase{
- scoreTarget: 2000
- timeTarget: 60
- moveTarget: 20
- mustClear: false
- goalText: "10 of 10<br><br>Score 2000 in one minute with less than 20 moves!"
- startingGrid: [ 3 , 2 , 3 , 1 , 3 , 3 , 4 , 1 , 3 , 3 ,
- 2 , 3 , 2 , 1 , 1 , 2 , 2 , 2 , 4 , 1 ,
- 2 , 4 , 4 , 4 , 3 , 1 , 4 , 4 , 4 , 1 ,
- 3 , 1 , 3 , 4 , 4 , 2 , 2 , 2 , 2 , 3 ,
- 2 , 1 , 4 , 4 , 3 , 3 , 1 , 1 , 3 , 2 ,
- 3 , 2 , 1 , 4 , 3 , 4 , 1 , 3 , 4 , 2 ,
- 3 , 3 , 1 , 4 , 4 , 4 , 2 , 1 , 2 , 3 ,
- 2 , 3 , 4 , 3 , 4 , 1 , 1 , 3 , 2 , 4 ,
- 4 , 4 , 1 , 2 , 4 , 3 , 2 , 2 , 2 , 4 ,
- 1 , 4 , 2 , 2 , 1 , 1 , 2 , 1 , 1 , 4 ,
- 1 , 4 , 3 , 3 , 3 , 1 , 3 , 4 , 4 , 2 ,
- 3 , 4 , 1 , 1 , 2 , 2 , 2 , 3 , 2 , 1 ,
- 3 , 3 , 4 , 3 , 1 , 1 , 1 , 4 , 4 , 3 ]
-}
diff --git a/examples/quick/demos/samegame/content/qmldir b/examples/quick/demos/samegame/content/qmldir
deleted file mode 100644
index 3b552ec1f1..0000000000
--- a/examples/quick/demos/samegame/content/qmldir
+++ /dev/null
@@ -1,13 +0,0 @@
-singleton Settings 1.0 Settings.qml
-Block 1.0 Block.qml
-BlockEmitter 1.0 BlockEmitter.qml
-Button 1.0 Button.qml
-GameArea 1.0 GameArea.qml
-LogoAnimation 1.0 LogoAnimation.qml
-MenuEmitter 1.0 MenuEmitter.qml
-PaintEmitter 1.0 PaintEmitter.qml
-PrimaryPack 1.0 PrimaryPack.qml
-PuzzleBlock 1.0 PuzzleBlock.qml
-SamegameText 1.0 SamegameText.qml
-SimpleBlock 1.0 SimpleBlock.qml
-SmokeText 1.0 SmokeText.qml
diff --git a/examples/quick/demos/samegame/content/samegame.js b/examples/quick/demos/samegame/content/samegame.js
deleted file mode 100644
index 0e2cd4ea5b..0000000000
--- a/examples/quick/demos/samegame/content/samegame.js
+++ /dev/null
@@ -1,590 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/* This script file handles the game logic */
-.pragma library
-.import QtQuick.LocalStorage 2.0 as Sql
-
-var maxColumn = 10;
-var maxRow = 13;
-var types = 3;
-var maxIndex = maxColumn*maxRow;
-var board = new Array(maxIndex);
-var blockSrc = "Block.qml";
-var gameDuration;
-var component = Qt.createComponent(blockSrc);
-var gameCanvas;
-var betweenTurns = false;
-
-var puzzleLevel = null;
-var puzzlePath = "";
-
-var gameMode = "arcade"; //Set in new game, then tweaks behaviour of other functions
-var gameOver = false;
-
-function changeBlock(src)
-{
- blockSrc = src;
- component = Qt.createComponent(blockSrc);
-}
-
-// Index function used instead of a 2D array
-function index(column, row)
-{
- return column + row * maxColumn;
-}
-
-function timeStr(msecs)
-{
- var secs = Math.floor(msecs/1000);
- var m = Math.floor(secs/60);
- var ret = "" + m + "m " + (secs%60) + "s";
- return ret;
-}
-
-function cleanUp()
-{
- if (gameCanvas == undefined)
- return;
- // Delete blocks from previous game
- for (var i = 0; i < maxIndex; i++) {
- if (board[i] != null)
- board[i].destroy();
- board[i] = null;
- }
- if (puzzleLevel != null){
- puzzleLevel.destroy();
- puzzleLevel = null;
- }
- gameCanvas.mode = ""
-}
-
-function startNewGame(gc, mode, map)
-{
- gameCanvas = gc;
- if (mode == undefined)
- gameMode = "arcade";
- else
- gameMode = mode;
- gameOver = false;
-
- cleanUp();
-
- gc.gameOver = false;
- gc.mode = gameMode;
- // Calculate board size
- maxColumn = Math.floor(gameCanvas.width/gameCanvas.blockSize);
- maxRow = Math.floor(gameCanvas.height/gameCanvas.blockSize);
- maxIndex = maxRow * maxColumn;
- if (gameMode == "arcade") //Needs to be after board sizing
- getHighScore();
-
-
- // Initialize Board
- board = new Array(maxIndex);
- gameCanvas.score = 0;
- gameCanvas.score2 = 0;
- gameCanvas.moves = 0;
- gameCanvas.curTurn = 1;
- if (gameMode == "puzzle")
- loadMap(map);
- else//Note that we load them in reverse order for correct visual stacking
- for (var column = maxColumn - 1; column >= 0; column--)
- for (var row = maxRow - 1; row >= 0; row--)
- createBlock(column, row);
- if (gameMode == "puzzle")
- getLevelHistory();//Needs to be after map load
- gameDuration = new Date();
-}
-
-var fillFound; // Set after a floodFill call to the number of blocks found
-var floodBoard; // Set to 1 if the floodFill reaches off that node
-
-// NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
-function handleClick(x,y)
-{
- if (betweenTurns || gameOver || gameCanvas == undefined)
- return;
- var column = Math.floor(x/gameCanvas.blockSize);
- var row = Math.floor(y/gameCanvas.blockSize);
- if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
- return;
- if (board[index(column, row)] == null)
- return;
- // If it's a valid block, remove it and all connected (does nothing if it's not connected)
- floodFill(column,row, -1);
- if (fillFound <= 0)
- return;
- if (gameMode == "multiplayer" && gameCanvas.curTurn == 2)
- gameCanvas.score2 += (fillFound - 1) * (fillFound - 1);
- else
- gameCanvas.score += (fillFound - 1) * (fillFound - 1);
- if (gameMode == "multiplayer" && gameCanvas.curTurn == 2)
- shuffleUp();
- else
- shuffleDown();
- gameCanvas.moves += 1;
- if (gameMode == "endless")
- refill();
- else if (gameMode != "multiplayer")
- victoryCheck();
- if (gameMode == "multiplayer" && !gc.gameOver){
- betweenTurns = true;
- gameCanvas.swapPlayers();//signal, animate and call turnChange() when ready
- }
-}
-
-function floodFill(column,row,type)
-{
- if (board[index(column, row)] == null)
- return;
- var first = false;
- if (type == -1) {
- first = true;
- type = board[index(column,row)].type;
-
- // Flood fill initialization
- fillFound = 0;
- floodBoard = new Array(maxIndex);
- }
- if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
- return;
- if (floodBoard[index(column, row)] == 1 || (!first && type != board[index(column, row)].type))
- return;
- floodBoard[index(column, row)] = 1;
- floodFill(column + 1, row, type);
- floodFill(column - 1, row, type);
- floodFill(column, row + 1, type);
- floodFill(column, row - 1, type);
- if (first == true && fillFound == 0)
- return; // Can't remove single blocks
- board[index(column, row)].dying = true;
- board[index(column, row)] = null;
- fillFound += 1;
-}
-
-function shuffleDown()
-{
- // Fall down
- for (var column = 0; column < maxColumn; column++) {
- var fallDist = 0;
- for (var row = maxRow - 1; row >= 0; row--) {
- if (board[index(column,row)] == null) {
- fallDist += 1;
- } else {
- if (fallDist > 0) {
- var obj = board[index(column, row)];
- obj.y = (row + fallDist) * gameCanvas.blockSize;
- board[index(column, row + fallDist)] = obj;
- board[index(column, row)] = null;
- }
- }
- }
- }
- // Fall to the left
- fallDist = 0;
- for (column = 0; column < maxColumn; column++) {
- if (board[index(column, maxRow - 1)] == null) {
- fallDist += 1;
- } else {
- if (fallDist > 0) {
- for (row = 0; row < maxRow; row++) {
- obj = board[index(column, row)];
- if (obj == null)
- continue;
- obj.x = (column - fallDist) * gameCanvas.blockSize;
- board[index(column - fallDist,row)] = obj;
- board[index(column, row)] = null;
- }
- }
- }
- }
-}
-
-
-function shuffleUp()
-{
- // Fall up
- for (var column = 0; column < maxColumn; column++) {
- var fallDist = 0;
- for (var row = 0; row < maxRow; row++) {
- if (board[index(column,row)] == null) {
- fallDist += 1;
- } else {
- if (fallDist > 0) {
- var obj = board[index(column, row)];
- obj.y = (row - fallDist) * gameCanvas.blockSize;
- board[index(column, row - fallDist)] = obj;
- board[index(column, row)] = null;
- }
- }
- }
- }
- // Fall to the left (or should it be right, so as to be left for P2?)
- fallDist = 0;
- for (column = 0; column < maxColumn; column++) {
- if (board[index(column, 0)] == null) {
- fallDist += 1;
- } else {
- if (fallDist > 0) {
- for (row = 0; row < maxRow; row++) {
- obj = board[index(column, row)];
- if (obj == null)
- continue;
- obj.x = (column - fallDist) * gameCanvas.blockSize;
- board[index(column - fallDist,row)] = obj;
- board[index(column, row)] = null;
- }
- }
- }
- }
-}
-
-function turnChange()//called by ui outside
-{
- betweenTurns = false;
- if (gameCanvas.curTurn == 1){
- shuffleUp();
- gameCanvas.curTurn = 2;
- victoryCheck();
- }else{
- shuffleDown();
- gameCanvas.curTurn = 1;
- victoryCheck();
- }
-}
-
-function refill()
-{
- for (var column = 0; column < maxColumn; column++) {
- for (var row = 0; row < maxRow; row++) {
- if (board[index(column, row)] == null)
- createBlock(column, row);
- }
- }
-}
-
-function victoryCheck()
-{
- // Awards bonuses for no blocks left
- var deservesBonus = true;
- if (board[index(0,maxRow - 1)] != null || board[index(0,0)] != null)
- deservesBonus = false;
- // Checks for game over
- if (deservesBonus){
- if (gameCanvas.curTurn = 1)
- gameCanvas.score += 1000;
- else
- gameCanvas.score2 += 1000;
- }
- gameOver = deservesBonus;
- if (gameCanvas.curTurn == 1){
- if (!(floodMoveCheck(0, maxRow - 1, -1)))
- gameOver = true;
- }else{
- if (!(floodMoveCheck(0, 0, -1, true)))
- gameOver = true;
- }
- if (gameMode == "puzzle"){
- puzzleVictoryCheck(deservesBonus);//Takes it from here
- return;
- }
- if (gameOver) {
- var winnerScore = Math.max(gameCanvas.score, gameCanvas.score2);
- if (gameMode == "multiplayer"){
- gameCanvas.score = winnerScore;
- saveHighScore(gameCanvas.score2);
- }
- saveHighScore(gameCanvas.score);
- gameDuration = new Date() - gameDuration;
- gameCanvas.gameOver = true;
- }
-}
-
-// Only floods up and right, to see if it can find adjacent same-typed blocks
-function floodMoveCheck(column, row, type, goDownInstead)
-{
- if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
- return false;
- if (board[index(column, row)] == null)
- return false;
- var myType = board[index(column, row)].type;
- if (type == myType)
- return true;
- if (goDownInstead)
- return floodMoveCheck(column + 1, row, myType, goDownInstead) ||
- floodMoveCheck(column, row + 1, myType, goDownInstead);
- else
- return floodMoveCheck(column + 1, row, myType) ||
- floodMoveCheck(column, row - 1, myType);
-}
-
-function createBlock(column,row,type)
-{
- // Note that we don't wait for the component to become ready. This will
- // only work if the block QML is a local file. Otherwise the component will
- // not be ready immediately. There is a statusChanged signal on the
- // component you could use if you want to wait to load remote files.
- if (component.status == 1){
- if (type == undefined)
- type = Math.floor(Math.random() * types);
- if (type < 0 || type > 4) {
- console.log("Invalid type requested");//TODO: Is this triggered by custom levels much?
- return;
- }
- var dynamicObject = component.createObject(gameCanvas,
- {"type": type,
- "x": column*gameCanvas.blockSize,
- "y": -1*gameCanvas.blockSize,
- "width": gameCanvas.blockSize,
- "height": gameCanvas.blockSize,
- "particleSystem": gameCanvas.ps});
- if (dynamicObject == null){
- console.log("error creating block");
- console.log(component.errorString());
- return false;
- }
- dynamicObject.y = row*gameCanvas.blockSize;
- dynamicObject.spawned = true;
-
- board[index(column,row)] = dynamicObject;
- }else{
- console.log("error loading block component");
- console.log(component.errorString());
- return false;
- }
- return true;
-}
-
-function showPuzzleError(str)
-{
- //TODO: Nice user visible UI?
- console.log(str);
-}
-
-function loadMap(map)
-{
- puzzlePath = map;
- var levelComp = Qt.createComponent(puzzlePath);
- if (levelComp.status != 1){
- console.log("Error loading level");
- showPuzzleError(levelComp.errorString());
- return;
- }
- puzzleLevel = levelComp.createObject();
- if (puzzleLevel == null || !puzzleLevel.startingGrid instanceof Array) {
- showPuzzleError("Bugger!");
- return;
- }
- gameCanvas.showPuzzleGoal(puzzleLevel.goalText);
- //showPuzzleGoal should call finishLoadingMap as the next thing it does, before handling more events
-}
-
-function finishLoadingMap()
-{
- for (var i in puzzleLevel.startingGrid)
- if (! (puzzleLevel.startingGrid[i] >= 0 && puzzleLevel.startingGrid[i] <= 9) )
- puzzleLevel.startingGrid[i] = 0;
- //TODO: Don't allow loading larger levels, leads to cheating
- while (puzzleLevel.startingGrid.length > maxIndex) puzzleLevel.startingGrid.shift();
- while (puzzleLevel.startingGrid.length < maxIndex) puzzleLevel.startingGrid.unshift(0);
- for (var i in puzzleLevel.startingGrid)
- if (puzzleLevel.startingGrid[i] > 0)
- createBlock(i % maxColumn, Math.floor(i / maxColumn), puzzleLevel.startingGrid[i] - 1);
-
- //### Experimental feature - allow levels to contain arbitrary QML scenes as well!
- //while (puzzleLevel.children.length)
- // puzzleLevel.children[0].parent = gameCanvas;
- gameDuration = new Date(); //Don't start until we finish loading
-}
-
-function puzzleVictoryCheck(clearedAll)//gameOver has also been set if no more moves
-{
- var won = true;
- var soFar = new Date() - gameDuration;
- if (puzzleLevel.scoreTarget != -1 && gameCanvas.score < puzzleLevel.scoreTarget){
- won = false;
- } if (puzzleLevel.scoreTarget != -1 && gameCanvas.score >= puzzleLevel.scoreTarget && !puzzleLevel.mustClear){
- gameOver = true;
- } if (puzzleLevel.timeTarget != -1 && soFar/1000.0 > puzzleLevel.timeTarget){
- gameOver = true;
- } if (puzzleLevel.moveTarget != -1 && gameCanvas.moves >= puzzleLevel.moveTarget){
- gameOver = true;
- } if (puzzleLevel.mustClear && gameOver && !clearedAll) {
- won = false;
- }
-
- if (gameOver) {
- gameCanvas.gameOver = true;
- gameCanvas.showPuzzleEnd(won);
-
- if (won) {
- // Store progress
- saveLevelHistory();
- }
- }
-}
-
-function getHighScore()
-{
- var db = Sql.LocalStorage.openDatabaseSync(
- "SameGame",
- "2.0",
- "SameGame Local Data",
- 100
- );
- db.transaction(
- function(tx) {
- tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(game TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
- // Only show results for the current grid size
- var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "'
- + maxColumn + "x" + maxRow + '" AND game = "' + gameMode + '" ORDER BY score desc');
- if (rs.rows.length > 0)
- gameCanvas.highScore = rs.rows.item(0).score;
- else
- gameCanvas.highScore = 0;
- }
- );
-}
-
-function saveHighScore(score)
-{
- // Offline storage
- var db = Sql.LocalStorage.openDatabaseSync(
- "SameGame",
- "2.0",
- "SameGame Local Data",
- 100
- );
- var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)";
- var data = [
- gameMode,
- score,
- maxColumn + "x" + maxRow,
- Math.floor(gameDuration / 1000)
- ];
- if (score >= gameCanvas.highScore)//Update UI field
- gameCanvas.highScore = score;
-
- db.transaction(
- function(tx) {
- tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(game TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
- tx.executeSql(dataStr, data);
- }
- );
-}
-
-function getLevelHistory()
-{
- var db = Sql.LocalStorage.openDatabaseSync(
- "SameGame",
- "2.0",
- "SameGame Local Data",
- 100
- );
- db.transaction(
- function(tx) {
- tx.executeSql('CREATE TABLE IF NOT EXISTS Puzzle(level TEXT, score NUMBER, moves NUMBER, time NUMBER)');
- var rs = tx.executeSql('SELECT * FROM Puzzle WHERE level = "' + puzzlePath + '" ORDER BY score desc');
- if (rs.rows.length > 0) {
- gameCanvas.puzzleWon = true;
- gameCanvas.highScore = rs.rows.item(0).score;
- } else {
- gameCanvas.puzzleWon = false;
- gameCanvas.highScore = 0;
- }
- }
- );
-}
-
-function saveLevelHistory()
-{
- var db = Sql.LocalStorage.openDatabaseSync(
- "SameGame",
- "2.0",
- "SameGame Local Data",
- 100
- );
- var dataStr = "INSERT INTO Puzzle VALUES(?, ?, ?, ?)";
- var data = [
- puzzlePath,
- gameCanvas.score,
- gameCanvas.moves,
- Math.floor(gameDuration / 1000)
- ];
- gameCanvas.puzzleWon = true;
-
- db.transaction(
- function(tx) {
- tx.executeSql('CREATE TABLE IF NOT EXISTS Puzzle(level TEXT, score NUMBER, moves NUMBER, time NUMBER)');
- tx.executeSql(dataStr, data);
- }
- );
-}
-
-function nuke() //For "Debug mode"
-{
- for (var row = 1; row <= 5; row++) {
- for (var col = 0; col < 5; col++) {
- if (board[index(col, maxRow - row)] != null) {
- board[index(col, maxRow - row)].dying = true;
- board[index(col, maxRow - row)] = null;
- }
- }
- }
- if (gameMode == "multiplayer" && gameCanvas.curTurn == 2)
- shuffleUp();
- else
- shuffleDown();
- if (gameMode == "endless")
- refill();
- else
- victoryCheck();
-}
diff --git a/examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-1.png b/examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-1.png
deleted file mode 100644
index cce9f11017..0000000000
--- a/examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-1.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-2.png b/examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-2.png
deleted file mode 100644
index ca9e8368b1..0000000000
--- a/examples/quick/demos/samegame/doc/images/qtquick-demo-samegame-med-2.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/samegame/doc/src/samegame.qdoc b/examples/quick/demos/samegame/doc/src/samegame.qdoc
deleted file mode 100644
index 25d0376c8e..0000000000
--- a/examples/quick/demos/samegame/doc/src/samegame.qdoc
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Same Game
- \ingroup qtquickdemos
- \example demos/samegame
- \brief A QML implementation of the popular puzzle game by Kuniaki Moribe.
-
- \e{Same Game} demonstrates a QML game with custom types and logic written in
- JavaScript. The game uses various \l{Qt Quick} features such as
- particles, animation, and loading images.
-
- \image qtquick-demo-samegame-med-1.png
- \image qtquick-demo-samegame-med-2.png
-
- For more details about different parts of the example, see
- \l{QML Advanced Tutorial}.
-
- \include examples-run.qdocinc
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/samegame/main.cpp b/examples/quick/demos/samegame/main.cpp
deleted file mode 100644
index d2ccd84cf6..0000000000
--- a/examples/quick/demos/samegame/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/samegame/samegame)
diff --git a/examples/quick/demos/samegame/samegame.pro b/examples/quick/demos/samegame/samegame.pro
deleted file mode 100644
index 7b680490ad..0000000000
--- a/examples/quick/demos/samegame/samegame.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick sql
-SOURCES += main.cpp
-RESOURCES += samegame.qrc
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/samegame
-INSTALLS += target
diff --git a/examples/quick/demos/samegame/samegame.qml b/examples/quick/demos/samegame/samegame.qml
deleted file mode 100644
index 6045c512f9..0000000000
--- a/examples/quick/demos/samegame/samegame.qml
+++ /dev/null
@@ -1,382 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Particles 2.0
-import "content/samegame.js" as Logic
-import "content"
-
-Rectangle {
- id: root
- width: Settings.screenWidth; height: Settings.screenHeight
- property int acc: 0
-
-
- function loadPuzzle() {
- if (gameCanvas.mode != "")
- Logic.cleanUp();
- Logic.startNewGame(gameCanvas,"puzzle","levels/level"+acc+".qml")
- }
- function nextPuzzle() {
- acc = (acc + 1) % 10;
- loadPuzzle();
- }
- Timer {
- id: gameOverTimer
- interval: 1500
- running : gameCanvas.gameOver && gameCanvas.mode == "puzzle" //mode will be reset by cleanUp();
- repeat : false
- onTriggered: {
- Logic.cleanUp();
- nextPuzzle();
- }
- }
-
- Image {
- source: "content/gfx/background.png"
- anchors.fill: parent
- }
-
- GameArea {
- id: gameCanvas
- z: 1
- y: Settings.headerHeight
-
- width: parent.width
- height: parent.height - Settings.headerHeight - Settings.footerHeight
-
- backgroundVisible: root.state == "in-game"
- onModeChanged: if (gameCanvas.mode != "puzzle") puzzleWon = false; //UI has stricter constraints on this variable than the game does
- Age {
- groups: ["redspots", "greenspots", "bluespots", "yellowspots"]
- enabled: root.state == ""
- system: gameCanvas.ps
- }
-
- onPuzzleLost: acc--;//So that nextPuzzle() reloads the current one
-
- }
-
- Item {
- id: menu
- z: 2
- width: parent.width;
- anchors.top: parent.top
- anchors.bottom: bottomBar.top
-
- LogoAnimation {
- x: 64
- y: Settings.headerHeight
- particleSystem: gameCanvas.ps
- running: root.state == ""
- }
- Row {
- x: 112
- y: 20
- Image { source: "content/gfx/logo-a.png" }
- Image { source: "content/gfx/logo-m.png" }
- Image { source: "content/gfx/logo-e.png" }
- }
-
- Column {
- y: 100 + 40
- spacing: Settings.menuButtonSpacing
- width: parent.width
- height: parent.height - (140 + Settings.footerHeight)
-
- Button {
- width: root.width
- rotatedButton: true
- imgSrc: "content/gfx/but-game-1.png"
- onClicked: {
- if (root.state == "in-game")
- return //Prevent double clicking
- root.state = "in-game"
- gameCanvas.blockFile = "Block.qml"
- gameCanvas.background = "gfx/background.png"
- arcadeTimer.start();
- }
- //Emitted particles don't fade out, because ImageParticle is on the GameArea
- system: gameCanvas.ps
- group: "green"
- Timer {
- id: arcadeTimer
- interval: Settings.menuDelay
- running : false
- repeat : false
- onTriggered: Logic.startNewGame(gameCanvas)
- }
- }
-
- Button {
- width: root.width
- rotatedButton: true
- imgSrc: "content/gfx/but-game-2.png"
- onClicked: {
- if (root.state == "in-game")
- return
- root.state = "in-game"
- gameCanvas.blockFile = "Block.qml"
- gameCanvas.background = "gfx/background.png"
- twopTimer.start();
- }
- system: gameCanvas.ps
- group: "green"
- Timer {
- id: twopTimer
- interval: Settings.menuDelay
- running : false
- repeat : false
- onTriggered: Logic.startNewGame(gameCanvas, "multiplayer")
- }
- }
-
- Button {
- width: root.width
- rotatedButton: true
- imgSrc: "content/gfx/but-game-3.png"
- onClicked: {
- if (root.state == "in-game")
- return
- root.state = "in-game"
- gameCanvas.blockFile = "SimpleBlock.qml"
- gameCanvas.background = "gfx/background.png"
- endlessTimer.start();
- }
- system: gameCanvas.ps
- group: "blue"
- Timer {
- id: endlessTimer
- interval: Settings.menuDelay
- running : false
- repeat : false
- onTriggered: Logic.startNewGame(gameCanvas, "endless")
- }
- }
-
- Button {
- width: root.width
- rotatedButton: true
- imgSrc: "content/gfx/but-game-4.png"
- group: "yellow"
- onClicked: {
- if (root.state == "in-game")
- return
- root.state = "in-game"
- gameCanvas.blockFile = "PuzzleBlock.qml"
- gameCanvas.background = "gfx/background.png"
- puzzleTimer.start();
- }
- Timer {
- id: puzzleTimer
- interval: Settings.menuDelay
- running : false
- repeat : false
- onTriggered: loadPuzzle();
- }
- system: gameCanvas.ps
- }
- }
- }
-
- Image {
- id: scoreBar
- source: "content/gfx/bar.png"
- width: parent.width
- z: 6
- y: -Settings.headerHeight
- height: Settings.headerHeight
- Behavior on opacity { NumberAnimation {} }
- SamegameText {
- id: arcadeScore
- anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
- text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
- font.pixelSize: Settings.fontPixelSize
- textFormat: Text.StyledText
- color: "white"
- opacity: gameCanvas.mode == "arcade" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
- }
- SamegameText {
- id: arcadeHighScore
- anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
- text: '<font color="#f7d303">Highscore:</font> ' + gameCanvas.highScore
- opacity: gameCanvas.mode == "arcade" ? 1 : 0
- }
- SamegameText {
- id: p1Score
- anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
- text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
- opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
- }
- SamegameText {
- id: p2Score
- anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
- text: '<font color="#f7d303">P2:</font> ' + gameCanvas.score2
- opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
- rotation: 180
- }
- SamegameText {
- id: puzzleMoves
- anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
- text: '<font color="#f7d303">Moves:</font> ' + gameCanvas.moves
- opacity: gameCanvas.mode == "puzzle" ? 1 : 0
- }
- SamegameText {
- Image {
- source: "content/gfx/icon-time.png"
- x: -20
- }
- id: puzzleTime
- anchors { topMargin: 3; top: parent.top; horizontalCenter: parent.horizontalCenter; horizontalCenterOffset: 20}
- text: "00:00"
- opacity: gameCanvas.mode == "puzzle" ? 1 : 0
- Timer {
- interval: 1000
- repeat: true
- running: gameCanvas.mode == "puzzle" && !gameCanvas.gameOver
- onTriggered: {
- var elapsed = Math.floor((new Date() - Logic.gameDuration)/ 1000.0);
- var mins = Math.floor(elapsed/60.0);
- var secs = (elapsed % 60);
- puzzleTime.text = (mins < 10 ? "0" : "") + mins + ":" + (secs < 10 ? "0" : "") + secs;
- }
- }
- }
- SamegameText {
- id: puzzleScore
- anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
- text: '<font color="#f7d303">Score:</font> ' + gameCanvas.score
- opacity: gameCanvas.mode == "puzzle" ? 1 : 0
- }
- }
-
- Image {
- id: bottomBar
- width: parent.width
- height: Settings.footerHeight
- source: "content/gfx/bar.png"
- y: parent.height - Settings.footerHeight;
- z: 2
- Button {
- id: quitButton
- height: Settings.toolButtonHeight
- imgSrc: "content/gfx/but-quit.png"
- onClicked: {Qt.quit(); }
- anchors { left: parent.left; verticalCenter: parent.verticalCenter; leftMargin: 11 }
- }
- Button {
- id: menuButton
- height: Settings.toolButtonHeight
- imgSrc: "content/gfx/but-menu.png"
- visible: (root.state == "in-game");
- onClicked: {root.state = ""; Logic.cleanUp(); gameCanvas.mode = ""}
- anchors { left: quitButton.right; verticalCenter: parent.verticalCenter; leftMargin: 0 }
- }
- Button {
- id: againButton
- height: Settings.toolButtonHeight
- imgSrc: "content/gfx/but-game-new.png"
- visible: (root.state == "in-game");
- opacity: gameCanvas.gameOver && (gameCanvas.mode == "arcade" || gameCanvas.mode == "multiplayer")
- Behavior on opacity{ NumberAnimation {} }
- onClicked: {if (gameCanvas.gameOver) { Logic.startNewGame(gameCanvas, gameCanvas.mode);}}
- anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
- }
- Button {
- id: nextButton
- height: Settings.toolButtonHeight
- imgSrc: "content/gfx/but-puzzle-next.png"
- visible: (root.state == "in-game") && gameCanvas.mode == "puzzle" && gameCanvas.puzzleWon
- opacity: gameCanvas.puzzleWon ? 1 : 0
- Behavior on opacity{ NumberAnimation {} }
- onClicked: {if (gameCanvas.puzzleWon) nextPuzzle();}
- anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
- }
- }
-
- Connections {
- target: root
- onStateChanged: stateChangeAnim.running = true
- }
- SequentialAnimation {
- id: stateChangeAnim
- ParallelAnimation {
- NumberAnimation { target: bottomBar; property: "y"; to: root.height; duration: Settings.menuDelay/2; easing.type: Easing.OutQuad }
- NumberAnimation { target: scoreBar; property: "y"; to: -Settings.headerHeight; duration: Settings.menuDelay/2; easing.type: Easing.OutQuad }
- }
- ParallelAnimation {
- NumberAnimation { target: bottomBar; property: "y"; to: root.height - Settings.footerHeight; duration: Settings.menuDelay/2; easing.type: Easing.OutBounce}
- NumberAnimation { target: scoreBar; property: "y"; to: root.state == "" ? -Settings.headerHeight : 0; duration: Settings.menuDelay/2; easing.type: Easing.OutBounce}
- }
- }
-
- states: [
- State {
- name: "in-game"
- PropertyChanges {
- target: menu
- opacity: 0
- visible: false
- }
- }
- ]
-
- transitions: [
- Transition {
- NumberAnimation {properties: "x,y,opacity"}
- }
- ]
-
- //"Debug mode"
- focus: true
- Keys.onAsteriskPressed: Logic.nuke();
- Keys.onSpacePressed: gameCanvas.puzzleWon = true;
-}
diff --git a/examples/quick/demos/samegame/samegame.qmlproject b/examples/quick/demos/samegame/samegame.qmlproject
deleted file mode 100644
index 42ffacf4f8..0000000000
--- a/examples/quick/demos/samegame/samegame.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "samegame.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
-}
diff --git a/examples/quick/demos/samegame/samegame.qrc b/examples/quick/demos/samegame/samegame.qrc
deleted file mode 100644
index 348ee109f9..0000000000
--- a/examples/quick/demos/samegame/samegame.qrc
+++ /dev/null
@@ -1,73 +0,0 @@
-<RCC>
- <qresource prefix="/demos/samegame">
- <file>samegame.qml</file>
- <file>content/qmldir</file>
- <file>content/Settings.qml</file>
- <file>content/gfx/text-p1-won.png</file>
- <file>content/gfx/background-puzzle.png</file>
- <file>content/gfx/background.png</file>
- <file>content/gfx/bar.png</file>
- <file>content/gfx/blue-puzzle.png</file>
- <file>content/gfx/blue.png</file>
- <file>content/gfx/bubble-highscore.png</file>
- <file>content/gfx/bubble-puzzle.png</file>
- <file>content/gfx/but-game-1.png</file>
- <file>content/gfx/but-game-2.png</file>
- <file>content/gfx/but-game-3.png</file>
- <file>content/gfx/but-game-4.png</file>
- <file>content/gfx/but-game-new.png</file>
- <file>content/gfx/but-menu.png</file>
- <file>content/gfx/but-puzzle-next.png</file>
- <file>content/gfx/but-quit.png</file>
- <file>content/gfx/green-puzzle.png</file>
- <file>content/gfx/green.png</file>
- <file>content/gfx/icon-fail.png</file>
- <file>content/gfx/icon-ok.png</file>
- <file>content/gfx/icon-time.png</file>
- <file>content/gfx/logo-a.png</file>
- <file>content/gfx/logo-e.png</file>
- <file>content/gfx/logo-g.png</file>
- <file>content/gfx/logo-m.png</file>
- <file>content/gfx/logo-s.png</file>
- <file>content/gfx/logo.png</file>
- <file>content/gfx/particle-brick.png</file>
- <file>content/gfx/particle-paint.png</file>
- <file>content/gfx/particle-smoke.png</file>
- <file>content/gfx/red-puzzle.png</file>
- <file>content/gfx/red.png</file>
- <file>content/gfx/text-highscore-new.png</file>
- <file>content/gfx/text-highscore.png</file>
- <file>content/gfx/text-no-winner.png</file>
- <file>content/gfx/text-p1-go.png</file>
- <file>content/gfx/text-p1.png</file>
- <file>content/gfx/text-p2-go.png</file>
- <file>content/gfx/text-p2-won.png</file>
- <file>content/gfx/text-p2.png</file>
- <file>content/gfx/yellow-puzzle.png</file>
- <file>content/gfx/yellow.png</file>
- <file>content/levels/level0.qml</file>
- <file>content/levels/level1.qml</file>
- <file>content/levels/level2.qml</file>
- <file>content/levels/level3.qml</file>
- <file>content/levels/level4.qml</file>
- <file>content/levels/level5.qml</file>
- <file>content/levels/level6.qml</file>
- <file>content/levels/level7.qml</file>
- <file>content/levels/level8.qml</file>
- <file>content/levels/level9.qml</file>
- <file>content/levels/TemplateBase.qml</file>
- <file>content/SamegameText.qml</file>
- <file>content/SimpleBlock.qml</file>
- <file>content/Block.qml</file>
- <file>content/BlockEmitter.qml</file>
- <file>content/Button.qml</file>
- <file>content/GameArea.qml</file>
- <file>content/LogoAnimation.qml</file>
- <file>content/MenuEmitter.qml</file>
- <file>content/PaintEmitter.qml</file>
- <file>content/PrimaryPack.qml</file>
- <file>content/PuzzleBlock.qml</file>
- <file>content/samegame.js</file>
- <file>content/SmokeText.qml</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/stocqt/content/+windows/Settings.qml b/examples/quick/demos/stocqt/content/+windows/Settings.qml
deleted file mode 100644
index 137ec546cc..0000000000
--- a/examples/quick/demos/stocqt/content/+windows/Settings.qml
+++ /dev/null
@@ -1,56 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-pragma Singleton
-import QtQml 2.0
-
-QtObject {
- property string fontFamily: "Arial"
-}
diff --git a/examples/quick/demos/stocqt/content/Banner.qml b/examples/quick/demos/stocqt/content/Banner.qml
deleted file mode 100644
index bcba122043..0000000000
--- a/examples/quick/demos/stocqt/content/Banner.qml
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Layouts 1.1
-
-Rectangle {
- id: banner
- height: 80
- color: "#000000"
-
- GridLayout {
- anchors.fill: parent
- rows: 1
- columns: 3
- Rectangle {
- Layout.leftMargin: 10
- Layout.topMargin: 20
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- Image {
- id: arrow
- source: "./images/icon-left-arrow.png"
- visible: root.currentIndex == 1 ? true : false
-
- MouseArea {
- anchors.fill: parent
- onClicked: root.currentIndex = 0;
- }
- }
- }
- Text {
- id: stocText
- color: "#ffffff"
- font.family: "Abel"
- font.pointSize: 40
- text: "Stoc"
- Layout.alignment: Qt.AlignRight
- Layout.leftMargin: parent.width / 2.5
- }
- Text {
- id: qtText
- color: "#5caa15"
- font.family: "Abel"
- font.pointSize: 40
- text: "Qt"
- Layout.fillWidth: true
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/Button.qml b/examples/quick/demos/stocqt/content/Button.qml
deleted file mode 100644
index ed9b4ed491..0000000000
--- a/examples/quick/demos/stocqt/content/Button.qml
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "."
-
-Rectangle {
- id: button
- signal clicked
- property alias text: txt.text
- property bool buttonEnabled: false
- width: Math.max(64, txt.width + 16)
- height: 32
- color: "transparent"
- MouseArea {
- anchors.fill: parent
- onClicked: button.clicked()
- }
- Text {
- anchors.centerIn: parent
- font.family: Settings.fontFamily
- font.pointSize: 19
- font.weight: Font.DemiBold
- color: button.buttonEnabled ? "#000000" : "#14aaff"
- id: txt
- }
-}
diff --git a/examples/quick/demos/stocqt/content/CheckBox.qml b/examples/quick/demos/stocqt/content/CheckBox.qml
deleted file mode 100644
index 9f9138963b..0000000000
--- a/examples/quick/demos/stocqt/content/CheckBox.qml
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: button
- property bool buttonEnabled: true
- width: 30
- height: 30
- x: 5
- MouseArea {
- id: mouse
- anchors.fill: parent
- onClicked: {
- if (buttonEnabled)
- buttonEnabled = false;
- else
- buttonEnabled = true;
- }
- }
- Rectangle {
- id: checkbox
- width: 30
- height: 30
- border.color: "#999999"
- border.width: 1
- antialiasing: true
- radius: 2
- color: "transparent"
- Rectangle {
- anchors.fill: parent
- anchors.margins: 5
- antialiasing: true
- radius: 1
- color: mouse.pressed || buttonEnabled ? "#999999" : "transparent"
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/Settings.qml b/examples/quick/demos/stocqt/content/Settings.qml
deleted file mode 100644
index 9c7c59ed70..0000000000
--- a/examples/quick/demos/stocqt/content/Settings.qml
+++ /dev/null
@@ -1,56 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-pragma Singleton
-import QtQml 2.0
-
-QtObject {
- property string fontFamily: "Open Sans"
-}
diff --git a/examples/quick/demos/stocqt/content/StockChart.qml b/examples/quick/demos/stocqt/content/StockChart.qml
deleted file mode 100644
index 0af06a8d54..0000000000
--- a/examples/quick/demos/stocqt/content/StockChart.qml
+++ /dev/null
@@ -1,400 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Layouts 1.1
-import "."
-
-Rectangle {
- id: chart
-
- property var stockModel: null
- property var startDate: new Date()
- property var endDate: new Date()
- property string activeChart: "week"
- property var settings
- property int gridSize: 4
- property real gridStep: gridSize ? (canvas.width - canvas.tickMargin) / gridSize : canvas.xGridStep
-
- function update() {
- endDate = new Date(stockModel.newest);
- if (chart.activeChart === "month") {
- chart.startDate = new Date(stockModel.newest.getFullYear(),
- stockModel.newest.getMonth() - 1,
- stockModel.newest.getDate());
- gridSize = 4;
- }
- else if (chart.activeChart === "quarter") {
- chart.startDate = new Date(stockModel.newest.getFullYear(),
- stockModel.newest.getMonth() - 3,
- stockModel.newest.getDate());
- gridSize = 3;
- }
- else if (chart.activeChart === "halfyear") {
- chart.startDate = new Date(stockModel.newest.getFullYear(),
- stockModel.newest.getMonth() - 6,
- stockModel.newest.getDate());
- gridSize = 6;
- }
- else {
- chart.startDate = new Date(stockModel.newest.getFullYear(),
- stockModel.newest.getMonth(),
- stockModel.newest.getDate() - 7);
- gridSize = 0;
- }
-
- canvas.requestPaint();
- }
-
- GridLayout {
- anchors.fill: parent
- columns: 6
- rows: 3
- columnSpacing: 4
- Button {
- id: weekButton
- text: "Week"
- buttonEnabled: chart.activeChart === "week"
- onClicked: {
- chart.activeChart = "week";
- chart.update();
- }
- }
-
- Button {
- id: monthButton
- text: "Month"
- buttonEnabled: chart.activeChart === "month"
- onClicked: {
- chart.activeChart = "month";
- chart.update();
- }
- }
-
- Button {
- id: quarterlyButton
- text: "3 Months"
- buttonEnabled: chart.activeChart === "quarter"
- onClicked: {
- chart.activeChart = "quarter";
- chart.update();
- }
- }
-
- Button {
- id: halfYearlyButton
- text: "6 Months"
- buttonEnabled: chart.activeChart === "halfyear"
- onClicked: {
- chart.activeChart = "halfyear";
- chart.update();
- }
- }
-
- Canvas {
- id: canvas
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.columnSpan: 6
- // Uncomment below lines to use OpenGL hardware accelerated rendering.
- // See Canvas documentation for available options.
- // renderTarget: Canvas.FramebufferObject
- // renderStrategy: Canvas.Threaded
-
- property int pixelSkip: 1
- property int numPoints: 1
- property int tickMargin: 34
-
- property real xGridStep: (canvas.width - tickMargin) / numPoints
- property real yGridOffset: canvas.height / 26
- property real yGridStep: canvas.height / 12
-
- function drawBackground(ctx) {
- ctx.save();
- ctx.fillStyle = "#ffffff";
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.strokeStyle = "#d7d7d7";
- ctx.beginPath();
- // Horizontal grid lines
- for (var i = 0; i < 12; i++) {
- ctx.moveTo(0, canvas.yGridOffset + i * canvas.yGridStep);
- ctx.lineTo(canvas.width, canvas.yGridOffset + i * canvas.yGridStep);
- }
-
- // Vertical grid lines
- var height = 35 * canvas.height / 36;
- var yOffset = canvas.height - height;
- var xOffset = 0;
- for (i = 0; i < chart.gridSize; i++) {
- ctx.moveTo(xOffset + i * chart.gridStep, yOffset);
- ctx.lineTo(xOffset + i * chart.gridStep, height);
- }
- ctx.stroke();
-
- // Right ticks
- ctx.strokeStyle = "#666666";
- ctx.beginPath();
- var xStart = canvas.width - tickMargin;
- ctx.moveTo(xStart, 0);
- ctx.lineTo(xStart, canvas.height);
- for (i = 0; i < 12; i++) {
- ctx.moveTo(xStart, canvas.yGridOffset + i * canvas.yGridStep);
- ctx.lineTo(canvas.width, canvas.yGridOffset + i * canvas.yGridStep);
- }
- ctx.moveTo(0, canvas.yGridOffset + 9 * canvas.yGridStep);
- ctx.lineTo(canvas.width, canvas.yGridOffset + 9 * canvas.yGridStep);
- ctx.closePath();
- ctx.stroke();
-
- ctx.restore();
- }
-
- // Returns a shortened, readable version of the potentially
- // large volume number.
- function volumeToString(value) {
- if (value < 1000)
- return value;
- var exponent = parseInt(Math.log(value) / Math.log(1000));
- var shortVal = parseFloat(parseFloat(value) / Math.pow(1000, exponent)).toFixed(1);
-
- // Drop the decimal point on 3-digit values to make it fit
- if (shortVal >= 100.0) {
- shortVal = parseFloat(shortVal).toFixed(0);
- }
- return shortVal + "KMBTG".charAt(exponent - 1);
- }
-
- function drawScales(ctx, high, low, vol)
- {
- ctx.save();
- ctx.strokeStyle = "#888888";
- ctx.font = "10px Open Sans"
-
- ctx.beginPath();
-
- // prices on y-axis
- var x = canvas.width - tickMargin + 3;
- var priceStep = (high - low) / 9.0;
- for (var i = 0; i < 10; i += 2) {
- var price = parseFloat(high - i * priceStep).toFixed(1);
- ctx.text(price, x, canvas.yGridOffset + i * yGridStep - 2);
- }
-
- // volume scale
- for (i = 0; i < 3; i++) {
- var volume = volumeToString(vol - (i * (vol/3)));
- ctx.text(volume, x, canvas.yGridOffset + (i + 9) * yGridStep + 10);
- }
-
- ctx.closePath();
- ctx.stroke();
- ctx.restore();
- }
-
- function drawPrice(ctx, from, to, color, price, points, highest, lowest)
- {
- ctx.save();
- ctx.globalAlpha = 0.7;
- ctx.strokeStyle = color;
-
- ctx.lineWidth = numPoints > 200 ? 1 : 3
-
- ctx.beginPath();
-
- var end = points.length;
-
- var range = highest - lowest;
- if (range == 0) {
- range = 1;
- }
-
- for (var i = 0; i < end; i += pixelSkip) {
- var x = points[i].x;
- var y = points[i][price];
- var h = 9 * yGridStep;
-
- y = h * (lowest - y)/range + h + yGridOffset;
-
- if (i == 0) {
- ctx.moveTo(x, y);
- } else {
- ctx.lineTo(x, y);
- }
- }
- ctx.stroke();
- ctx.restore();
- }
-
- function drawVolume(ctx, from, to, color, price, points, highest)
- {
- ctx.save();
- ctx.fillStyle = color;
- ctx.globalAlpha = 0.8;
- ctx.lineWidth = 0;
- ctx.beginPath();
-
- var end = points.length;
- var margin = 0;
-
- if (chart.activeChart === "month" || chart.activeChart === "week") {
- margin = 8;
- ctx.shadowOffsetX = 4;
- ctx.shadowBlur = 3.5;
- ctx.shadowColor = Qt.darker(color);
- }
-
- // To match the volume graph with price grid, skip drawing the initial
- // volume of the first day on chart.
- for (var i = 1; i < end; i += pixelSkip) {
- var x = points[i - 1].x;
- var y = points[i][price];
- y = canvas.height * (y / highest);
- y = 3 * y / 12;
- ctx.fillRect(x, canvas.height - y + yGridOffset,
- canvas.xGridStep - margin, y);
- }
-
- ctx.stroke();
- ctx.restore();
- }
-
- function drawError(ctx, msg)
- {
- ctx.save();
- ctx.strokeStyle = "#888888";
- ctx.font = "24px Open Sans"
- ctx.textAlign = "center"
- ctx.shadowOffsetX = 4;
- ctx.shadowOffsetY = 4;
- ctx.shadowBlur = 1.5;
- ctx.shadowColor = "#aaaaaa";
- ctx.beginPath();
-
- ctx.fillText(msg, (canvas.width - tickMargin) / 2,
- (canvas.height - yGridOffset - yGridStep) / 2);
-
- ctx.closePath();
- ctx.stroke();
- ctx.restore();
- }
-
- onPaint: {
- numPoints = stockModel.indexOf(chart.startDate);
- if (chart.gridSize == 0)
- chart.gridSize = numPoints
-
- var ctx = canvas.getContext("2d");
- ctx.globalCompositeOperation = "source-over";
- ctx.lineWidth = 1;
-
- drawBackground(ctx);
-
- if (!stockModel.ready) {
- drawError(ctx, "No data available.");
- return;
- }
-
- var highestPrice = 0;
- var highestVolume = 0;
- var lowestPrice = -1;
- var points = [];
- for (var i = numPoints, j = 0; i >= 0 ; i -= pixelSkip, j += pixelSkip) {
- var price = stockModel.get(i);
- if (parseFloat(highestPrice) < parseFloat(price.high))
- highestPrice = price.high;
- if (parseInt(highestVolume, 10) < parseInt(price.volume, 10))
- highestVolume = price.volume;
- if (lowestPrice < 0 || parseFloat(lowestPrice) > parseFloat(price.low))
- lowestPrice = price.low;
- points.push({
- x: j * xGridStep,
- open: price.open,
- close: price.close,
- high: price.high,
- low: price.low,
- volume: price.volume
- });
- }
-
- if (settings.drawHighPrice)
- drawPrice(ctx, 0, numPoints, settings.highColor, "high", points, highestPrice, lowestPrice);
- if (settings.drawLowPrice)
- drawPrice(ctx, 0, numPoints, settings.lowColor, "low", points, highestPrice, lowestPrice);
- if (settings.drawOpenPrice)
- drawPrice(ctx, 0, numPoints,settings.openColor, "open", points, highestPrice, lowestPrice);
- if (settings.drawClosePrice)
- drawPrice(ctx, 0, numPoints, settings.closeColor, "close", points, highestPrice, lowestPrice);
-
- drawVolume(ctx, 0, numPoints, settings.volumeColor, "volume", points, highestVolume);
- drawScales(ctx, highestPrice, lowestPrice, highestVolume);
- }
- }
-
-
- Text {
- id: fromDate
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 8
- Layout.alignment: Qt.AlignLeft
- text: "| " + startDate.toDateString()
- }
- Text {
- id: toDate
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 8
- Layout.alignment: Qt.AlignRight
- Layout.rightMargin: canvas.tickMargin
- Layout.columnSpan: 5
- text: endDate.toDateString() + " |"
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/StockInfo.qml b/examples/quick/demos/stocqt/content/StockInfo.qml
deleted file mode 100644
index e18f34e83c..0000000000
--- a/examples/quick/demos/stocqt/content/StockInfo.qml
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Layouts 1.1
-import "."
-
-Rectangle {
- id: root
- color: "transparent"
-
- property var stock: null
-
- GridLayout {
- id: stockInfoLayout
- anchors.fill: parent
- columns: 2
- rows: 3
- rowSpacing: 4
-
- Text {
- id: stockIdText
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 28
- font.weight: Font.DemiBold
- text: root.stock.stockId
- Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
- Layout.leftMargin: 10
- }
-
- Text {
- id: price
- color: "#6d6d6d"
- font.family: Settings.fontFamily
- font.pointSize: 28
- font.weight: Font.DemiBold
- text: parseFloat(root.stock.stockPrice).toFixed(2);
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
- Layout.leftMargin: 5
- }
-
- Text {
- id: stockNameText
- color: "#0c0c0c"
- font.family: Settings.fontFamily
- font.pointSize: 16
- elide: Text.ElideRight
- maximumLineCount: 3
- wrapMode: Text.WordWrap
- text: root.stock.stockName
- Layout.leftMargin: 10
- Layout.columnSpan: 2
- Layout.alignment: Qt.AlignLeft
- }
-
-
- Text {
- id: priceChange
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- Layout.leftMargin: 10
- color: root.stock.stockPriceChanged < 0 ? "#d40000" : "#328930"
- font.family: Settings.fontFamily
- font.pointSize: 18
- text: parseFloat(root.stock.stockPriceChanged).toFixed(2);
- }
-
- Text {
- id: priceChangePercentage
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- color: root.stock.stockPriceChanged < 0 ? "#d40000" : "#328930"
- font.family: Settings.fontFamily
- font.pointSize: 18
- font.weight: Font.DemiBold
- Layout.fillWidth: true
- text: "(" +
- parseFloat(root.stock.stockPriceChanged /
- (root.stock.stockPrice - root.stock.stockPriceChanged) * 100.0).toFixed(2) +
- "%)"
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/StockListDelegate.qml b/examples/quick/demos/stocqt/content/StockListDelegate.qml
deleted file mode 100644
index 8a4a8f6922..0000000000
--- a/examples/quick/demos/stocqt/content/StockListDelegate.qml
+++ /dev/null
@@ -1,163 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.5
-import QtQuick.Layouts 1.1
-import "."
-
-Rectangle {
- height: 102
- width: parent.width
- color: "transparent"
- MouseArea {
- anchors.fill: parent;
- onClicked: {
- if (view.currentIndex == index)
- mainRect.currentIndex = 1;
- else
- view.currentIndex = index;
- }
- }
- GridLayout {
- id: stockGrid
- columns: 3
- rows: 2
- anchors.fill: parent
-
- Text {
- id: stockIdText
- Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
- Layout.leftMargin: 10
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 20
- font.weight: Font.Bold
- verticalAlignment: Text.AlignVCenter
- text: stockId
- }
-
- Text {
- id: stockValueText
- Layout.preferredWidth: 100
- Layout.alignment: Qt.AlignRight | Qt.AlignBottom
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 20
- font.bold: true
- horizontalAlignment: Text.AlignRight
- verticalAlignment: Text.AlignVCenter
- text: value
- }
- Text {
- id: stockValueChangeText
- Layout.preferredWidth: 135
- Layout.rightMargin: 10
- Layout.alignment: Qt.AlignRight | Qt.AlignBottom
- color: "#328930"
- font.family: Settings.fontFamily
- font.pointSize: 20
- font.bold: true
- horizontalAlignment: Text.AlignRight
- verticalAlignment: Text.AlignVCenter
- text: change
- onTextChanged: {
- if (parseFloat(text) >= 0.0)
- color = "#328930";
- else
- color = "#d40000";
- }
- }
- Text {
- id: stockNameText
- Layout.preferredWidth: 300
- Layout.leftMargin: 10
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 16
- font.bold: false
- elide: Text.ElideRight
- maximumLineCount: 1
- verticalAlignment: Text.AlignVCenter
- text: name
- }
-
- Item {Layout.fillWidth: true }
-
- Text {
- id: stockValueChangePercentageText
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignRight | Qt.AlignTop
- Layout.rightMargin: 10
- color: "#328930"
- font.family: Settings.fontFamily
- font.pointSize: 18
- font.bold: false
- horizontalAlignment: Text.AlignRight
- verticalAlignment: Text.AlignVCenter
- text: changePercentage
- onTextChanged: {
- if (parseFloat(text) >= 0.0)
- color = "#328930";
- else
- color = "#d40000";
- }
- }
- }
-
- Rectangle {
- id: endingLine
- anchors.top: stockGrid.bottom
- height: 1
- width: parent.width
- color: "#d7d7d7"
- }
-}
-
diff --git a/examples/quick/demos/stocqt/content/StockListModel.qml b/examples/quick/demos/stocqt/content/StockListModel.qml
deleted file mode 100644
index 2f697f5644..0000000000
--- a/examples/quick/demos/stocqt/content/StockListModel.qml
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-import QtQuick 2.0
-
-ListModel {
- id: stocks
-
- // pre-fetch data for all entries
- Component.onCompleted: {
- for (var idx = 0; idx < count; ++idx) {
- getCloseValue(idx)
- }
- }
-
- function getCloseValue(index) {
-
- var endDate = new Date(); // today
- var startDate = new Date();
- endDate.setDate(startDate.getDate() - 1);
- startDate.setDate(endDate.getDate() - 7);
-
- var req = "data/" + get(index).stockId + ".csv"
-
- var xhr = new XMLHttpRequest;
-
- xhr.open("GET", req, true);
-
- xhr.onreadystatechange = function() {
- if (xhr.readyState === XMLHttpRequest.LOADING || xhr.readyState === XMLHttpRequest.DONE) {
- var records = xhr.responseText.split('\n');
- var unknown = "n/a";
- set(index, {"value": unknown, "change": unknown, "changePercentage": unknown});
- if (records.length > 0 && xhr.status == 200) {
- var r = records[1].split(',');
- var today = parseFloat(r[4]);
-
- if (!isNaN(today))
- setProperty(index, "value", today.toFixed(2));
- if (records.length > 2) {
- r = records[2].split(',');
- var yesterday = parseFloat(r[4]);
- var change = today - yesterday;
-
- if (change >= 0.0)
- setProperty(index, "change", "+" + change.toFixed(2));
- else
- setProperty(index, "change", change.toFixed(2));
-
- var changePercentage = (change / yesterday) * 100.0;
- if (changePercentage >= 0.0)
- setProperty(index, "changePercentage", "+" + changePercentage.toFixed(2) + "%");
- else
- setProperty(index, "changePercentage", changePercentage.toFixed(2) + "%");
- }
- }
- }
- }
- xhr.send()
- }
- // Uncomment to test invalid entries
- // ListElement {name: "The Qt Company"; stockId: "TQTC"; value: "999.0"; change: "0.0"; changePercentage: "0.0"}
-
- // Offline data downloaded using the url, https://www.quandl.com/api/v3/datasets/WIKI/<stockId>.csv.
- ListElement {name: "Advanced Micro Devices Inc."; stockId: "AMD"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Amazon.com Inc."; stockId: "AMZN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Apple Inc."; stockId: "AAPL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Autodesk Inc."; stockId: "ADSK"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Cisco Systems Inc."; stockId: "CSCO"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "eBay Inc."; stockId: "EBAY"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Electronic Arts Inc."; stockId: "EA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Intel Corp."; stockId: "INTC"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Microsoft Corp."; stockId: "MSFT"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "NetApp Inc."; stockId: "NTAP"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Netflix Inc."; stockId: "NFLX"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Norwegian Cruise Line Holdings Ltd."; stockId: "NCLH"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "NVIDIA Corp."; stockId: "NVDA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "PayPal Holdings Inc."; stockId: "PYPL"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "QUALCOMM Inc."; stockId: "QCOM"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Tesla Motors Inc."; stockId: "TSLA"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Texas Instruments Inc."; stockId: "TXN"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
- ListElement {name: "Facebook Inc."; stockId: "FB"; value: "0.0"; change: "0.0"; changePercentage: "0.0"}
-}
-
diff --git a/examples/quick/demos/stocqt/content/StockListView.qml b/examples/quick/demos/stocqt/content/StockListView.qml
deleted file mode 100644
index e30355c675..0000000000
--- a/examples/quick/demos/stocqt/content/StockListView.qml
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "."
-
-Rectangle {
- id: root
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- color: "white"
-
- property string currentStockId: ""
- property string currentStockName: ""
-
- ListView {
- id: view
- anchors.fill: parent
- clip: true
- keyNavigationWraps: true
- highlightMoveDuration: 0
- focus: true
- snapMode: ListView.SnapToItem
- model: StockListModel {}
- currentIndex: -1 // Don't pre-select any item
-
- onCurrentIndexChanged: {
- if (currentItem) {
- root.currentStockId = model.get(currentIndex).stockId;
- root.currentStockName = model.get(currentIndex).name;
- }
- }
-
- delegate: StockListDelegate {}
-
- highlight: Rectangle {
- width: view.width
- color: "#eeeeee"
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/StockModel.qml b/examples/quick/demos/stocqt/content/StockModel.qml
deleted file mode 100644
index 9e3a815c11..0000000000
--- a/examples/quick/demos/stocqt/content/StockModel.qml
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-ListModel {
- id: model
- property string stockId: ""
- property string stockName: ""
- property var newest
- property var oldest
- property bool ready: false
- property real stockPrice: 0.0
- property real stockPriceChanged: 0.0
-
- signal dataReady
-
- function indexOf(date) {
- if (model.count == 0)
- return -1;
-
- if (newest <= date)
- date = new Date(newest.getYear(),
- newest.getMonth(),
- newest.getDate() - 7);
-
- if (oldest >= date)
- return model.count - 1;
-
- var currDiff = 0;
- var bestDiff = Math.abs(date.getTime() - newest.getTime());
- var retval = 0;
- for (var i = 0; i < model.count; i++) {
- var d = new Date(model.get(i).date);
- currDiff = Math.abs(d.getTime() - date.getTime());
- if (currDiff < bestDiff) {
- bestDiff = currDiff;
- retval = i + 1;
- }
- if (currDiff > bestDiff)
- return retval;
- }
- return -1;
- }
-
- function createStockPrice(r) {
- return {
- "date": r[0],
- "open":r[1],
- "high":r[2],
- "low":r[3],
- "close":r[4],
- "volume":r[5],
- };
- }
-
- function updateStock() {
- if (stockId === "")
- return;
-
- var startDate = new Date(2011, 4, 25);
- var endDate = new Date(); //today
-
- var req = "data/" + stockId + ".csv"
- if (!req)
- return;
-
- var xhr = new XMLHttpRequest;
-
- xhr.open("GET", req, true);
-
- model.ready = false;
- model.clear();
- var i = 1; //skip the first line
- xhr.onreadystatechange = function() {
- if (xhr.readyState === XMLHttpRequest.LOADING || xhr.readyState === XMLHttpRequest.DONE) {
- var records = xhr.responseText.split('\n');
- for (;i < records.length; i++ ) {
- var r = records[i].split(',');
- if (r.length >= 6)
- model.append(createStockPrice(r));
- }
-
- if (xhr.readyState === XMLHttpRequest.DONE) {
- if (model.count > 0) {
- model.ready = true;
- model.stockPrice = model.get(0).close;
- model.stockPriceChanged = model.count > 1 ? (Math.round((model.stockPrice - model.get(1).close) * 100) / 100) : 0;
- newest = new Date(model.get(0).date);
- oldest = new Date(model.get(model.count - 1).date);
- } else {
- model.stockPrice = 0;
- model.stockPriceChanged = 0;
- }
- model.dataReady(); // emit signal - model.ready indicates whether the data is valid
- }
- }
- }
- xhr.send()
- }
-}
diff --git a/examples/quick/demos/stocqt/content/StockSettingsPanel.qml b/examples/quick/demos/stocqt/content/StockSettingsPanel.qml
deleted file mode 100644
index 48a77d8495..0000000000
--- a/examples/quick/demos/stocqt/content/StockSettingsPanel.qml
+++ /dev/null
@@ -1,163 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Layouts 1.1
-import "."
-
-Rectangle {
- id: root
- color: "transparent"
-
- property bool drawOpenPrice: false
- property bool drawClosePrice: false
- property bool drawHighPrice: true
- property bool drawLowPrice: true
-
- property string openColor: "#face20"
- property string closeColor: "#14aaff"
- property string highColor: "#80c342"
- property string lowColor: "#f30000"
- property string volumeColor: "#14aaff"
-
- GridLayout {
- id: settingsGrid
- rows: 5
- columns: 3
- rowSpacing: 4
- anchors.fill: parent
-
- Item {
- Layout.fillHeight: true
- Layout.columnSpan: 3
- }
-
- Text {
- id: openText
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 19
- text: "Open"
- Layout.leftMargin: 10
- }
- Rectangle {
- Layout.preferredHeight: 4
- Layout.preferredWidth: 114
- color: openColor
- }
- CheckBox {
- id: openButton
- buttonEnabled: false
- onButtonEnabledChanged: drawOpenPrice = buttonEnabled
- Layout.rightMargin: 10
- }
-
- Text {
- id: closeText
- Layout.leftMargin: 10
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 19
- text: "Close"
- }
- Rectangle {
- Layout.preferredHeight: 4
- Layout.preferredWidth: 114
- color: closeColor
- }
- CheckBox {
- id: closeButton
- buttonEnabled: false
- onButtonEnabledChanged: drawClosePrice = buttonEnabled
- Layout.rightMargin: 10
- }
-
- Text {
- id: highText
- Layout.leftMargin: 10
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 19
- text: "High"
- }
- Rectangle {
- Layout.preferredHeight: 4
- Layout.preferredWidth: 114
- color: highColor
- }
- CheckBox {
- id: highButton
- buttonEnabled: true
- onButtonEnabledChanged: drawHighPrice = buttonEnabled
- Layout.rightMargin: 10
- }
-
- Text {
- id: lowText
- Layout.leftMargin: 10
- color: "#000000"
- font.family: Settings.fontFamily
- font.pointSize: 19
- text: "Low"
- }
- Rectangle {
- Layout.preferredHeight: 4
- Layout.preferredWidth: 114
- color: lowColor
- }
-
- CheckBox {
- id: lowButton
- buttonEnabled: true
- onButtonEnabledChanged: drawLowPrice = buttonEnabled
- Layout.rightMargin: 10
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/StockView.qml b/examples/quick/demos/stocqt/content/StockView.qml
deleted file mode 100644
index f966f06b18..0000000000
--- a/examples/quick/demos/stocqt/content/StockView.qml
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QtQuick.Window 2.1
-import QtQuick.Layouts 1.1
-
-Rectangle {
- id: root
- width: 320
- height: 480
- color: "transparent"
-
- property var stock: null
- property var stocklist: null
- signal settingsClicked
-
- function update() {
- chart.update()
- }
-
- Rectangle {
- id: mainRect
- color: "transparent"
- anchors.fill: parent
-
- GridLayout {
- anchors.fill: parent
- rows: 2
- columns: Screen.primaryOrientation === Qt.PortraitOrientation ? 1 : 2
-
- StockInfo {
- id: stockInfo
- Layout.alignment: Qt.AlignTop
- Layout.preferredWidth: 400
- Layout.preferredHeight: 160
- stock: root.stock
- }
-
- StockChart {
- id: chart
- Layout.alignment: Qt.AlignRight
- Layout.margins: 5
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.rowSpan: 2
- stockModel: root.stock
- settings: settingsPanel
- }
- StockSettingsPanel {
- id: settingsPanel
- Layout.alignment: Qt.AlignBottom
- Layout.fillHeight: true
- Layout.preferredWidth: 400
- Layout.bottomMargin: 5
- onDrawOpenPriceChanged: root.update()
- onDrawClosePriceChanged: root.update();
- onDrawHighPriceChanged: root.update();
- onDrawLowPriceChanged: root.update();
- }
- }
- }
-}
diff --git a/examples/quick/demos/stocqt/content/data/AAPL.csv b/examples/quick/demos/stocqt/content/data/AAPL.csv
deleted file mode 100644
index de56baa19a..0000000000
--- a/examples/quick/demos/stocqt/content/data/AAPL.csv
+++ /dev/null
@@ -1,147 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,170.52,170.59,169.22,169.23,25643711.0,0.0,1.0,170.52,170.59,169.22,169.23,25643711.0
-2017-12-28,171.0,171.85,170.48,171.08,15997739.0,0.0,1.0,171.0,171.85,170.48,171.08,15997739.0
-2017-12-27,170.1,170.78,169.71,170.6,21672062.0,0.0,1.0,170.1,170.78,169.71,170.6,21672062.0
-2017-12-26,170.8,171.47,169.679,170.57,32968167.0,0.0,1.0,170.8,171.47,169.679,170.57,32968167.0
-2017-12-22,174.68,175.424,174.5,175.01,16052615.0,0.0,1.0,174.68,175.424,174.5,175.01,16052615.0
-2017-12-21,174.17,176.02,174.1,175.01,20356826.0,0.0,1.0,174.17,176.02,174.1,175.01,20356826.0
-2017-12-20,174.87,175.42,173.25,174.35,23000392.0,0.0,1.0,174.87,175.42,173.25,174.35,23000392.0
-2017-12-19,175.03,175.39,174.09,174.54,27078872.0,0.0,1.0,175.03,175.39,174.09,174.54,27078872.0
-2017-12-18,174.88,177.2,174.86,176.42,28831533.0,0.0,1.0,174.88,177.2,174.86,176.42,28831533.0
-2017-12-15,173.63,174.17,172.46,173.87,37054632.0,0.0,1.0,173.63,174.17,172.46,173.87,37054632.0
-2017-12-14,172.4,173.13,171.65,172.22,20219307.0,0.0,1.0,172.4,173.13,171.65,172.22,20219307.0
-2017-12-13,172.5,173.54,172.0,172.27,23142242.0,0.0,1.0,172.5,173.54,172.0,172.27,23142242.0
-2017-12-12,172.15,172.39,171.461,171.7,18945457.0,0.0,1.0,172.15,172.39,171.461,171.7,18945457.0
-2017-12-11,169.2,172.89,168.79,172.67,33092051.0,0.0,1.0,169.2,172.89,168.79,172.67,33092051.0
-2017-12-08,170.49,171.0,168.82,169.37,23096872.0,0.0,1.0,170.49,171.0,168.82,169.37,23096872.0
-2017-12-07,169.03,170.44,168.91,169.452,24469613.0,0.0,1.0,169.03,170.44,168.91,169.452,24469613.0
-2017-12-06,167.5,170.2047,166.46,169.01,28224357.0,0.0,1.0,167.5,170.2047,166.46,169.01,28224357.0
-2017-12-05,169.06,171.52,168.4,169.64,27008428.0,0.0,1.0,169.06,171.52,168.4,169.64,27008428.0
-2017-12-04,172.48,172.62,169.63,169.8,32115052.0,0.0,1.0,172.48,172.62,169.63,169.8,32115052.0
-2017-12-01,169.95,171.67,168.5,171.05,39590080.0,0.0,1.0,169.95,171.67,168.5,171.05,39590080.0
-2017-11-30,170.43,172.14,168.44,171.85,40172368.0,0.0,1.0,170.43,172.14,168.44,171.85,40172368.0
-2017-11-29,172.63,172.92,167.16,169.48,40788324.0,0.0,1.0,172.63,172.92,167.16,169.48,40788324.0
-2017-11-28,174.3,174.87,171.86,173.07,25468442.0,0.0,1.0,174.3,174.87,171.86,173.07,25468442.0
-2017-11-27,175.05,175.08,173.34,174.09,20536313.0,0.0,1.0,175.05,175.08,173.34,174.09,20536313.0
-2017-11-24,175.1,175.5,174.6459,174.97,14026519.0,0.0,1.0,175.1,175.5,174.6459,174.97,14026519.0
-2017-11-22,173.36,175.0,173.05,174.96,24997274.0,0.0,1.0,173.36,175.0,173.05,174.96,24997274.0
-2017-11-21,170.78,173.7,170.78,173.14,24875471.0,0.0,1.0,170.78,173.7,170.78,173.14,24875471.0
-2017-11-20,170.29,170.56,169.56,169.98,15974387.0,0.0,1.0,170.29,170.56,169.56,169.98,15974387.0
-2017-11-17,171.04,171.39,169.64,170.15,21665811.0,0.0,1.0,171.04,171.39,169.64,170.15,21665811.0
-2017-11-16,171.18,171.87,170.3,171.1,23497326.0,0.0,1.0,171.18,171.87,170.3,171.1,23497326.0
-2017-11-15,169.97,170.3197,168.38,169.08,28702351.0,0.0,1.0,169.97,170.3197,168.38,169.08,28702351.0
-2017-11-14,173.04,173.48,171.18,171.34,23588451.0,0.0,1.0,173.04,173.48,171.18,171.34,23588451.0
-2017-11-13,173.5,174.5,173.4,173.97,16828025.0,0.0,1.0,173.5,174.5,173.4,173.97,16828025.0
-2017-11-10,175.11,175.38,174.27,174.67,25061183.0,0.0,1.0,175.11,175.38,174.27,174.67,25061183.0
-2017-11-09,175.11,176.095,173.14,175.88,28636531.0,0.0,1.0,175.11,176.095,173.14,175.88,28636531.0
-2017-11-07,173.91,175.25,173.6,174.81,23910914.0,0.0,1.0,173.91,175.25,173.6,174.81,23910914.0
-2017-11-06,172.365,174.99,171.72,174.25,34242566.0,0.0,1.0,172.365,174.99,171.72,174.25,34242566.0
-2017-11-03,174.0,174.26,171.12,172.5,58683826.0,0.0,1.0,174.0,174.26,171.12,172.5,58683826.0
-2017-11-02,167.64,168.5,165.28,168.11,32710040.0,0.0,1.0,167.64,168.5,165.28,168.11,32710040.0
-2017-11-01,169.87,169.94,165.61,166.89,33100847.0,0.0,1.0,169.87,169.94,165.61,166.89,33100847.0
-2017-10-31,167.9,169.6499,166.94,169.04,35474672.0,0.0,1.0,167.9,169.6499,166.94,169.04,35474672.0
-2017-10-30,163.89,168.07,163.72,166.72,43923292.0,0.0,1.0,163.89,168.07,163.72,166.72,43923292.0
-2017-10-27,159.29,163.6,158.7,163.05,43904150.0,0.0,1.0,159.29,163.6,158.7,163.05,43904150.0
-2017-10-26,157.23,157.8295,156.78,157.41,16751691.0,0.0,1.0,157.23,157.8295,156.78,157.41,16751691.0
-2017-10-25,156.91,157.55,155.27,156.405,20126554.0,0.0,1.0,156.91,157.55,155.27,156.405,20126554.0
-2017-10-24,156.29,157.42,156.2,157.1,17137731.0,0.0,1.0,156.29,157.42,156.2,157.1,17137731.0
-2017-10-23,156.89,157.69,155.5,156.17,21654461.0,0.0,1.0,156.89,157.69,155.5,156.17,21654461.0
-2017-10-20,156.61,157.75,155.96,156.16,23612246.0,0.0,1.0,156.61,157.75,155.96,156.16,23612246.0
-2017-10-19,156.75,157.08,155.02,155.98,42111326.0,0.0,1.0,156.75,157.08,155.02,155.98,42111326.0
-2017-10-18,160.42,160.71,159.6,159.76,16158659.0,0.0,1.0,160.42,160.71,159.6,159.76,16158659.0
-2017-10-17,159.78,160.87,159.23,160.47,18816438.0,0.0,1.0,159.78,160.87,159.23,160.47,18816438.0
-2017-10-16,157.9,160.0,157.65,159.88,23894630.0,0.0,1.0,157.9,160.0,157.65,159.88,23894630.0
-2017-10-13,156.73,157.28,156.41,156.99,16287608.0,0.0,1.0,156.73,157.28,156.41,156.99,16287608.0
-2017-10-12,156.35,157.37,155.7299,156.0,16045720.0,0.0,1.0,156.35,157.37,155.7299,156.0,16045720.0
-2017-10-11,155.97,156.98,155.75,156.55,16607693.0,0.0,1.0,155.97,156.98,155.75,156.55,16607693.0
-2017-10-10,156.055,158.0,155.1,155.9,15456331.0,0.0,1.0,156.055,158.0,155.1,155.9,15456331.0
-2017-10-09,155.81,156.73,155.485,155.84,16200129.0,0.0,1.0,155.81,156.73,155.485,155.84,16200129.0
-2017-10-06,154.97,155.49,154.56,155.3,16423749.0,0.0,1.0,154.97,155.49,154.56,155.3,16423749.0
-2017-10-05,154.18,155.44,154.05,155.39,21032800.0,0.0,1.0,154.18,155.44,154.05,155.39,21032800.0
-2017-10-04,153.63,153.86,152.46,153.4508,19844177.0,0.0,1.0,153.63,153.86,152.46,153.4508,19844177.0
-2017-10-03,154.01,155.09,153.91,154.48,16146388.0,0.0,1.0,154.01,155.09,153.91,154.48,16146388.0
-2017-10-02,154.26,154.45,152.72,153.81,18524860.0,0.0,1.0,154.26,154.45,152.72,153.81,18524860.0
-2017-09-29,153.21,154.13,152.0,154.12,25856530.0,0.0,1.0,153.21,154.13,152.0,154.12,25856530.0
-2017-09-28,153.89,154.28,152.7,153.28,21896592.0,0.0,1.0,153.89,154.28,152.7,153.28,21896592.0
-2017-09-27,153.8,154.7189,153.54,154.23,24959552.0,0.0,1.0,153.8,154.7189,153.54,154.23,24959552.0
-2017-09-26,151.78,153.92,151.69,153.14,35470985.0,0.0,1.0,151.78,153.92,151.69,153.14,35470985.0
-2017-09-25,149.99,151.83,149.16,150.55,43922334.0,0.0,1.0,149.99,151.83,149.16,150.55,43922334.0
-2017-09-22,152.02,152.27,150.56,151.89,46114424.0,0.0,1.0,152.02,152.27,150.56,151.89,46114424.0
-2017-09-21,155.8,155.8,152.75,153.39,36643382.0,0.0,1.0,155.8,155.8,152.75,153.39,36643382.0
-2017-09-20,157.9,158.26,153.83,156.07,51693239.0,0.0,1.0,157.9,158.26,153.83,156.07,51693239.0
-2017-09-19,159.51,159.77,158.44,158.73,20347352.0,0.0,1.0,159.51,159.77,158.44,158.73,20347352.0
-2017-09-18,160.11,160.5,157.995,158.67,27939718.0,0.0,1.0,160.11,160.5,157.995,158.67,27939718.0
-2017-09-15,158.47,160.97,158.0,159.88,48203642.0,0.0,1.0,158.47,160.97,158.0,159.88,48203642.0
-2017-09-14,158.99,159.4,158.09,158.28,23073646.0,0.0,1.0,158.99,159.4,158.09,158.28,23073646.0
-2017-09-13,159.87,159.96,157.91,159.65,44393752.0,0.0,1.0,159.87,159.96,157.91,159.65,44393752.0
-2017-09-12,162.61,163.96,158.77,160.82,71139119.0,0.0,1.0,162.61,163.96,158.77,160.82,71139119.0
-2017-09-11,160.5,162.05,159.89,161.5,31028926.0,0.0,1.0,160.5,162.05,159.89,161.5,31028926.0
-2017-09-08,160.86,161.15,158.53,158.63,28183159.0,0.0,1.0,160.86,161.15,158.53,158.63,28183159.0
-2017-09-07,162.09,162.24,160.36,161.26,21722995.0,0.0,1.0,162.09,162.24,160.36,161.26,21722995.0
-2017-09-06,162.71,162.99,160.52,161.91,21179047.0,0.0,1.0,162.71,162.99,160.52,161.91,21179047.0
-2017-09-05,163.75,164.25,160.56,162.08,29317054.0,0.0,1.0,163.75,164.25,160.56,162.08,29317054.0
-2017-09-01,164.8,164.94,163.63,164.05,16508568.0,0.0,1.0,164.8,164.94,163.63,164.05,16508568.0
-2017-08-31,163.64,164.52,163.48,164.0,26412439.0,0.0,1.0,163.64,164.52,163.48,164.0,26412439.0
-2017-08-30,163.8,163.89,162.61,163.35,26973946.0,0.0,1.0,163.8,163.89,162.61,163.35,26973946.0
-2017-08-29,160.1,163.12,160.0,162.91,29307862.0,0.0,1.0,160.1,163.12,160.0,162.91,29307862.0
-2017-08-28,160.14,162.0,159.93,161.47,25279674.0,0.0,1.0,160.14,162.0,159.93,161.47,25279674.0
-2017-08-25,159.65,160.56,159.27,159.86,25015218.0,0.0,1.0,159.65,160.56,159.27,159.86,25015218.0
-2017-08-24,160.43,160.74,158.55,159.27,19029621.0,0.0,1.0,160.43,160.74,158.55,159.27,19029621.0
-2017-08-23,159.07,160.47,158.88,159.98,19198189.0,0.0,1.0,159.07,160.47,158.88,159.98,19198189.0
-2017-08-22,158.23,160.0,158.02,159.78,21297812.0,0.0,1.0,158.23,160.0,158.02,159.78,21297812.0
-2017-08-21,157.5,157.89,155.1101,157.21,26145653.0,0.0,1.0,157.5,157.89,155.1101,157.21,26145653.0
-2017-08-18,157.86,159.5,156.72,157.5,27012525.0,0.0,1.0,157.86,159.5,156.72,157.5,27012525.0
-2017-08-17,160.52,160.71,157.84,157.87,26925694.0,0.0,1.0,160.52,160.71,157.84,157.87,26925694.0
-2017-08-16,161.94,162.51,160.15,160.95,27321761.0,0.0,1.0,161.94,162.51,160.15,160.95,27321761.0
-2017-08-15,160.66,162.195,160.14,161.6,27936774.0,0.0,1.0,160.66,162.195,160.14,161.6,27936774.0
-2017-08-14,159.32,160.21,158.75,159.85,21754810.0,0.0,1.0,159.32,160.21,158.75,159.85,21754810.0
-2017-08-11,156.6,158.5728,156.07,157.48,25943187.0,0.0,1.0,156.6,158.5728,156.07,157.48,25943187.0
-2017-08-10,159.9,160.0,154.63,155.27,39081017.0,0.63,1.0,159.9,160.0,154.63,155.27,39081017.0
-2017-08-09,159.26,161.27,159.11,161.06,25640394.0,0.0,1.0,158.61642206543,160.61829955099,158.46702822322,160.40914817191,25640394.0
-2017-08-08,158.6,161.83,158.27,160.08,35775675.0,0.0,1.0,157.95908915972,161.1760365619,157.63042270686,159.43310840282,35775675.0
-2017-08-04,156.07,157.4,155.69,156.39,20349532.0,0.0,1.0,155.43931302117,156.76393842207,155.06084862091,155.75801988454,20349532.0
-2017-08-03,157.05,157.21,155.02,155.57,26000738.0,0.0,1.0,156.41535279025,156.57470622194,154.39355612572,154.94133354715,26000738.0
-2017-08-02,159.28,159.75,156.16,157.14,69222793.0,0.0,1.0,158.63634124439,159.10444194997,155.52894932649,156.50498909557,69222793.0
-2017-08-01,149.1,150.22,148.41,150.05,24725526.0,0.0,1.0,148.4974791533,149.61295317511,147.81026747915,149.44364015394,24725526.0
-2017-07-31,149.9,150.33,148.13,148.85,19422655.0,0.0,1.0,149.29424631174,149.7225086594,147.5313989737,148.24848941629,19422655.0
-2017-07-28,149.89,150.23,149.19,149.5,16832947.0,0.0,1.0,149.28428672226,149.62291276459,148.58711545863,148.89586273252,16832947.0
-2017-07-27,153.75,153.99,147.3,150.56,32175875.0,0.0,1.0,153.12868826171,153.36771840924,146.70475304682,149.95157921745,32175875.0
-2017-07-26,153.35,153.93,153.06,153.46,15172136.0,0.0,1.0,152.73030468249,153.30796087235,152.44147658756,152.83986016677,15172136.0
-2017-07-25,151.8,153.84,151.8,152.74,18612649.0,0.0,1.0,151.18656831302,153.21832456703,151.18656831302,152.12276972418,18612649.0
-2017-07-24,150.58,152.44,149.9,152.09,21122730.0,0.0,1.0,149.97149839641,151.82398203977,149.29424631174,151.47539640795,21122730.0
-2017-07-21,149.99,150.44,148.88,150.27,24671002.0,0.0,1.0,149.38388261706,149.83206414368,148.27836818473,149.66275112251,24671002.0
-2017-07-20,151.5,151.74,150.19,150.34,17053326.0,0.0,1.0,150.88778062861,151.12681077614,149.58307440667,149.73246824888,17053326.0
-2017-07-19,150.48,151.42,149.95,151.02,20615419.0,0.0,1.0,149.8719025016,150.80810391276,149.34404425914,150.40972033355,20615419.0
-2017-07-18,149.2,150.13,148.67,150.08,17713795.0,0.0,1.0,148.59707504811,149.52331686979,148.06921680564,149.47351892239,17713795.0
-2017-07-17,148.82,150.9,148.57,149.56,23243713.0,0.0,1.0,148.21861064785,150.29020525978,147.96962091084,148.9556202694,23243713.0
-2017-07-14,147.97,149.33,147.33,149.04,19961788.0,0.0,1.0,147.37204554201,148.72654971135,146.73463181527,148.43772161642,19961788.0
-2017-07-13,145.5,148.49,145.44,147.77,24922788.0,0.0,1.0,144.91202694035,147.889944195,144.85226940346,147.17285375241,24922788.0
-2017-07-12,145.87,146.18,144.82,145.74,23617964.0,0.0,1.0,145.28053175112,145.58927902502,144.23477485568,145.15105708788,23617964.0
-2017-07-11,144.73,145.85,144.38,145.53,18311156.0,0.0,1.0,144.14513855035,145.26061257216,143.79655291854,144.94190570879,18311156.0
-2017-07-10,144.11,145.95,143.37,145.06,21030466.0,0.0,1.0,143.52764400257,145.36020846697,142.79063438101,144.47380500321,21030466.0
-2017-07-07,142.9,144.75,142.9,144.18,18505351.0,0.0,1.0,142.32253367543,144.16505772931,142.32253367543,143.59736112893,18505351.0
-2017-07-06,143.02,143.5,142.41,142.73,23374374.0,0.0,1.0,142.4420487492,142.92010904426,141.83451379089,142.15322065427,23374374.0
-2017-07-05,143.69,144.79,142.7237,144.09,20758795.0,0.0,1.0,143.10934124439,144.20489608724,142.14694611289,143.5077248236,20758795.0
-2017-07-03,144.88,145.3001,143.1,143.5,14276812.0,0.0,1.0,144.29453239256,144.71293474663,142.52172546504,142.92010904426,14276812.0
-2017-06-30,144.45,144.96,143.78,144.02,22328979.0,0.0,1.0,143.8662700449,144.3742091084,143.19897754971,143.43800769724,22328979.0
-2017-06-29,144.71,145.13,142.28,143.68,31116980.0,0.0,1.0,144.12521937139,144.54352212957,141.70503912765,143.09938165491,31116980.0
-2017-06-28,144.49,146.11,143.1601,145.83,21915939.0,0.0,1.0,143.90610840282,145.51956189865,142.58158259782,145.2406933932,21915939.0
-2017-06-27,145.01,146.16,143.62,143.74,24423643.0,0.0,1.0,144.4240070558,145.56935984606,143.03962411802,143.15913919179,24423643.0
-2017-06-26,147.17,148.28,145.38,145.82,25524661.0,0.0,1.0,146.57527838358,147.68079281591,144.79251186658,145.23073380372,25524661.0
-2017-06-23,145.13,147.16,145.11,146.35,25997976.0,0.0,1.0,144.54352212957,146.5653187941,144.52360295061,145.75859204618,25997976.0
-2017-06-22,145.77,146.7,145.1199,145.63,18673365.0,0.0,1.0,145.18093585632,146.107177678,144.5334629442,145.04150160359,18673365.0
-2017-06-21,145.52,146.0693,144.61,145.87,21064679.0,0.0,1.0,144.93194611931,145.47902636947,144.02562347659,145.28053175112,21064679.0
-2017-06-20,146.87,146.87,144.94,145.01,24572170.0,0.0,1.0,146.27649069917,146.27649069917,144.35428992944,144.4240070558,24572170.0
-2017-06-19,143.66,146.74,143.66,146.34,31449132.0,0.0,1.0,143.07946247595,146.14701603592,143.07946247595,145.7486324567,31449132.0
-2017-06-16,143.78,144.5,142.2,142.27,49180748.0,0.0,1.0,143.19897754971,143.9160679923,141.6253624118,141.69507953817,49180748.0
-2017-06-15,143.32,144.4798,142.21,144.29,31348832.0,0.0,1.0,142.74083643361,143.89594962155,141.63532200128,143.70691661321,31348832.0
-2017-06-14,147.5,147.5,143.84,145.16,31224203.0,0.0,1.0,146.90394483643,146.90394483643,143.25873508659,144.57340089801,31224203.0
-2017-06-13,147.16,147.45,145.15,146.59,33749154.0,0.0,1.0,146.5653187941,146.85414688903,144.56344130853,145.99762219371,33749154.0
-2017-06-12,145.74,146.09,142.51,145.32,71563614.0,0.0,1.0,145.15105708788,145.49964271969,141.9341096857,144.7327543297,71563614.0
-2017-06-09,155.19,155.19,146.02,148.98,64176149.0,0.0,1.0,154.56286914689,154.56286914689,145.42992559333,148.37796407954,64176149.0
-2017-06-08,155.25,155.54,154.4,154.99,20771367.0,0.0,1.0,154.62262668377,154.9114547787,153.77606157793,154.36367735728,20771367.0
-2017-06-07,155.02,155.98,154.48,155.37,20678772.0,0.0,1.0,154.39355612572,155.34967671584,153.85573829378,154.74214175754,20678772.0
-2017-06-06,153.9,155.81,153.78,154.45,26249630.0,0.0,1.0,153.27808210391,155.18036369468,153.15856703015,153.82585952534,26249630.0
-2017-06-05,154.34,154.45,153.46,153.93,24803858.0,0.0,1.0,153.71630404105,153.82585952534,152.83986016677,153.30796087235,24803858.0
-2017-06-02,153.58,155.45,152.89,155.45,27285861.0,0.0,1.0,152.95937524054,154.82181847338,152.27216356639,154.82181847338,27285861.0
-2017-06-01,153.17,153.33,152.22,153.18,16180143.0,0.0,1.0,152.55103207184,152.71038550353,151.6048710712,152.56099166132,16180143.0
diff --git a/examples/quick/demos/stocqt/content/data/ADSK.csv b/examples/quick/demos/stocqt/content/data/ADSK.csv
deleted file mode 100644
index 704fa3f32a..0000000000
--- a/examples/quick/demos/stocqt/content/data/ADSK.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,105.04,105.65,104.5301,104.83,1042328.0,0.0,1.0,105.04,105.65,104.5301,104.83,1042328.0
-2017-12-28,104.66,105.22,104.2,105.07,860725.0,0.0,1.0,104.66,105.22,104.2,105.07,860725.0
-2017-12-27,103.97,105.199,103.48,104.58,959904.0,0.0,1.0,103.97,105.199,103.48,104.58,959904.0
-2017-12-26,103.45,104.15,103.19,103.8,1307823.0,0.0,1.0,103.45,104.15,103.19,103.8,1307823.0
-2017-12-22,104.85,104.85,103.78,103.89,1411598.0,0.0,1.0,104.85,104.85,103.78,103.89,1411598.0
-2017-12-21,105.58,105.6699,103.65,104.43,3901415.0,0.0,1.0,105.58,105.6699,103.65,104.43,3901415.0
-2017-12-20,106.02,106.02,104.19,105.03,2502489.0,0.0,1.0,106.02,106.02,104.19,105.03,2502489.0
-2017-12-19,107.24,107.84,105.37,105.39,1807167.0,0.0,1.0,107.24,107.84,105.37,105.39,1807167.0
-2017-12-18,108.66,109.43,107.28,107.48,2305840.0,0.0,1.0,108.66,109.43,107.28,107.48,2305840.0
-2017-12-15,106.55,108.93,106.47,108.4,2434779.0,0.0,1.0,106.55,108.93,106.47,108.4,2434779.0
-2017-12-14,105.95,107.12,105.95,106.25,1479116.0,0.0,1.0,105.95,107.12,105.95,106.25,1479116.0
-2017-12-13,107.03,107.89,105.51,106.02,1924569.0,0.0,1.0,107.03,107.89,105.51,106.02,1924569.0
-2017-12-12,106.32,107.98,105.58,106.33,1987461.0,0.0,1.0,106.32,107.98,105.58,106.33,1987461.0
-2017-12-11,106.87,107.95,106.15,106.83,2270028.0,0.0,1.0,106.87,107.95,106.15,106.83,2270028.0
-2017-12-08,109.6,110.17,106.69,107.16,3094512.0,0.0,1.0,109.6,110.17,106.69,107.16,3094512.0
-2017-12-07,106.2,110.18,106.0,109.61,3028608.0,0.0,1.0,106.2,110.18,106.0,109.61,3028608.0
-2017-12-06,105.73,107.83,105.73,106.92,1678616.0,0.0,1.0,105.73,107.83,105.73,106.92,1678616.0
-2017-12-05,107.91,109.49,106.55,106.59,2983741.0,0.0,1.0,107.91,109.49,106.55,106.59,2983741.0
-2017-12-04,108.0,108.69,105.16,107.95,3940444.0,0.0,1.0,108.0,108.69,105.16,107.95,3940444.0
-2017-12-01,108.81,110.12,106.29,107.06,4905374.0,0.0,1.0,108.81,110.12,106.29,107.06,4905374.0
-2017-11-30,109.64,111.579,106.54,109.7,8408815.0,0.0,1.0,109.64,111.579,106.54,109.7,8408815.0
-2017-11-29,114.03,114.46,106.2,109.34,19333560.0,0.0,1.0,114.03,114.46,106.2,109.34,19333560.0
-2017-11-28,130.76,131.1,127.49,129.95,3683510.0,0.0,1.0,130.76,131.1,127.49,129.95,3683510.0
-2017-11-27,130.19,130.92,129.26,130.24,2248835.0,0.0,1.0,130.19,130.92,129.26,130.24,2248835.0
-2017-11-24,127.74,129.54,127.65,129.5,1013550.0,0.0,1.0,127.74,129.54,127.65,129.5,1013550.0
-2017-11-22,128.01,128.685,126.835,127.77,1467080.0,0.0,1.0,128.01,128.685,126.835,127.77,1467080.0
-2017-11-21,127.13,128.17,126.97,127.71,1567056.0,0.0,1.0,127.13,128.17,126.97,127.71,1567056.0
-2017-11-20,127.51,128.28,126.11,126.28,1711322.0,0.0,1.0,127.51,128.28,126.11,126.28,1711322.0
-2017-11-17,127.49,127.92,125.87,127.49,1458953.0,0.0,1.0,127.49,127.92,125.87,127.49,1458953.0
-2017-11-16,124.79,127.0,124.64,127.0,1525137.0,0.0,1.0,124.79,127.0,124.64,127.0,1525137.0
-2017-11-15,123.87,125.01,122.44,124.02,1439532.0,0.0,1.0,123.87,125.01,122.44,124.02,1439532.0
-2017-11-14,124.4,124.82,123.16,123.87,1221703.0,0.0,1.0,124.4,124.82,123.16,123.87,1221703.0
-2017-11-13,124.34,125.02,122.685,124.64,1132264.0,0.0,1.0,124.34,125.02,122.685,124.64,1132264.0
-2017-11-10,121.95,123.32,121.31,123.11,929375.0,0.0,1.0,121.95,123.32,121.31,123.11,929375.0
-2017-11-09,122.9,123.09,120.01,122.4,1455225.0,0.0,1.0,122.9,123.09,120.01,122.4,1455225.0
-2017-11-07,124.26,124.54,122.61,123.4,803631.0,0.0,1.0,124.26,124.54,122.61,123.4,803631.0
-2017-11-06,125.0,125.09,123.19,123.82,994672.0,0.0,1.0,125.0,125.09,123.19,123.82,994672.0
-2017-11-03,124.5,125.5,124.1101,124.85,1308745.0,0.0,1.0,124.5,125.5,124.1101,124.85,1308745.0
-2017-11-02,125.5,125.65,123.51,124.72,1732421.0,0.0,1.0,125.5,125.65,123.51,124.72,1732421.0
-2017-11-01,125.63,126.44,123.4,124.78,1612432.0,0.0,1.0,125.63,126.44,123.4,124.78,1612432.0
-2017-10-31,124.28,125.01,123.42,124.96,1836559.0,0.0,1.0,124.28,125.01,123.42,124.96,1836559.0
-2017-10-30,123.04,124.28,121.9,123.91,1606533.0,0.0,1.0,123.04,124.28,121.9,123.91,1606533.0
-2017-10-27,121.61,123.97,121.4,123.58,1503302.0,0.0,1.0,121.61,123.97,121.4,123.58,1503302.0
-2017-10-26,120.21,121.95,119.46,121.35,893806.0,0.0,1.0,120.21,121.95,119.46,121.35,893806.0
-2017-10-25,119.0,120.25,118.05,119.94,1064033.0,0.0,1.0,119.0,120.25,118.05,119.94,1064033.0
-2017-10-24,118.96,119.61,117.9,119.29,1306666.0,0.0,1.0,118.96,119.61,117.9,119.29,1306666.0
-2017-10-23,120.99,121.72,118.73,118.99,1484003.0,0.0,1.0,120.99,121.72,118.73,118.99,1484003.0
-2017-10-20,119.98,121.88,119.7,120.81,1570159.0,0.0,1.0,119.98,121.88,119.7,120.81,1570159.0
-2017-10-19,119.0,119.32,117.57,119.29,1087574.0,0.0,1.0,119.0,119.32,117.57,119.29,1087574.0
-2017-10-18,118.5,118.86,117.7834,118.54,998575.0,0.0,1.0,118.5,118.86,117.7834,118.54,998575.0
-2017-10-17,119.35,119.7599,118.06,118.72,1179973.0,0.0,1.0,119.35,119.7599,118.06,118.72,1179973.0
-2017-10-16,119.69,119.97,118.67,119.2,1176704.0,0.0,1.0,119.69,119.97,118.67,119.2,1176704.0
-2017-10-13,119.77,119.77,118.4498,119.63,1226925.0,0.0,1.0,119.77,119.77,118.4498,119.63,1226925.0
-2017-10-12,118.55,119.84,118.51,118.99,1226381.0,0.0,1.0,118.55,119.84,118.51,118.99,1226381.0
-2017-10-11,117.02,118.66,116.93,118.57,1072510.0,0.0,1.0,117.02,118.66,116.93,118.57,1072510.0
-2017-10-10,117.22,117.53,116.32,117.05,916721.0,0.0,1.0,117.22,117.53,116.32,117.05,916721.0
-2017-10-09,116.8,117.52,116.64,117.14,847005.0,0.0,1.0,116.8,117.52,116.64,117.14,847005.0
-2017-10-06,116.18,117.61,115.81,116.96,1718039.0,0.0,1.0,116.18,117.61,115.81,116.96,1718039.0
-2017-10-05,114.5,116.83,113.9,116.54,1578348.0,0.0,1.0,114.5,116.83,113.9,116.54,1578348.0
-2017-10-04,113.79,114.07,112.35,114.05,1120483.0,0.0,1.0,113.79,114.07,112.35,114.05,1120483.0
-2017-10-03,112.39,113.73,111.67,113.63,1039855.0,0.0,1.0,112.39,113.73,111.67,113.63,1039855.0
-2017-10-02,110.6915,113.76,110.68,112.47,1957433.0,0.0,1.0,110.6915,113.76,110.68,112.47,1957433.0
-2017-09-29,111.25,112.76,111.0,112.26,2013739.0,0.0,1.0,111.25,112.76,111.0,112.26,2013739.0
-2017-09-28,111.4,111.96,110.52,111.45,1335191.0,0.0,1.0,111.4,111.96,110.52,111.45,1335191.0
-2017-09-27,110.21,113.47,110.21,111.96,1717796.0,0.0,1.0,110.21,113.47,110.21,111.96,1717796.0
-2017-09-26,110.59,111.38,108.83,110.61,1579054.0,0.0,1.0,110.59,111.38,108.83,110.61,1579054.0
-2017-09-25,111.67,111.83,108.65,109.82,2015979.0,0.0,1.0,111.67,111.83,108.65,109.82,2015979.0
-2017-09-22,111.68,112.82,111.64,111.78,944731.0,0.0,1.0,111.68,112.82,111.64,111.78,944731.0
-2017-09-21,112.82,113.0,111.37,112.29,1148893.0,0.0,1.0,112.82,113.0,111.37,112.29,1148893.0
-2017-09-20,113.07,113.339,111.35,112.73,1686485.0,0.0,1.0,113.07,113.339,111.35,112.73,1686485.0
-2017-09-19,113.77,114.06,112.97,113.08,1945388.0,0.0,1.0,113.77,114.06,112.97,113.08,1945388.0
-2017-09-18,113.74,114.66,112.87,113.84,2020868.0,0.0,1.0,113.74,114.66,112.87,113.84,2020868.0
-2017-09-15,115.62,115.62,113.88,114.3,6185403.0,0.0,1.0,115.62,115.62,113.88,114.3,6185403.0
-2017-09-14,115.62,116.14,114.5,115.48,1625113.0,0.0,1.0,115.62,116.14,114.5,115.48,1625113.0
-2017-09-13,116.04,116.5,115.25,116.18,1269826.0,0.0,1.0,116.04,116.5,115.25,116.18,1269826.0
-2017-09-12,116.35,116.99,114.98,116.16,1523756.0,0.0,1.0,116.35,116.99,114.98,116.16,1523756.0
-2017-09-11,112.98,117.125,112.22,116.48,2279670.0,0.0,1.0,112.98,117.125,112.22,116.48,2279670.0
-2017-09-08,114.17,115.72,114.1,114.44,2650236.0,0.0,1.0,114.17,115.72,114.1,114.44,2650236.0
-2017-09-07,114.14,114.465,113.19,114.05,1705693.0,0.0,1.0,114.14,114.465,113.19,114.05,1705693.0
-2017-09-06,114.4,114.78,112.65,113.79,2328344.0,0.0,1.0,114.4,114.78,112.65,113.79,2328344.0
-2017-09-05,113.46,114.81,112.52,113.77,3089055.0,0.0,1.0,113.46,114.81,112.52,113.77,3089055.0
-2017-09-01,114.63,115.62,113.65,113.71,1521113.0,0.0,1.0,114.63,115.62,113.65,113.71,1521113.0
-2017-08-31,113.63,114.7,112.815,114.46,1442442.0,0.0,1.0,113.63,114.7,112.815,114.46,1442442.0
-2017-08-30,111.27,113.67,110.61,113.29,1439951.0,0.0,1.0,111.27,113.67,110.61,113.29,1439951.0
-2017-08-29,109.65,111.895,109.25,111.27,1798166.0,0.0,1.0,109.65,111.895,109.25,111.27,1798166.0
-2017-08-28,115.06,115.14,110.01,111.48,3591870.0,0.0,1.0,115.06,115.14,110.01,111.48,3591870.0
-2017-08-25,115.0,119.73,113.54,114.97,7085626.0,0.0,1.0,115.0,119.73,113.54,114.97,7085626.0
-2017-08-24,110.58,111.25,109.04,110.61,2948237.0,0.0,1.0,110.58,111.25,109.04,110.61,2948237.0
-2017-08-23,110.91,111.34,110.05,110.65,1631213.0,0.0,1.0,110.91,111.34,110.05,110.65,1631213.0
-2017-08-22,110.31,112.235,109.77,111.01,1705576.0,0.0,1.0,110.31,112.235,109.77,111.01,1705576.0
-2017-08-21,108.37,110.3,108.37,109.75,1265606.0,0.0,1.0,108.37,110.3,108.37,109.75,1265606.0
-2017-08-18,107.86,110.1,107.19,108.56,1145061.0,0.0,1.0,107.86,110.1,107.19,108.56,1145061.0
-2017-08-17,110.07,110.82,107.73,107.89,1715092.0,0.0,1.0,110.07,110.82,107.73,107.89,1715092.0
-2017-08-16,110.36,110.93,109.36,110.49,1312081.0,0.0,1.0,110.36,110.93,109.36,110.49,1312081.0
-2017-08-15,109.02,110.1,108.12,109.8,1258345.0,0.0,1.0,109.02,110.1,108.12,109.8,1258345.0
-2017-08-14,109.2,110.0,108.01,108.9,1634486.0,0.0,1.0,109.2,110.0,108.01,108.9,1634486.0
-2017-08-11,105.75,108.7577,105.1,108.01,1422869.0,0.0,1.0,105.75,108.7577,105.1,108.01,1422869.0
-2017-08-10,106.56,107.54,104.77,104.98,1842203.0,0.0,1.0,106.56,107.54,104.77,104.98,1842203.0
-2017-08-09,107.69,107.96,106.54,107.45,1115478.0,0.0,1.0,107.69,107.96,106.54,107.45,1115478.0
-2017-08-08,109.38,110.27,108.0,108.35,1080202.0,0.0,1.0,109.38,110.27,108.0,108.35,1080202.0
-2017-08-07,108.67,111.0,108.4,109.82,1491115.0,0.0,1.0,108.67,111.0,108.4,109.82,1491115.0
-2017-08-04,108.35,109.04,107.56,108.39,1481357.0,0.0,1.0,108.35,109.04,107.56,108.39,1481357.0
-2017-08-03,107.95,108.5,105.6,107.88,2249989.0,0.0,1.0,107.95,108.5,105.6,107.88,2249989.0
-2017-08-02,111.08,111.38,107.28,109.13,1756009.0,0.0,1.0,111.08,111.38,107.28,109.13,1756009.0
-2017-08-01,111.27,112.59,111.1,111.38,1304376.0,0.0,1.0,111.27,112.59,111.1,111.38,1304376.0
-2017-07-31,111.65,112.315,109.78,110.79,1356552.0,0.0,1.0,111.65,112.315,109.78,110.79,1356552.0
-2017-07-28,110.6,112.2754,110.3326,111.5,939043.0,0.0,1.0,110.6,112.2754,110.3326,111.5,939043.0
-2017-07-27,114.97,115.25,109.32,111.52,2357620.0,0.0,1.0,114.97,115.25,109.32,111.52,2357620.0
-2017-07-26,112.5,114.1,112.41,114.08,1882057.0,0.0,1.0,112.5,114.1,112.41,114.08,1882057.0
-2017-07-25,110.91,112.4,110.2,112.26,1337115.0,0.0,1.0,110.91,112.4,110.2,112.26,1337115.0
-2017-07-24,109.59,110.89,109.335,110.81,1050047.0,0.0,1.0,109.59,110.89,109.335,110.81,1050047.0
-2017-07-21,109.41,110.54,109.08,109.75,1100700.0,0.0,1.0,109.41,110.54,109.08,109.75,1100700.0
-2017-07-20,109.72,110.5,108.88,109.91,1259425.0,0.0,1.0,109.72,110.5,108.88,109.91,1259425.0
-2017-07-19,108.5,110.5,108.47,110.25,2034611.0,0.0,1.0,108.5,110.5,108.47,110.25,2034611.0
-2017-07-18,106.67,107.85,106.23,107.7,862647.0,0.0,1.0,106.67,107.85,106.23,107.7,862647.0
-2017-07-17,108.9,109.0,106.56,106.94,1175554.0,0.0,1.0,108.9,109.0,106.56,106.94,1175554.0
-2017-07-14,107.46,108.91,107.01,108.74,1479526.0,0.0,1.0,107.46,108.91,107.01,108.74,1479526.0
-2017-07-13,107.49,108.5,106.38,107.07,1411266.0,0.0,1.0,107.49,108.5,106.38,107.07,1411266.0
-2017-07-12,105.61,107.08,104.76,106.68,2612888.0,0.0,1.0,105.61,107.08,104.76,106.68,2612888.0
-2017-07-11,103.47,104.73,102.98,104.3,1450669.0,0.0,1.0,103.47,104.73,102.98,104.3,1450669.0
-2017-07-10,103.33,104.185,102.38,103.74,1191783.0,0.0,1.0,103.33,104.185,102.38,103.74,1191783.0
-2017-07-07,102.29,104.28,102.29,103.32,1666452.0,0.0,1.0,102.29,104.28,102.29,103.32,1666452.0
-2017-07-06,101.59,103.11,100.794,102.05,2593456.0,0.0,1.0,101.59,103.11,100.794,102.05,2593456.0
-2017-07-05,99.37,103.04,99.22,102.6,2759895.0,0.0,1.0,99.37,103.04,99.22,102.6,2759895.0
-2017-07-03,101.32,101.82,99.32,99.36,1454229.0,0.0,1.0,101.32,101.82,99.32,99.36,1454229.0
-2017-06-30,102.32,102.37,100.75,100.82,1659031.0,0.0,1.0,102.32,102.37,100.75,100.82,1659031.0
-2017-06-29,103.57,103.8105,100.0,101.39,2333399.0,0.0,1.0,103.57,103.8105,100.0,101.39,2333399.0
-2017-06-28,103.69,104.86,101.54,104.28,1640245.0,0.0,1.0,103.69,104.86,101.54,104.28,1640245.0
-2017-06-27,105.58,106.45,102.5,102.92,2215375.0,0.0,1.0,105.58,106.45,102.5,102.92,2215375.0
-2017-06-26,107.76,109.07,105.31,106.12,1870235.0,0.0,1.0,107.76,109.07,105.31,106.12,1870235.0
-2017-06-23,106.4,108.76,105.3,107.71,3598155.0,0.0,1.0,106.4,108.76,105.3,107.71,3598155.0
-2017-06-22,105.72,107.26,104.55,106.78,2327303.0,0.0,1.0,105.72,107.26,104.55,106.78,2327303.0
-2017-06-21,105.88,106.56,104.82,105.69,2641503.0,0.0,1.0,105.88,106.56,104.82,105.69,2641503.0
-2017-06-20,106.01,107.11,104.3,104.93,1946595.0,0.0,1.0,106.01,107.11,104.3,104.93,1946595.0
-2017-06-19,105.6,106.7,105.16,106.16,2432063.0,0.0,1.0,105.6,106.7,105.16,106.16,2432063.0
-2017-06-16,105.5,105.92,103.63,104.88,2536983.0,0.0,1.0,105.5,105.92,103.63,104.88,2536983.0
-2017-06-15,104.77,106.04,103.48,105.58,1740903.0,0.0,1.0,104.77,106.04,103.48,105.58,1740903.0
-2017-06-14,108.52,108.65,105.0232,106.2,1953219.0,0.0,1.0,108.52,108.65,105.0232,106.2,1953219.0
-2017-06-13,107.6,108.24,105.17,107.55,2257865.0,0.0,1.0,107.6,108.24,105.17,107.55,2257865.0
-2017-06-12,104.21,108.62,100.7,107.44,5005477.0,0.0,1.0,104.21,108.62,100.7,107.44,5005477.0
-2017-06-09,111.16,111.6999,103.62,105.95,3011163.0,0.0,1.0,111.16,111.6999,103.62,105.95,3011163.0
-2017-06-08,111.51,111.95,110.2,111.12,2006959.0,0.0,1.0,111.51,111.95,110.2,111.12,2006959.0
-2017-06-07,111.38,112.08,110.6,111.17,2010213.0,0.0,1.0,111.38,112.08,110.6,111.17,2010213.0
-2017-06-06,110.4,112.27,110.19,111.45,1505270.0,0.0,1.0,110.4,112.27,110.19,111.45,1505270.0
-2017-06-05,112.74,113.14,110.23,110.88,3933494.0,0.0,1.0,112.74,113.14,110.23,110.88,3933494.0
-2017-06-02,113.78,113.88,111.76,112.91,2213075.0,0.0,1.0,113.78,113.88,111.76,112.91,2213075.0
-2017-06-01,111.72,113.12,110.94,113.03,2318445.0,0.0,1.0,111.72,113.12,110.94,113.03,2318445.0
diff --git a/examples/quick/demos/stocqt/content/data/AMD.csv b/examples/quick/demos/stocqt/content/data/AMD.csv
deleted file mode 100644
index 62c33c6faa..0000000000
--- a/examples/quick/demos/stocqt/content/data/AMD.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,10.57,10.58,10.27,10.28,26321111.0,0.0,1.0,10.57,10.58,10.27,10.28,26321111.0
-2017-12-28,10.57,10.64,10.43,10.55,18345480.0,0.0,1.0,10.57,10.64,10.43,10.55,18345480.0
-2017-12-27,10.45,10.74,10.4,10.53,22780900.0,0.0,1.0,10.45,10.74,10.4,10.53,22780900.0
-2017-12-26,10.38,10.579,10.34,10.46,20362897.0,0.0,1.0,10.38,10.579,10.34,10.46,20362897.0
-2017-12-22,10.75,10.77,10.2,10.54,50572874.0,0.0,1.0,10.75,10.77,10.2,10.54,50572874.0
-2017-12-21,10.98,11.0793,10.87,10.89,21645217.0,0.0,1.0,10.98,11.0793,10.87,10.89,21645217.0
-2017-12-20,11.1,11.18,10.8,10.98,31053753.0,0.0,1.0,11.1,11.18,10.8,10.98,31053753.0
-2017-12-19,11.0,11.19,10.87,10.95,43445290.0,0.0,1.0,11.0,11.19,10.87,10.95,43445290.0
-2017-12-18,10.6,11.0,10.51,10.98,62789226.0,0.0,1.0,10.6,11.0,10.51,10.98,62789226.0
-2017-12-15,10.13,10.32,10.02,10.3,42459234.0,0.0,1.0,10.13,10.32,10.02,10.3,42459234.0
-2017-12-14,10.1,10.17,9.96,10.13,26491754.0,0.0,1.0,10.1,10.17,9.96,10.13,26491754.0
-2017-12-13,9.97,10.21,9.95,10.11,41201508.0,0.0,1.0,9.97,10.21,9.95,10.11,41201508.0
-2017-12-12,10.13,10.14,9.88,9.9,35843064.0,0.0,1.0,10.13,10.14,9.88,9.9,35843064.0
-2017-12-11,9.97,10.16,9.96,10.16,29359732.0,0.0,1.0,9.97,10.16,9.96,10.16,29359732.0
-2017-12-08,10.15,10.2,9.92,9.94,34582737.0,0.0,1.0,10.15,10.2,9.92,9.94,34582737.0
-2017-12-07,10.0705,10.19,9.95,10.04,32273896.0,0.0,1.0,10.0705,10.19,9.95,10.04,32273896.0
-2017-12-06,9.9,10.05,9.71,10.0,38351614.0,0.0,1.0,9.9,10.05,9.71,10.0,38351614.0
-2017-12-05,9.89,10.34,9.7,9.91,66840417.0,0.0,1.0,9.89,10.34,9.7,9.91,66840417.0
-2017-12-04,10.85,10.86,9.82,10.03,95608827.0,0.0,1.0,10.85,10.86,9.82,10.03,95608827.0
-2017-12-01,10.81,10.97,10.53,10.7201,41932685.0,0.0,1.0,10.81,10.97,10.53,10.7201,41932685.0
-2017-11-30,10.87,11.03,10.76,10.89,42311007.0,0.0,1.0,10.87,11.03,10.76,10.89,42311007.0
-2017-11-29,11.08,11.17,10.73,10.825,63028757.0,0.0,1.0,11.08,11.17,10.73,10.825,63028757.0
-2017-11-28,11.45,11.54,11.0,11.17,65088197.0,0.0,1.0,11.45,11.54,11.0,11.17,65088197.0
-2017-11-27,11.34,11.74,11.3358,11.55,41565129.0,0.0,1.0,11.34,11.74,11.3358,11.55,41565129.0
-2017-11-24,11.38,11.42,11.3,11.38,11033178.0,0.0,1.0,11.38,11.42,11.3,11.38,11033178.0
-2017-11-22,11.41,11.49,11.3,11.37,23686100.0,0.0,1.0,11.41,11.49,11.3,11.37,23686100.0
-2017-11-21,11.421,11.49,11.24,11.4,31469531.0,0.0,1.0,11.421,11.49,11.24,11.4,31469531.0
-2017-11-20,11.47,11.505,11.19,11.34,35827552.0,0.0,1.0,11.47,11.505,11.19,11.34,35827552.0
-2017-11-17,11.3,11.75,11.28,11.38,56245136.0,0.0,1.0,11.3,11.75,11.28,11.38,56245136.0
-2017-11-16,11.13,11.32,11.13,11.25,30814936.0,0.0,1.0,11.13,11.32,11.13,11.25,30814936.0
-2017-11-15,11.01,11.13,10.77,11.07,33326871.0,0.0,1.0,11.01,11.13,10.77,11.07,33326871.0
-2017-11-14,11.03,11.26,11.0,11.12,36254723.0,0.0,1.0,11.03,11.26,11.0,11.12,36254723.0
-2017-11-13,11.18,11.2,10.92,11.09,53925999.0,0.0,1.0,11.18,11.2,10.92,11.09,53925999.0
-2017-11-10,11.22,11.43,11.115,11.26,50022529.0,0.0,1.0,11.22,11.43,11.115,11.26,50022529.0
-2017-11-09,11.25,11.35,11.03,11.12,75698460.0,0.0,1.0,11.25,11.35,11.03,11.12,75698460.0
-2017-11-07,11.94,12.27,11.92,12.05,66232713.0,0.0,1.0,11.94,12.27,11.92,12.05,66232713.0
-2017-11-06,12.04,12.09,11.64,11.93,95719936.0,0.0,1.0,12.04,12.09,11.64,11.93,95719936.0
-2017-11-03,10.95,11.13,10.82,11.12,43989491.0,0.0,1.0,10.95,11.13,10.82,11.12,43989491.0
-2017-11-02,10.87,10.99,10.66,10.85,47509725.0,0.0,1.0,10.87,10.99,10.66,10.85,47509725.0
-2017-11-01,11.25,11.29,10.72,10.8,66416610.0,0.0,1.0,11.25,11.29,10.72,10.8,66416610.0
-2017-10-31,10.76,11.31,10.69,10.985,78118243.0,0.0,1.0,10.76,11.31,10.69,10.985,78118243.0
-2017-10-30,11.255,11.42,10.65,10.89,136725037.0,0.0,1.0,11.255,11.42,10.65,10.89,136725037.0
-2017-10-27,12.17,12.19,11.35,11.84,115163241.0,0.0,1.0,12.17,12.19,11.35,11.84,115163241.0
-2017-10-26,12.45,12.46,12.0,12.005,86725366.0,0.0,1.0,12.45,12.46,12.0,12.005,86725366.0
-2017-10-25,12.95,13.13,12.29,12.33,165686209.0,0.0,1.0,12.95,13.13,12.29,12.33,165686209.0
-2017-10-24,14.2,14.36,14.15,14.25,60340437.0,0.0,1.0,14.2,14.36,14.15,14.25,60340437.0
-2017-10-23,13.94,14.19,13.8999,14.1,49438627.0,0.0,1.0,13.94,14.19,13.8999,14.1,49438627.0
-2017-10-20,14.03,14.09,13.8,13.81,31624215.0,0.0,1.0,14.03,14.09,13.8,13.81,31624215.0
-2017-10-19,13.85,14.04,13.69,13.95,33600243.0,0.0,1.0,13.85,14.04,13.69,13.95,33600243.0
-2017-10-18,14.2,14.279,13.76,14.07,38868463.0,0.0,1.0,14.2,14.279,13.76,14.07,38868463.0
-2017-10-17,14.24,14.345,14.135,14.16,28695155.0,0.0,1.0,14.24,14.345,14.135,14.16,28695155.0
-2017-10-16,14.25,14.35,14.12,14.26,33684147.0,0.0,1.0,14.25,14.35,14.12,14.26,33684147.0
-2017-10-13,14.32,14.41,14.12,14.22,37160693.0,0.0,1.0,14.32,14.41,14.12,14.22,37160693.0
-2017-10-12,13.85,14.37,13.81,14.2,69313327.0,0.0,1.0,13.85,14.37,13.81,14.2,69313327.0
-2017-10-11,13.62,13.96,13.61,13.88,38017847.0,0.0,1.0,13.62,13.96,13.61,13.88,38017847.0
-2017-10-10,13.72,13.79,13.44,13.7,43046193.0,0.0,1.0,13.72,13.79,13.44,13.7,43046193.0
-2017-10-09,13.26,13.83,13.26,13.47,53748724.0,0.0,1.0,13.26,13.83,13.26,13.47,53748724.0
-2017-10-06,13.22,13.39,13.18,13.23,27939491.0,0.0,1.0,13.22,13.39,13.18,13.23,27939491.0
-2017-10-05,13.38,13.46,13.21,13.34,34409933.0,0.0,1.0,13.38,13.46,13.21,13.34,34409933.0
-2017-10-04,13.31,13.5,13.15,13.31,41814144.0,0.0,1.0,13.31,13.5,13.15,13.31,41814144.0
-2017-10-03,12.73,13.48,12.7,13.42,84656340.0,0.0,1.0,12.73,13.48,12.7,13.42,84656340.0
-2017-10-02,12.8,12.85,12.62,12.71,34256219.0,0.0,1.0,12.8,12.85,12.62,12.71,34256219.0
-2017-09-29,12.765,12.82,12.6,12.75,33358815.0,0.0,1.0,12.765,12.82,12.6,12.75,33358815.0
-2017-09-28,12.76,12.84,12.55,12.74,35439338.0,0.0,1.0,12.76,12.84,12.55,12.74,35439338.0
-2017-09-27,12.65,12.87,12.5,12.74,59391214.0,0.0,1.0,12.65,12.87,12.5,12.74,59391214.0
-2017-09-26,12.85,12.93,12.43,12.45,67417625.0,0.0,1.0,12.85,12.93,12.43,12.45,67417625.0
-2017-09-25,13.25,13.28,12.49,12.61,83429167.0,0.0,1.0,13.25,13.28,12.49,12.61,83429167.0
-2017-09-22,13.2,13.4,13.12,13.3,49752570.0,0.0,1.0,13.2,13.4,13.12,13.3,49752570.0
-2017-09-21,14.0,14.24,13.32,13.41,164802839.0,0.0,1.0,14.0,14.24,13.32,13.41,164802839.0
-2017-09-20,13.07,13.8,12.8,13.76,82385985.0,0.0,1.0,13.07,13.8,12.8,13.76,82385985.0
-2017-09-19,13.25,13.29,12.88,13.12,64693928.0,0.0,1.0,13.25,13.29,12.88,13.12,64693928.0
-2017-09-18,12.77,13.3,12.74,13.08,82647358.0,0.0,1.0,12.77,13.3,12.74,13.08,82647358.0
-2017-09-15,12.33,12.66,12.31,12.52,49576344.0,0.0,1.0,12.33,12.66,12.31,12.52,49576344.0
-2017-09-14,12.15,12.46,12.11,12.26,36903301.0,0.0,1.0,12.15,12.46,12.11,12.26,36903301.0
-2017-09-13,12.22,12.36,12.12,12.22,36978783.0,0.0,1.0,12.22,12.36,12.12,12.22,36978783.0
-2017-09-12,12.66,12.68,12.213,12.3,54029549.0,0.0,1.0,12.66,12.68,12.213,12.3,54029549.0
-2017-09-11,12.46,12.74,12.4001,12.55,42904404.0,0.0,1.0,12.46,12.74,12.4001,12.55,42904404.0
-2017-09-08,12.5712,12.61,12.035,12.25,60503832.0,0.0,1.0,12.5712,12.61,12.035,12.25,60503832.0
-2017-09-07,12.84,12.94,12.6,12.63,35467788.0,0.0,1.0,12.84,12.94,12.6,12.63,35467788.0
-2017-09-06,13.02,13.08,12.75,12.85,33828656.0,0.0,1.0,13.02,13.08,12.75,12.85,33828656.0
-2017-09-05,12.88,13.18,12.65,12.92,51359359.0,0.0,1.0,12.88,13.18,12.65,12.92,51359359.0
-2017-09-01,13.12,13.485,13.04,13.19,52901453.0,0.0,1.0,13.12,13.485,13.04,13.19,52901453.0
-2017-08-31,12.82,13.16,12.79,13.0,51056961.0,0.0,1.0,12.82,13.16,12.79,13.0,51056961.0
-2017-08-30,12.19,12.68,12.16,12.67,43434380.0,0.0,1.0,12.19,12.68,12.16,12.67,43434380.0
-2017-08-29,12.0,12.18,11.93,12.15,33290113.0,0.0,1.0,12.0,12.18,11.93,12.15,33290113.0
-2017-08-28,12.53,12.55,12.16,12.23,35078317.0,0.0,1.0,12.53,12.55,12.16,12.23,35078317.0
-2017-08-25,12.51,12.57,12.25,12.425,29543318.0,0.0,1.0,12.51,12.57,12.25,12.425,29543318.0
-2017-08-24,12.69,12.71,12.39,12.505,37056907.0,0.0,1.0,12.69,12.71,12.39,12.505,37056907.0
-2017-08-23,12.0,12.535,11.95,12.48,43429439.0,0.0,1.0,12.0,12.535,11.95,12.48,43429439.0
-2017-08-22,12.2,12.33,12.1,12.175,38705808.0,0.0,1.0,12.2,12.33,12.1,12.175,38705808.0
-2017-08-21,12.42,12.42,11.86,12.05,58620489.0,0.0,1.0,12.42,12.42,11.86,12.05,58620489.0
-2017-08-18,12.43,12.555,12.25,12.376,37172947.0,0.0,1.0,12.43,12.555,12.25,12.376,37172947.0
-2017-08-17,12.46,12.65,12.32,12.34,46960411.0,0.0,1.0,12.46,12.65,12.32,12.34,46960411.0
-2017-08-16,13.17,13.19,12.52,12.63,64171662.0,0.0,1.0,13.17,13.19,12.52,12.63,64171662.0
-2017-08-15,13.01,13.14,12.75,13.02,57447725.0,0.0,1.0,13.01,13.14,12.75,13.02,57447725.0
-2017-08-14,12.58,12.845,12.58,12.76,63873137.0,0.0,1.0,12.58,12.845,12.58,12.76,63873137.0
-2017-08-11,12.04,12.39,11.88,12.23,63319050.0,0.0,1.0,12.04,12.39,11.88,12.23,63319050.0
-2017-08-10,12.7,12.92,12.11,12.12,80131441.0,0.0,1.0,12.7,12.92,12.11,12.12,80131441.0
-2017-08-09,12.76,12.89,12.54,12.83,58571682.0,0.0,1.0,12.76,12.89,12.54,12.83,58571682.0
-2017-08-08,13.48,13.55,13.08,13.11,46548040.0,0.0,1.0,13.48,13.55,13.08,13.11,46548040.0
-2017-08-07,13.33,13.57,13.27,13.43,57203474.0,0.0,1.0,13.33,13.57,13.27,13.43,57203474.0
-2017-08-04,13.2,13.36,13.02,13.12,63954775.0,0.0,1.0,13.2,13.36,13.02,13.12,63954775.0
-2017-08-03,13.42,13.52,13.08,13.24,51720273.0,0.0,1.0,13.42,13.52,13.08,13.24,51720273.0
-2017-08-02,13.81,13.93,13.12,13.37,67062121.0,0.0,1.0,13.81,13.93,13.12,13.37,67062121.0
-2017-08-01,13.72,13.86,13.45,13.71,48273874.0,0.0,1.0,13.72,13.86,13.45,13.71,48273874.0
-2017-07-31,14.09,14.22,13.47,13.61,68653763.0,0.0,1.0,14.09,14.22,13.47,13.61,68653763.0
-2017-07-28,13.845,14.1,13.68,13.95,66352470.0,0.0,1.0,13.845,14.1,13.68,13.95,66352470.0
-2017-07-27,14.99,15.04,13.7,14.12,129095996.0,0.0,1.0,14.99,15.04,13.7,14.12,129095996.0
-2017-07-26,15.13,15.65,14.4,14.76,234655935.0,0.0,1.0,15.13,15.65,14.4,14.76,234655935.0
-2017-07-25,14.2895,14.32,13.87,14.11,76089789.0,0.0,1.0,14.2895,14.32,13.87,14.11,76089789.0
-2017-07-24,14.0,14.44,13.97,14.16,70306709.0,0.0,1.0,14.0,14.44,13.97,14.16,70306709.0
-2017-07-21,13.7,14.05,13.62,13.88,50836269.0,0.0,1.0,13.7,14.05,13.62,13.88,50836269.0
-2017-07-20,13.61,13.89,13.45,13.8,47328081.0,0.0,1.0,13.61,13.89,13.45,13.8,47328081.0
-2017-07-19,13.62,13.74,13.41,13.55,51511044.0,0.0,1.0,13.62,13.74,13.41,13.55,51511044.0
-2017-07-18,13.29,13.53,13.15,13.48,77823247.0,0.0,1.0,13.29,13.53,13.15,13.48,77823247.0
-2017-07-17,14.03,14.12,13.51,13.8,70594469.0,0.0,1.0,14.03,14.12,13.51,13.8,70594469.0
-2017-07-14,13.46,13.93,13.32,13.92,81515312.0,0.0,1.0,13.46,13.93,13.32,13.92,81515312.0
-2017-07-13,14.33,14.49,13.43,13.53,110860494.0,0.0,1.0,14.33,14.49,13.43,13.53,110860494.0
-2017-07-12,14.17,14.39,13.96,14.29,78011028.0,0.0,1.0,14.17,14.39,13.96,14.29,78011028.0
-2017-07-11,13.77,14.099,13.62,13.89,70760527.0,0.0,1.0,13.77,14.099,13.62,13.89,70760527.0
-2017-07-10,13.61,13.88,13.27,13.81,77940920.0,0.0,1.0,13.61,13.88,13.27,13.81,77940920.0
-2017-07-07,13.27,13.745,13.18,13.36,88021133.0,0.0,1.0,13.27,13.745,13.18,13.36,88021133.0
-2017-07-06,12.94,13.32,12.665,13.02,88418322.0,0.0,1.0,12.94,13.32,12.665,13.02,88418322.0
-2017-07-05,12.36,13.21,12.32,13.19,98729984.0,0.0,1.0,12.36,13.21,12.32,13.19,98729984.0
-2017-07-03,12.57,12.73,12.13,12.15,39888247.0,0.0,1.0,12.57,12.73,12.13,12.15,39888247.0
-2017-06-30,12.57,12.83,12.36,12.48,58976478.0,0.0,1.0,12.57,12.83,12.36,12.48,58976478.0
-2017-06-29,13.06,13.15,12.45,12.6,86658774.0,0.0,1.0,13.06,13.15,12.45,12.6,86658774.0
-2017-06-28,13.65,13.7,13.09,13.23,84591176.0,0.0,1.0,13.65,13.7,13.09,13.23,84591176.0
-2017-06-27,13.76,14.04,13.37,13.395,88742270.0,0.0,1.0,13.76,14.04,13.37,13.395,88742270.0
-2017-06-26,14.39,14.49,13.84,14.08,100078492.0,0.0,1.0,14.39,14.49,13.84,14.08,100078492.0
-2017-06-23,14.15,14.67,13.9,14.15,151603584.0,0.0,1.0,14.15,14.67,13.9,14.15,151603584.0
-2017-06-22,14.1,14.5,13.56,14.3708,147959418.0,0.0,1.0,14.1,14.5,13.56,14.3708,147959418.0
-2017-06-21,13.36,14.01,13.13,13.98,187161633.0,0.0,1.0,13.36,14.01,13.13,13.98,187161633.0
-2017-06-20,12.19,12.93,12.18,12.64,116319537.0,0.0,1.0,12.19,12.93,12.18,12.64,116319537.0
-2017-06-19,11.63,12.12,11.62,11.93,61268773.0,0.0,1.0,11.63,12.12,11.62,11.93,61268773.0
-2017-06-16,11.66,11.83,11.28,11.44,58774371.0,0.0,1.0,11.66,11.83,11.28,11.44,58774371.0
-2017-06-15,11.34,11.58,11.21,11.5,60332254.0,0.0,1.0,11.34,11.58,11.21,11.5,60332254.0
-2017-06-14,11.91,12.05,11.65,11.76,51454208.0,0.0,1.0,11.91,12.05,11.65,11.76,51454208.0
-2017-06-13,12.33,12.48,11.67,11.96,86585397.0,0.0,1.0,12.33,12.48,11.67,11.96,86585397.0
-2017-06-12,11.75,12.35,11.47,12.085,123725528.0,0.0,1.0,11.75,12.35,11.47,12.085,123725528.0
-2017-06-09,13.1,13.4,11.63,12.28,165174160.0,0.0,1.0,13.1,13.4,11.63,12.28,165174160.0
-2017-06-08,12.81,12.91,12.4,12.9,87201152.0,0.0,1.0,12.81,12.91,12.4,12.9,87201152.0
-2017-06-07,12.42,12.96,12.2348,12.38,149171943.0,0.0,1.0,12.42,12.96,12.2348,12.38,149171943.0
-2017-06-06,11.27,12.24,11.24,12.02,113010266.0,0.0,1.0,11.27,12.24,11.24,12.02,113010266.0
-2017-06-05,10.84,11.34,10.8,11.24,64357671.0,0.0,1.0,10.84,11.34,10.8,11.24,64357671.0
-2017-06-02,10.93,10.96,10.565,10.9,42838855.0,0.0,1.0,10.93,10.96,10.565,10.9,42838855.0
-2017-06-01,11.25,11.285,10.81,10.93,47175511.0,0.0,1.0,11.25,11.285,10.81,10.93,47175511.0
diff --git a/examples/quick/demos/stocqt/content/data/AMZN.csv b/examples/quick/demos/stocqt/content/data/AMZN.csv
deleted file mode 100644
index f6fea4d2c8..0000000000
--- a/examples/quick/demos/stocqt/content/data/AMZN.csv
+++ /dev/null
@@ -1,147 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,1182.35,1184.0,1167.5,1169.47,2625283.0,0.0,1.0,1182.35,1184.0,1167.5,1169.47,2625283.0
-2017-12-28,1189.0,1190.1,1184.38,1186.1,1803460.0,0.0,1.0,1189.0,1190.1,1184.38,1186.1,1803460.0
-2017-12-27,1179.91,1187.29,1175.61,1182.26,1779382.0,0.0,1.0,1179.91,1187.29,1175.61,1182.26,1779382.0
-2017-12-26,1168.36,1178.32,1160.55,1176.76,1964871.0,0.0,1.0,1168.36,1178.32,1160.55,1176.76,1964871.0
-2017-12-22,1172.08,1174.62,1167.83,1168.36,1553997.0,0.0,1.0,1172.08,1174.62,1167.83,1168.36,1553997.0
-2017-12-21,1175.9,1179.17,1167.64,1174.76,2042448.0,0.0,1.0,1175.9,1179.17,1167.64,1174.76,2042448.0
-2017-12-20,1190.5,1191.0,1176.0,1177.62,2318916.0,0.0,1.0,1190.5,1191.0,1176.0,1177.62,2318916.0
-2017-12-19,1189.15,1192.97,1179.14,1187.38,2555235.0,0.0,1.0,1189.15,1192.97,1179.14,1187.38,2555235.0
-2017-12-18,1187.37,1194.78,1180.91,1190.58,2767271.0,0.0,1.0,1187.37,1194.78,1180.91,1190.58,2767271.0
-2017-12-15,1179.03,1182.75,1169.33,1179.14,4539895.0,0.0,1.0,1179.03,1182.75,1169.33,1179.14,4539895.0
-2017-12-14,1163.71,1177.93,1162.45,1174.26,3069993.0,0.0,1.0,1163.71,1177.93,1162.45,1174.26,3069993.0
-2017-12-13,1170.0,1170.87,1160.27,1164.13,2555053.0,0.0,1.0,1170.0,1170.87,1160.27,1164.13,2555053.0
-2017-12-12,1166.51,1173.6,1161.61,1165.08,2197697.0,0.0,1.0,1166.51,1173.6,1161.61,1165.08,2197697.0
-2017-12-11,1164.6,1169.9,1157.0,1168.92,2257922.0,0.0,1.0,1164.6,1169.9,1157.0,1168.92,2257922.0
-2017-12-08,1170.4,1172.79,1157.1,1162.0,2957785.0,0.0,1.0,1170.4,1172.79,1157.1,1162.0,2957785.0
-2017-12-07,1156.59,1163.19,1151.0,1159.79,2408323.0,0.0,1.0,1156.59,1163.19,1151.0,1159.79,2408323.0
-2017-12-06,1137.99,1155.89,1136.08,1152.35,2756730.0,0.0,1.0,1137.99,1155.89,1136.08,1152.35,2756730.0
-2017-12-05,1128.26,1159.27,1124.74,1141.57,4033184.0,0.0,1.0,1128.26,1159.27,1124.74,1141.57,4033184.0
-2017-12-04,1173.85,1175.2,1128.0,1133.95,5872358.0,0.0,1.0,1173.85,1175.2,1128.0,1133.95,5872358.0
-2017-12-01,1172.05,1179.65,1152.0,1162.35,4070722.0,0.0,1.0,1172.05,1179.65,1152.0,1162.35,4070722.0
-2017-11-30,1167.1,1178.57,1160.0,1176.75,4406535.0,0.0,1.0,1167.1,1178.57,1160.0,1176.75,4406535.0
-2017-11-29,1194.8,1194.8,1145.19,1161.27,9179567.0,0.0,1.0,1194.8,1194.8,1145.19,1161.27,9179567.0
-2017-11-28,1204.88,1205.34,1188.52,1193.6,4463476.0,0.0,1.0,1204.88,1205.34,1188.52,1193.6,4463476.0
-2017-11-27,1202.66,1213.41,1191.15,1195.83,6701343.0,0.0,1.0,1202.66,1213.41,1191.15,1195.83,6701343.0
-2017-11-24,1160.7,1186.84,1160.7,1186.0,3526582.0,0.0,1.0,1160.7,1186.84,1160.7,1186.0,3526582.0
-2017-11-22,1141.0,1160.27,1141.0,1156.16,3516336.0,0.0,1.0,1141.0,1160.27,1141.0,1156.16,3516336.0
-2017-11-21,1132.86,1140.0,1128.2,1139.49,2449503.0,0.0,1.0,1132.86,1140.0,1128.2,1139.49,2449503.0
-2017-11-20,1129.77,1133.42,1122.55,1126.31,2134381.0,0.0,1.0,1129.77,1133.42,1122.55,1126.31,2134381.0
-2017-11-17,1138.28,1138.8,1125.81,1129.88,2333554.0,0.0,1.0,1138.28,1138.8,1125.81,1129.88,2333554.0
-2017-11-16,1130.16,1138.16,1130.05,1137.29,2190456.0,0.0,1.0,1130.16,1138.16,1130.05,1137.29,2190456.0
-2017-11-15,1127.01,1131.75,1121.63,1126.69,3897230.0,0.0,1.0,1127.01,1131.75,1121.63,1126.69,3897230.0
-2017-11-14,1130.11,1138.0,1123.89,1136.84,3042295.0,0.0,1.0,1130.11,1138.0,1123.89,1136.84,3042295.0
-2017-11-13,1123.0,1139.9,1122.34,1129.17,2897563.0,0.0,1.0,1123.0,1139.9,1122.34,1129.17,2897563.0
-2017-11-10,1126.1,1131.75,1124.06,1125.35,2162985.0,0.0,1.0,1126.1,1131.75,1124.06,1125.35,2162985.0
-2017-11-09,1125.96,1129.62,1115.77,1129.13,3661411.0,0.0,1.0,1125.96,1129.62,1115.77,1129.13,3661411.0
-2017-11-07,1124.74,1130.6,1117.5,1123.17,2623474.0,0.0,1.0,1124.74,1130.6,1117.5,1123.17,2623474.0
-2017-11-06,1109.15,1125.41,1108.77,1120.66,3313857.0,0.0,1.0,1109.15,1125.41,1108.77,1120.66,3313857.0
-2017-11-03,1091.15,1112.68,1088.52,1111.6,3685172.0,0.0,1.0,1091.15,1112.68,1088.52,1111.6,3685172.0
-2017-11-02,1097.81,1101.94,1086.87,1094.22,3658748.0,0.0,1.0,1097.81,1101.94,1086.87,1094.22,3658748.0
-2017-11-01,1105.4,1108.97,1096.74,1103.68,3723680.0,0.0,1.0,1105.4,1108.97,1096.74,1103.68,3723680.0
-2017-10-31,1109.0,1110.54,1101.12,1105.28,3428461.0,0.0,1.0,1109.0,1110.54,1101.12,1105.28,3428461.0
-2017-10-30,1095.01,1122.79,1093.56,1110.85,6516639.0,0.0,1.0,1095.01,1122.79,1093.56,1110.85,6516639.0
-2017-10-27,1058.14,1105.58,1050.55,1100.95,16360527.0,0.0,1.0,1058.14,1105.58,1050.55,1100.95,16360527.0
-2017-10-26,980.33,982.9,968.55,972.43,3670282.0,0.0,1.0,980.33,982.9,968.55,972.43,3670282.0
-2017-10-25,978.0,984.44,966.24,972.91,2969295.0,0.0,1.0,978.0,984.44,966.24,972.91,2969295.0
-2017-10-24,969.0,979.85,965.0,975.9,2666782.0,0.0,1.0,969.0,979.85,965.0,975.9,2666782.0
-2017-10-23,986.73,986.775,962.5,966.3,3465469.0,0.0,1.0,986.73,986.775,962.5,966.3,3465469.0
-2017-10-20,993.53,994.62,982.0,982.91,2294145.0,0.0,1.0,993.53,994.62,982.0,982.91,2294145.0
-2017-10-19,990.0,991.05,980.24,986.61,3040066.0,0.0,1.0,990.0,991.05,980.24,986.61,3040066.0
-2017-10-18,1009.27,1022.31,996.55,997.0,2477357.0,0.0,1.0,1009.27,1022.31,996.55,997.0,2477357.0
-2017-10-17,1005.59,1011.47,1004.38,1009.13,2307075.0,0.0,1.0,1005.59,1011.47,1004.38,1009.13,2307075.0
-2017-10-16,1008.44,1009.57,1001.04,1006.34,1991556.0,0.0,1.0,1008.44,1009.57,1001.04,1006.34,1991556.0
-2017-10-13,1007.0,1007.77,1001.03,1002.94,2399403.0,0.0,1.0,1007.0,1007.77,1001.03,1002.94,2399403.0
-2017-10-12,996.81,1008.44,992.4,1000.93,4056172.0,0.0,1.0,996.81,1008.44,992.4,1000.93,4056172.0
-2017-10-11,991.27,995.5,986.695,995.0,2310872.0,0.0,1.0,991.27,995.5,986.695,995.0,2310872.0
-2017-10-10,996.67,997.95,980.099,987.2,3062820.0,0.0,1.0,996.67,997.95,980.099,987.2,3062820.0
-2017-10-09,993.24,998.5,987.5,990.99,2927994.0,0.0,1.0,993.24,998.5,987.5,990.99,2927994.0
-2017-10-06,975.64,995.75,975.64,989.58,3719840.0,0.0,1.0,975.64,995.75,975.64,989.58,3719840.0
-2017-10-05,970.0,981.51,969.64,980.85,3119487.0,0.0,1.0,970.0,981.51,969.64,980.85,3119487.0
-2017-10-04,954.21,967.79,954.05,965.45,2460721.0,0.0,1.0,954.21,967.79,954.05,965.45,2460721.0
-2017-10-03,958.0,963.69,950.37,957.1,2643484.0,0.0,1.0,958.0,963.69,950.37,957.1,2643484.0
-2017-10-02,964.0,967.305,952.1201,959.19,2415846.0,0.0,1.0,964.0,967.305,952.1201,959.19,2415846.0
-2017-09-29,960.11,964.83,958.375,961.35,2411643.0,0.0,1.0,960.11,964.83,958.375,961.35,2411643.0
-2017-09-28,951.86,959.7,950.101,956.4,2512567.0,0.0,1.0,951.86,959.7,950.101,956.4,2512567.0
-2017-09-27,948.0,955.3,943.3,950.87,3111263.0,0.0,1.0,948.0,955.3,943.3,950.87,3111263.0
-2017-09-26,945.49,948.63,931.75,938.6,3464183.0,0.0,1.0,945.49,948.63,931.75,938.6,3464183.0
-2017-09-25,949.31,949.42,932.89,939.79,5065542.0,0.0,1.0,949.31,949.42,932.89,939.79,5065542.0
-2017-09-22,961.01,965.61,954.42,955.1,2602418.0,0.0,1.0,961.01,965.61,954.42,955.1,2602418.0
-2017-09-21,971.31,971.7,962.02,964.65,2252940.0,0.0,1.0,971.31,971.7,962.02,964.65,2252940.0
-2017-09-20,971.79,974.81,962.1626,973.21,2727355.0,0.0,1.0,971.79,974.81,962.1626,973.21,2727355.0
-2017-09-19,977.25,978.24,967.46,969.86,2614059.0,0.0,1.0,977.25,978.24,967.46,969.86,2614059.0
-2017-09-18,990.4,992.7922,968.17,974.19,3376772.0,0.0,1.0,990.4,992.7922,968.17,974.19,3376772.0
-2017-09-15,993.01,996.25,984.03,986.79,3697742.0,0.0,1.0,993.01,996.25,984.03,986.79,3697742.0
-2017-09-14,996.8,998.56,987.74,992.21,3788472.0,0.0,1.0,996.8,998.56,987.74,992.21,3788472.0
-2017-09-13,983.97,1000.0,979.42,999.6,3314978.0,0.0,1.0,983.97,1000.0,979.42,999.6,3314978.0
-2017-09-12,983.27,984.6718,975.517,982.58,2444699.0,0.0,1.0,983.27,984.6718,975.517,982.58,2444699.0
-2017-09-11,974.46,981.94,974.22,977.96,2134582.0,0.0,1.0,974.46,981.94,974.22,977.96,2134582.0
-2017-09-08,979.1,979.88,963.47,965.9,2578269.0,0.0,1.0,979.1,979.88,963.47,965.9,2578269.0
-2017-09-07,974.0,980.59,972.55,979.47,2536000.0,0.0,1.0,974.0,980.59,972.55,979.47,2536000.0
-2017-09-06,968.32,971.84,960.6,967.8,2106605.0,0.0,1.0,968.32,971.84,960.6,967.8,2106605.0
-2017-09-05,975.4,976.7699,960.37,965.27,2875228.0,0.0,1.0,975.4,976.7699,960.37,965.27,2875228.0
-2017-09-01,984.2,984.5,976.875,978.25,2423132.0,0.0,1.0,984.2,984.5,976.875,978.25,2423132.0
-2017-08-31,974.7,981.0,972.76,980.6,3280945.0,0.0,1.0,974.7,981.0,972.76,980.6,3280945.0
-2017-08-30,958.44,969.41,956.9062,967.59,2860718.0,0.0,1.0,958.44,969.41,956.9062,967.59,2860718.0
-2017-08-29,940.0,956.0,936.33,954.06,2853972.0,0.0,1.0,940.0,956.0,936.33,954.06,2853972.0
-2017-08-28,946.54,953.0,942.25,946.02,2529087.0,0.0,1.0,946.54,953.0,942.25,946.02,2529087.0
-2017-08-25,956.0,957.621,944.1,945.26,3292776.0,0.0,1.0,956.0,957.621,944.1,945.26,3292776.0
-2017-08-24,957.42,959.0,941.14,952.45,5086748.0,0.0,1.0,957.42,959.0,941.14,952.45,5086748.0
-2017-08-23,959.38,962.0,954.2,958.0,2590245.0,0.0,1.0,959.38,962.0,954.2,958.0,2590245.0
-2017-08-22,955.52,967.93,955.495,966.9,2718261.0,0.0,1.0,955.52,967.93,955.495,966.9,2718261.0
-2017-08-21,957.57,961.2,945.46,953.29,3008450.0,0.0,1.0,957.57,961.2,945.46,953.29,3008450.0
-2017-08-18,961.4,965.43,954.65,958.47,3248677.0,0.0,1.0,961.4,965.43,954.65,958.47,3248677.0
-2017-08-17,977.84,977.84,960.32,960.57,3396045.0,0.0,1.0,977.84,977.84,960.32,960.57,3396045.0
-2017-08-16,981.65,986.4605,973.22,978.18,3096051.0,0.0,1.0,981.65,986.4605,973.22,978.18,3096051.0
-2017-08-15,988.9,991.74,982.0,982.74,2513139.0,0.0,1.0,988.9,991.74,982.0,982.74,2513139.0
-2017-08-14,978.41,985.5,976.19,983.3,3008007.0,0.0,1.0,978.41,985.5,976.19,983.3,3008007.0
-2017-08-11,960.0,970.39,951.38,967.99,3431423.0,0.0,1.0,960.0,970.39,951.38,967.99,3431423.0
-2017-08-10,976.295,979.86,954.68,956.92,5560388.0,0.0,1.0,976.295,979.86,954.68,956.92,5560388.0
-2017-08-09,982.6,988.0,975.27,982.01,3434077.0,0.0,1.0,982.6,988.0,975.27,982.01,3434077.0
-2017-08-08,994.35,996.28,985.79,989.84,2847527.0,0.0,1.0,994.35,996.28,985.79,989.84,2847527.0
-2017-08-04,989.68,991.672,982.0,987.58,2704026.0,0.0,1.0,989.68,991.672,982.0,987.58,2704026.0
-2017-08-03,999.47,999.5,984.59,986.92,3203134.0,0.0,1.0,999.47,999.5,984.59,986.92,3203134.0
-2017-08-02,1001.77,1003.21,981.73,995.89,4017780.0,0.0,1.0,1001.77,1003.21,981.73,995.89,4017780.0
-2017-08-01,996.11,1006.4,991.58,996.19,4421395.0,0.0,1.0,996.11,1006.4,991.58,996.19,4421395.0
-2017-07-31,1019.05,1019.05,987.02,987.78,7246638.0,0.0,1.0,1019.05,1019.05,987.02,987.78,7246638.0
-2017-07-28,1012.14,1032.85,1001.0,1020.04,7624498.0,0.0,1.0,1012.14,1032.85,1001.0,1020.04,7624498.0
-2017-07-27,1069.55,1083.31,1040.18,1046.0,9905158.0,0.0,1.0,1069.55,1083.31,1040.18,1046.0,9905158.0
-2017-07-26,1043.2,1053.2,1043.2,1052.8,2828980.0,0.0,1.0,1043.2,1053.2,1043.2,1052.8,2828980.0
-2017-07-25,1038.05,1043.33,1032.48,1039.87,2432328.0,0.0,1.0,1038.05,1043.33,1032.48,1039.87,2432328.0
-2017-07-24,1028.34,1043.01,1027.43,1038.95,3212499.0,0.0,1.0,1028.34,1043.01,1027.43,1038.95,3212499.0
-2017-07-21,1021.28,1026.1,1011.0,1025.67,2677517.0,0.0,1.0,1021.28,1026.1,1011.0,1025.67,2677517.0
-2017-07-20,1031.59,1034.97,1022.52,1028.7,2964341.0,0.0,1.0,1031.59,1034.97,1022.52,1028.7,2964341.0
-2017-07-19,1025.0,1031.59,1022.5,1026.87,2936902.0,0.0,1.0,1025.0,1031.59,1022.5,1026.87,2936902.0
-2017-07-18,1006.0,1026.03,1004.0,1024.38,3957892.0,0.0,1.0,1006.0,1026.03,1004.0,1024.38,3957892.0
-2017-07-17,1004.69,1014.75,1003.81,1010.04,3636801.0,0.0,1.0,1004.69,1014.75,1003.81,1010.04,3636801.0
-2017-07-14,1002.4,1004.45,996.89,1001.81,2066362.0,0.0,1.0,1002.4,1004.45,996.89,1001.81,2066362.0
-2017-07-13,1004.62,1006.88,995.9,999.855,2864533.0,0.0,1.0,1004.62,1006.88,995.9,999.855,2864533.0
-2017-07-12,1000.65,1008.55,998.1,1006.51,3491988.0,0.0,1.0,1000.65,1008.55,998.1,1006.51,3491988.0
-2017-07-11,993.0,995.99,983.72,994.13,2947479.0,0.0,1.0,993.0,995.99,983.72,994.13,2947479.0
-2017-07-10,985.0,999.4392,983.5,996.47,3462884.0,0.0,1.0,985.0,999.4392,983.5,996.47,3462884.0
-2017-07-07,969.55,980.11,969.14,978.76,2582645.0,0.0,1.0,969.55,980.11,969.14,978.76,2582645.0
-2017-07-06,964.66,974.4,959.02,965.14,3229378.0,0.0,1.0,964.66,974.4,959.02,965.14,3229378.0
-2017-07-05,961.53,975.0,955.25,971.4,3587645.0,0.0,1.0,961.53,975.0,955.25,971.4,3587645.0
-2017-07-03,972.79,974.49,951.0001,953.66,2908267.0,0.0,1.0,972.79,974.49,951.0001,953.66,2908267.0
-2017-06-30,980.12,983.47,967.61,968.0,3309138.0,0.0,1.0,980.12,983.47,967.61,968.0,3309138.0
-2017-06-29,979.0,987.56,965.25,975.93,4246765.0,0.0,1.0,979.0,987.56,965.25,975.93,4246765.0
-2017-06-28,978.55,990.68,969.21,990.33,3708638.0,0.0,1.0,978.55,990.68,969.21,990.33,3708638.0
-2017-06-27,990.69,998.8,976.0,976.78,3735360.0,0.0,1.0,990.69,998.8,976.0,976.78,3735360.0
-2017-06-26,1008.5,1009.8,992.0,993.98,3347195.0,0.0,1.0,1008.5,1009.8,992.0,993.98,3347195.0
-2017-06-23,1002.54,1004.62,998.02,1003.74,2645973.0,0.0,1.0,1002.54,1004.62,998.02,1003.74,2645973.0
-2017-06-22,1002.23,1006.96,997.2,1001.3,2221035.0,0.0,1.0,1002.23,1006.96,997.2,1001.3,2221035.0
-2017-06-21,998.7,1002.72,992.6518,1002.23,2892563.0,0.0,1.0,998.7,1002.72,992.6518,1002.23,2892563.0
-2017-06-20,998.0,1004.88,992.02,992.59,4040990.0,0.0,1.0,998.0,1004.88,992.02,992.59,4040990.0
-2017-06-19,1017.0,1017.0,989.9,995.17,4967600.0,0.0,1.0,1017.0,1017.0,989.9,995.17,4967600.0
-2017-06-16,996.0,999.75,982.0,987.71,11314754.0,0.0,1.0,996.0,999.75,982.0,987.71,11314754.0
-2017-06-15,958.7,965.73,950.86,964.17,5202147.0,0.0,1.0,958.7,965.73,950.86,964.17,5202147.0
-2017-06-14,988.59,990.34,966.71,976.47,3943670.0,0.0,1.0,988.59,990.34,966.71,976.47,3943670.0
-2017-06-13,977.99,984.5,966.1,980.79,4533933.0,0.0,1.0,977.99,984.5,966.1,980.79,4533933.0
-2017-06-12,967.0,975.95,945.0,964.83,9393802.0,0.0,1.0,967.0,975.95,945.0,964.83,9393802.0
-2017-06-09,1012.5,1012.99,927.0,978.31,7548854.0,0.0,1.0,1012.5,1012.99,927.0,978.31,7548854.0
-2017-06-08,1012.06,1013.61,1006.11,1009.94,2724408.0,0.0,1.0,1012.06,1013.61,1006.11,1009.94,2724408.0
-2017-06-07,1005.95,1010.25,1002.0,1010.07,2779551.0,0.0,1.0,1005.95,1010.25,1002.0,1010.07,2779551.0
-2017-06-06,1012.0,1016.5,1001.25,1002.97,3298378.0,0.0,1.0,1012.0,1016.5,1001.25,1002.97,3298378.0
-2017-06-05,1007.23,1013.21,1003.51,1011.34,2676857.0,0.0,1.0,1007.23,1013.21,1003.51,1011.34,2676857.0
-2017-06-02,998.99,1008.48,995.67,1006.73,3714954.0,0.0,1.0,998.99,1008.48,995.67,1006.73,3714954.0
-2017-06-01,998.59,998.99,991.37,995.95,2384298.0,0.0,1.0,998.59,998.99,991.37,995.95,2384298.0
diff --git a/examples/quick/demos/stocqt/content/data/CSCO.csv b/examples/quick/demos/stocqt/content/data/CSCO.csv
deleted file mode 100644
index 0c4b9b05c9..0000000000
--- a/examples/quick/demos/stocqt/content/data/CSCO.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,38.41,38.62,38.3,38.3,12359455.0,0.0,1.0,38.41,38.62,38.3,38.3,12359455.0
-2017-12-28,38.73,38.73,38.45,38.59,8662664.0,0.0,1.0,38.73,38.73,38.45,38.59,8662664.0
-2017-12-27,38.54,38.65,38.45,38.56,10262927.0,0.0,1.0,38.54,38.65,38.45,38.56,10262927.0
-2017-12-26,38.55,38.68,38.36,38.48,8148042.0,0.0,1.0,38.55,38.68,38.36,38.48,8148042.0
-2017-12-22,38.52,38.74,38.47,38.55,11120656.0,0.0,1.0,38.52,38.74,38.47,38.55,11120656.0
-2017-12-21,38.88,38.995,38.49,38.53,16188471.0,0.0,1.0,38.88,38.995,38.49,38.53,16188471.0
-2017-12-20,38.49,38.8,38.21,38.74,18701741.0,0.0,1.0,38.49,38.8,38.21,38.74,18701741.0
-2017-12-19,38.66,38.86,38.28,38.3,18478762.0,0.0,1.0,38.66,38.86,38.28,38.3,18478762.0
-2017-12-18,38.48,38.89,38.3,38.48,21036306.0,0.0,1.0,38.48,38.89,38.3,38.48,21036306.0
-2017-12-15,38.01,38.28,37.7,38.19,36491640.0,0.0,1.0,38.01,38.28,37.7,38.19,36491640.0
-2017-12-14,38.2,38.27,37.855,37.9,16556403.0,0.0,1.0,38.2,38.27,37.855,37.9,16556403.0
-2017-12-13,38.09,38.37,38.0,38.15,19934529.0,0.0,1.0,38.09,38.37,38.0,38.15,19934529.0
-2017-12-12,37.79,38.1,37.56,37.91,16451320.0,0.0,1.0,37.79,38.1,37.56,37.91,16451320.0
-2017-12-11,37.59,38.04,37.57,37.96,15619388.0,0.0,1.0,37.59,38.04,37.57,37.96,15619388.0
-2017-12-08,37.59,37.69,37.42,37.61,13777371.0,0.0,1.0,37.59,37.69,37.42,37.61,13777371.0
-2017-12-07,37.26,37.78,37.26,37.4,15189086.0,0.0,1.0,37.26,37.78,37.26,37.4,15189086.0
-2017-12-06,37.37,37.72,37.25,37.41,16312845.0,0.0,1.0,37.37,37.72,37.25,37.41,16312845.0
-2017-12-05,37.74,37.82,37.17,37.31,22743474.0,0.0,1.0,37.74,37.82,37.17,37.31,22743474.0
-2017-12-04,37.81,37.99,37.54,37.72,29006129.0,0.0,1.0,37.81,37.99,37.54,37.72,29006129.0
-2017-12-01,37.09,37.66,36.73,37.6,26851147.0,0.0,1.0,37.09,37.66,36.73,37.6,26851147.0
-2017-11-30,37.62,37.8,37.3,37.3,28692862.0,0.0,1.0,37.62,37.8,37.3,37.3,28692862.0
-2017-11-29,37.75,38.025,37.23,37.48,36640805.0,0.0,1.0,37.75,38.025,37.23,37.48,36640805.0
-2017-11-28,37.0,37.8,36.98,37.73,30097816.0,0.0,1.0,37.0,37.8,36.98,37.73,30097816.0
-2017-11-27,36.51,37.09,36.5,36.87,20667352.0,0.0,1.0,36.51,37.09,36.5,36.87,20667352.0
-2017-11-24,36.41,36.57,36.32,36.49,6155294.0,0.0,1.0,36.41,36.57,36.32,36.49,6155294.0
-2017-11-22,36.7,36.715,36.36,36.45,16650130.0,0.0,1.0,36.7,36.715,36.36,36.45,16650130.0
-2017-11-21,36.75,36.97,36.58,36.65,23986203.0,0.0,1.0,36.75,36.97,36.58,36.65,23986203.0
-2017-11-20,35.93,36.54,35.93,36.5,26376364.0,0.0,1.0,35.93,36.54,35.93,36.5,26376364.0
-2017-11-17,35.9,36.32,35.81,35.9,27106406.0,0.0,1.0,35.9,36.32,35.81,35.9,27106406.0
-2017-11-16,36.04,36.67,35.83,35.88,59861205.0,0.0,1.0,36.04,36.67,35.83,35.88,59861205.0
-2017-11-15,33.97,34.31,33.75,34.11,27797071.0,0.0,1.0,33.97,34.31,33.75,34.11,27797071.0
-2017-11-14,33.86,34.16,33.8,34.04,15540925.0,0.0,1.0,33.86,34.16,33.8,34.04,15540925.0
-2017-11-13,33.86,34.21,33.83,33.95,15608341.0,0.0,1.0,33.86,34.21,33.83,33.95,15608341.0
-2017-11-10,34.06,34.09,33.67,33.99,19003147.0,0.0,1.0,34.06,34.09,33.67,33.99,19003147.0
-2017-11-09,34.29,34.32,33.871,34.05,16266161.0,0.0,1.0,34.29,34.32,33.871,34.05,16266161.0
-2017-11-07,34.32,34.48,34.2147,34.4,10980008.0,0.0,1.0,34.32,34.48,34.2147,34.4,10980008.0
-2017-11-06,34.37,34.56,34.26,34.41,12725467.0,0.0,1.0,34.37,34.56,34.26,34.41,12725467.0
-2017-11-03,34.28,34.49,34.0269,34.47,13293171.0,0.0,1.0,34.28,34.49,34.0269,34.47,13293171.0
-2017-11-02,34.55,34.64,34.16,34.21,19647242.0,0.0,1.0,34.55,34.64,34.16,34.21,19647242.0
-2017-11-01,34.29,34.75,34.28,34.62,21831973.0,0.0,1.0,34.29,34.75,34.28,34.62,21831973.0
-2017-10-31,33.98,34.24,33.96,34.15,13544441.0,0.0,1.0,33.98,34.24,33.96,34.15,13544441.0
-2017-10-30,34.32,34.38,33.8244,34.04,18241531.0,0.0,1.0,34.32,34.38,33.8244,34.04,18241531.0
-2017-10-27,34.15,34.62,34.09,34.43,20237956.0,0.0,1.0,34.15,34.62,34.09,34.43,20237956.0
-2017-10-26,34.41,34.51,34.07,34.27,14541155.0,0.0,1.0,34.41,34.51,34.07,34.27,14541155.0
-2017-10-25,34.73,34.73,34.163,34.3,17012218.0,0.0,1.0,34.73,34.73,34.163,34.3,17012218.0
-2017-10-24,34.4,34.675,34.25,34.58,15273905.0,0.0,1.0,34.4,34.675,34.25,34.58,15273905.0
-2017-10-23,34.45,34.68,34.27,34.35,22490134.0,0.0,1.0,34.45,34.68,34.27,34.35,22490134.0
-2017-10-20,34.02,34.39,34.01,34.25,24055347.0,0.0,1.0,34.02,34.39,34.01,34.25,24055347.0
-2017-10-19,33.51,33.89,33.45,33.75,12928532.0,0.0,1.0,33.51,33.89,33.45,33.75,12928532.0
-2017-10-18,33.72,33.75,33.44,33.55,9739887.0,0.0,1.0,33.72,33.75,33.44,33.55,9739887.0
-2017-10-17,33.59,33.67,33.46,33.6,8633089.0,0.0,1.0,33.59,33.67,33.46,33.6,8633089.0
-2017-10-16,33.6,33.64,33.47,33.54,10469019.0,0.0,1.0,33.6,33.64,33.47,33.54,10469019.0
-2017-10-13,33.4,33.57,33.323,33.47,13451108.0,0.0,1.0,33.4,33.57,33.323,33.47,13451108.0
-2017-10-12,33.26,33.46,33.17,33.26,17811160.0,0.0,1.0,33.26,33.46,33.17,33.26,17811160.0
-2017-10-11,33.38,33.63,33.25,33.59,12353462.0,0.0,1.0,33.38,33.63,33.25,33.59,12353462.0
-2017-10-10,33.88,33.91,33.47,33.55,17978700.0,0.0,1.0,33.88,33.91,33.47,33.55,17978700.0
-2017-10-09,33.77,33.89,33.61,33.76,8684822.0,0.0,1.0,33.77,33.89,33.61,33.76,8684822.0
-2017-10-06,33.65,33.78,33.5247,33.75,13438950.0,0.0,1.0,33.65,33.78,33.5247,33.75,13438950.0
-2017-10-05,33.58,33.67,33.41,33.59,14301206.0,0.0,1.0,33.58,33.67,33.41,33.59,14301206.0
-2017-10-04,33.53,33.56,33.29,33.44,14606016.0,0.29,1.0,33.53,33.56,33.29,33.44,14606016.0
-2017-10-03,33.72,33.9,33.61,33.85,13159079.0,0.0,1.0,33.430085976875,33.608538393122,33.321031722502,33.558968277498,13159079.0
-2017-10-02,33.61,33.77,33.52,33.75,16443224.0,0.0,1.0,33.321031722502,33.479656092499,33.231805514379,33.45982804625,16443224.0
-2017-09-29,33.31,33.67,33.24,33.63,14419404.0,0.0,1.0,33.023611028758,33.380515861251,32.954212866884,33.340859768752,14419404.0
-2017-09-28,33.22,33.46,33.22,33.35,14689819.0,0.0,1.0,32.934384820634,33.17232137563,32.934384820634,33.063267121257,14689819.0
-2017-09-27,33.78,33.92,33.3037,33.48,21687593.0,0.0,1.0,33.489570115624,33.628366439371,33.017365194189,33.19214942188,21687593.0
-2017-09-26,33.76,34.1,33.67,33.76,25835270.0,0.0,1.0,33.469742069374,33.806818855618,33.380515861251,33.469742069374,25835270.0
-2017-09-25,33.31,33.84,33.2,33.72,30475969.0,0.0,1.0,33.023611028758,33.549054254373,32.914556774385,33.430085976875,30475969.0
-2017-09-22,32.66,33.53,32.64,33.37,27904695.0,0.0,1.0,32.379199525645,33.241719537504,32.359371479395,33.083095167507,27904695.0
-2017-09-21,32.72,32.9,32.5,32.7,19762651.0,0.0,1.0,32.438683664394,32.61713608064,32.220575155648,32.418855618144,19762651.0
-2017-09-20,32.55,32.75,32.39,32.6,18701702.0,0.0,1.0,32.270145271272,32.468425733768,32.111520901275,32.319715386896,18701702.0
-2017-09-19,32.46,32.65,32.395,32.49,12424056.0,0.0,1.0,32.180919063149,32.36928550252,32.116477912837,32.210661132523,12424056.0
-2017-09-18,32.43,32.66,32.26,32.52,17035443.0,0.0,1.0,32.151176993774,32.379199525645,31.982638600652,32.240403201897,17035443.0
-2017-09-15,32.2,32.5,32.12,32.44,27708447.0,0.0,1.0,31.923154461903,32.220575155648,31.843842276905,32.161091016899,27708447.0
-2017-09-14,31.91,32.22,31.91,32.19,17711003.0,0.0,1.0,31.635647791284,31.942982508153,31.635647791284,31.913240438779,17711003.0
-2017-09-13,32.34,32.39,31.96,32.18,21872095.0,0.0,1.0,32.061950785651,32.111520901275,31.685217906908,31.903326415654,21872095.0
-2017-09-12,32.3,32.47,32.19,32.41,18510454.0,0.0,1.0,32.022294693151,32.190833086273,31.913240438779,32.131348947524,18510454.0
-2017-09-11,31.71,32.3,31.67,32.205,21365590.0,0.0,1.0,31.437367328787,32.022294693151,31.397711236288,31.928111473466,21365590.0
-2017-09-08,31.68,31.78,31.46,31.48,15115756.0,0.0,1.0,31.407625259413,31.506765490661,31.189516750667,31.209344796917,15115756.0
-2017-09-07,31.96,31.97,31.74,31.76,14611809.0,0.0,1.0,31.685217906908,31.695131930033,31.467109398162,31.486937444412,14611809.0
-2017-09-06,31.75,31.91,31.63,31.87,16380030.0,0.0,1.0,31.477023421287,31.635647791284,31.358055143789,31.595991698784,16380030.0
-2017-09-05,32.15,32.245,31.455,31.62,24327663.0,0.0,1.0,31.873584346279,31.967767565965,31.184559739105,31.348141120664,24327663.0
-2017-09-01,32.22,32.345,32.03,32.32,14661162.0,0.0,1.0,31.942982508153,32.066907797213,31.754616068782,32.042122739401,14661162.0
-2017-08-31,32.1,32.34,31.99,32.21,27138172.0,0.0,1.0,31.824014230655,32.061950785651,31.714959976282,31.933068485028,27138172.0
-2017-08-30,31.47,32.2,31.42,31.99,23028578.0,0.0,1.0,31.199430773792,31.923154461903,31.149860658168,31.714959976282,23028578.0
-2017-08-29,31.26,31.6299,31.19,31.48,16192694.0,0.0,1.0,30.991236288171,31.357956003558,30.921838126297,31.209344796917,16192694.0
-2017-08-28,31.6,31.66,31.41,31.54,12747867.0,0.0,1.0,31.328313074414,31.387797213163,31.139946635043,31.268828935666,12747867.0
-2017-08-25,31.39,31.8,31.36,31.44,19351094.0,0.0,1.0,31.120118588793,31.526593536911,31.090376519419,31.169688704417,19351094.0
-2017-08-24,30.95,31.4,30.9,31.24,21867401.0,0.0,1.0,30.683901571302,31.130032611918,30.634331455677,30.971408241921,21867401.0
-2017-08-23,31.21,31.4,30.91,30.92,22269978.0,0.0,1.0,30.941666172547,31.130032611918,30.644245478802,30.654159501927,22269978.0
-2017-08-22,30.85,31.33,30.75,31.27,24438367.0,0.0,1.0,30.584761340053,31.060634450044,30.485621108805,31.001150311296,24438367.0
-2017-08-21,30.37,30.795,30.36,30.68,24025228.0,0.0,1.0,30.108888230062,30.530234212867,30.098974206937,30.416222946932,24025228.0
-2017-08-18,31.0,31.06,30.36,30.37,34622147.0,0.0,1.0,30.733471686926,30.792955825674,30.098974206937,30.108888230062,34622147.0
-2017-08-17,31.49,31.77,30.85,31.04,51557052.0,0.0,1.0,31.219258820042,31.496851467536,30.584761340053,30.773127779425,51557052.0
-2017-08-16,32.1,32.4652,32.06,32.34,27088237.0,0.0,1.0,31.824014230655,32.186074355173,31.784358138156,32.061950785651,27088237.0
-2017-08-15,31.85,32.21,31.84,32.09,24406258.0,0.0,1.0,31.576163652535,31.933068485028,31.56624962941,31.81410020753,24406258.0
-2017-08-14,31.69,31.89,31.56,31.84,21605411.0,0.0,1.0,31.417539282538,31.615819745034,31.288656981915,31.56624962941,21605411.0
-2017-08-11,31.23,31.545,31.04,31.47,20521935.0,0.0,1.0,30.961494218796,31.273785947228,30.773127779425,31.199430773792,20521935.0
-2017-08-10,31.56,31.56,31.0,31.0,22748854.0,0.0,1.0,31.288656981915,31.288656981915,30.733471686926,30.733471686926,22748854.0
-2017-08-09,31.55,31.675,31.36,31.62,15931711.0,0.0,1.0,31.27874295879,31.402668247851,31.090376519419,31.348141120664,15931711.0
-2017-08-08,31.75,32.0,31.6,31.67,13632423.0,0.0,1.0,31.477023421287,31.724873999407,31.328313074414,31.397711236288,13632423.0
-2017-08-07,31.79,31.8799,31.69,31.84,11730203.0,0.0,1.0,31.516679513786,31.605806581678,31.417539282538,31.56624962941,11730203.0
-2017-08-04,31.67,31.91,31.58,31.8,16322686.0,0.0,1.0,31.397711236288,31.635647791284,31.308485028165,31.526593536911,16322686.0
-2017-08-03,31.59,31.72,31.43,31.56,13884046.0,0.0,1.0,31.31839905129,31.447281351912,31.159774681293,31.288656981915,13884046.0
-2017-08-02,31.57,31.57,31.25,31.52,15797711.0,0.0,1.0,31.29857100504,31.29857100504,30.981322265046,31.249000889416,15797711.0
-2017-08-01,31.59,31.66,31.43,31.65,12727298.0,0.0,1.0,31.31839905129,31.387797213163,31.159774681293,31.377883190039,12727298.0
-2017-07-31,31.54,31.59,31.37,31.45,18534978.0,0.0,1.0,31.268828935666,31.31839905129,31.100290542544,31.179602727542,18534978.0
-2017-07-28,31.45,31.6,31.26,31.52,15509841.0,0.0,1.0,31.179602727542,31.328313074414,30.991236288171,31.249000889416,15509841.0
-2017-07-27,31.73,31.7502,31.21,31.57,21224338.0,0.0,1.0,31.457195375037,31.477221701749,30.941666172547,31.29857100504,21224338.0
-2017-07-26,32.12,32.225,31.51,31.66,21472799.0,0.0,1.0,31.843842276905,31.947939519715,31.239086866291,31.387797213163,21472799.0
-2017-07-25,31.9,32.25,31.88,32.12,14848920.0,0.0,1.0,31.625733768159,31.972724577527,31.605905721909,31.843842276905,14848920.0
-2017-07-24,31.86,31.925,31.66,31.86,15232167.0,0.0,1.0,31.58607767566,31.650518825971,31.387797213163,31.58607767566,15232167.0
-2017-07-21,31.86,32.03,31.705,31.84,13271427.0,0.0,1.0,31.58607767566,31.754616068782,31.432410317225,31.56624962941,13271427.0
-2017-07-20,31.91,32.05,31.76,31.86,15917114.0,0.0,1.0,31.635647791284,31.774444115031,31.486937444412,31.58607767566,15917114.0
-2017-07-19,31.51,32.05,31.46,31.9,21369697.0,0.0,1.0,31.239086866291,31.774444115031,31.189516750667,31.625733768159,21369697.0
-2017-07-18,31.41,31.51,31.17,31.51,15366450.0,0.0,1.0,31.139946635043,31.239086866291,30.902010080047,31.239086866291,15366450.0
-2017-07-17,31.5,31.635,31.45,31.5,16012951.0,0.0,1.0,31.229172843166,31.363012155351,31.179602727542,31.229172843166,16012951.0
-2017-07-14,31.37,31.45,31.27,31.42,13261554.0,0.0,1.0,31.100290542544,31.179602727542,31.001150311296,31.149860658168,13261554.0
-2017-07-13,31.26,31.28,31.08,31.27,15870454.0,0.0,1.0,30.991236288171,31.01106433442,30.812783871924,31.001150311296,15870454.0
-2017-07-12,31.25,31.44,31.145,31.16,18428809.0,0.0,1.0,30.981322265046,31.169688704417,30.877225022235,30.892096056923,18428809.0
-2017-07-11,31.05,31.12,30.86,31.09,12253478.0,0.0,1.0,30.78304180255,30.852439964423,30.594675363178,30.822697895049,12253478.0
-2017-07-10,30.88,31.09,30.82,30.98,15193572.0,0.0,1.0,30.614503409428,30.822697895049,30.555019270679,30.713643640676,15193572.0
-2017-07-07,30.76,31.07,30.75,30.9,15221015.0,0.0,1.0,30.49553513193,30.802869848799,30.485621108805,30.634331455677,15221015.0
-2017-07-06,30.99,31.02,30.67,30.725,20456451.0,0.0,1.0,30.723557663801,30.753299733175,30.406308923807,30.460836050993,20456451.0
-2017-07-05,30.85,31.27,30.73,31.11,23391894.0,0.29,1.0,30.584761340053,31.001150311296,30.465793062556,30.842525941299,23391894.0
-2017-07-03,31.09,31.64,31.03,31.33,14111474.0,0.0,1.0,30.538029666082,31.078264993079,30.479094903137,30.773768717863,14111474.0
-2017-06-30,31.79,31.79,31.3,31.3,22981379.0,0.0,1.0,31.225601900442,31.225601900442,30.74430133639,30.74430133639,22981379.0
-2017-06-29,31.79,32.025,31.25,31.41,26891695.0,0.0,1.0,31.225601900442,31.456429721977,30.695189033936,30.852348401789,26891695.0
-2017-06-28,31.78,32.275,31.76,32.08,17587686.0,0.0,1.0,31.215779439951,31.701991234249,31.196134518969,31.510453254677,17587686.0
-2017-06-27,32.09,32.26,31.76,31.76,23092594.0,0.0,1.0,31.520275715168,31.687257543512,31.196134518969,31.196134518969,23092594.0
-2017-06-26,32.22,32.5,32.18,32.24,21409287.0,0.0,1.0,31.647967701549,31.922996595293,31.608677859586,31.667612622531,21409287.0
-2017-06-23,31.85,32.3,31.75,32.1,23006424.0,0.0,1.0,31.284536663387,31.726547385476,31.186312058479,31.530098175659,23006424.0
-2017-06-22,31.91,32.0,31.7,31.85,19194637.0,0.0,1.0,31.343471426332,31.43187357075,31.137199756024,31.284536663387,19194637.0
-2017-06-21,31.73,31.87,31.51,31.84,20103067.0,0.0,1.0,31.166667137497,31.304181584369,30.950573006698,31.274714202896,20103067.0
-2017-06-20,31.94,32.16,31.84,31.85,17859664.0,0.0,1.0,31.372938807805,31.589032938604,31.274714202896,31.284536663387,17859664.0
-2017-06-19,31.77,32.02,31.581,31.99,16753701.0,0.0,1.0,31.20595697946,31.451518491732,31.020312476183,31.422051110259,16753701.0
-2017-06-16,31.61,31.64,31.2,31.6201,33785850.0,0.0,1.0,31.048797611607,31.078264993079,30.646076731481,31.058718296702,33785850.0
-2017-06-15,31.25,31.64,31.22,31.5801,19110962.0,0.0,1.0,30.695189033936,31.078264993079,30.665721652463,31.019428454739,19110962.0
-2017-06-14,31.87,31.97,31.33,31.6,24850713.0,0.0,1.0,31.304181584369,31.402406189278,30.773768717863,31.038975151116,24850713.0
-2017-06-13,31.3,31.8,31.28,31.7,27251001.0,0.0,1.0,30.74430133639,31.235424360933,30.724656415408,31.137199756024,27251001.0
-2017-06-12,31.34,31.64,31.15,31.245,24330382.0,0.0,1.0,30.783591178353,31.078264993079,30.596964429027,30.69027780369,24330382.0
-2017-06-09,31.64,31.83,31.085,31.37,25031675.0,0.0,1.0,31.078264993079,31.264891742406,30.533118435836,30.813058559826,25031675.0
-2017-06-08,31.53,31.81,31.52,31.615,19877271.0,0.0,1.0,30.97021792768,31.245246821424,30.960395467189,31.053708841852,19877271.0
-2017-06-07,31.61,31.72,31.44,31.61,14417549.0,0.0,1.0,31.048797611607,31.156844677006,30.881815783262,31.048797611607,14417549.0
-2017-06-06,31.75,31.76,31.5,31.56,15987734.0,0.0,1.0,31.186312058479,31.196134518969,30.940750546207,30.999685309152,15987734.0
-2017-06-05,32.05,32.05,31.57,31.76,15581429.0,0.0,1.0,31.480985873204,31.480985873204,31.009507769643,31.196134518969,15581429.0
-2017-06-02,31.93,32.06,31.68,31.98,19978713.0,0.0,1.0,31.363116347314,31.490808333695,31.117554835043,31.412228649768,19978713.0
-2017-06-01,31.52,31.82,31.47,31.82,15397418.0,0.0,1.0,30.960395467189,31.255069281915,30.911283164735,31.255069281915,15397418.0
diff --git a/examples/quick/demos/stocqt/content/data/EA.csv b/examples/quick/demos/stocqt/content/data/EA.csv
deleted file mode 100644
index ad6a60fc7b..0000000000
--- a/examples/quick/demos/stocqt/content/data/EA.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,105.29,105.68,104.39,105.06,2033331.0,0.0,1.0,105.29,105.68,104.39,105.06,2033331.0
-2017-12-28,105.29,105.55,104.55,105.31,1431096.0,0.0,1.0,105.29,105.55,104.55,105.31,1431096.0
-2017-12-27,105.4,106.44,104.58,105.23,2427713.0,0.0,1.0,105.4,106.44,104.58,105.23,2427713.0
-2017-12-26,105.66,106.02,104.65,105.06,1685265.0,0.0,1.0,105.66,106.02,104.65,105.06,1685265.0
-2017-12-22,108.31,108.31,105.675,106.02,2401349.0,0.0,1.0,108.31,108.31,105.675,106.02,2401349.0
-2017-12-21,107.88,108.735,107.78,107.97,2784216.0,0.0,1.0,107.88,108.735,107.78,107.97,2784216.0
-2017-12-20,107.5,108.87,107.15,108.45,2642416.0,0.0,1.0,107.5,108.87,107.15,108.45,2642416.0
-2017-12-19,107.42,107.7558,106.69,107.0,1985332.0,0.0,1.0,107.42,107.7558,106.69,107.0,1985332.0
-2017-12-18,109.89,110.0,106.56,107.34,4241871.0,0.0,1.0,109.89,110.0,106.56,107.34,4241871.0
-2017-12-15,107.77,109.68,106.63,109.28,5755867.0,0.0,1.0,107.77,109.68,106.63,109.28,5755867.0
-2017-12-14,105.2,107.62,104.7,106.42,2580582.0,0.0,1.0,105.2,107.62,104.7,106.42,2580582.0
-2017-12-13,107.71,108.31,105.22,105.54,3730504.0,0.0,1.0,107.71,108.31,105.22,105.54,3730504.0
-2017-12-12,108.0,108.92,107.02,107.66,3512468.0,0.0,1.0,108.0,108.92,107.02,107.66,3512468.0
-2017-12-11,105.61,108.16,105.0,107.92,3271833.0,0.0,1.0,105.61,108.16,105.0,107.92,3271833.0
-2017-12-08,104.49,106.4,104.42,105.27,3194502.0,0.0,1.0,104.49,106.4,104.42,105.27,3194502.0
-2017-12-07,103.23,105.6,102.75,104.37,3486643.0,0.0,1.0,103.23,105.6,102.75,104.37,3486643.0
-2017-12-06,102.96,103.92,100.41,103.18,4441608.0,0.0,1.0,102.96,103.92,100.41,103.18,4441608.0
-2017-12-05,100.55,105.1926,99.63,103.38,4454836.0,0.0,1.0,100.55,105.1926,99.63,103.38,4454836.0
-2017-12-04,105.53,105.875,100.68,100.83,6476227.0,0.0,1.0,105.53,105.875,100.68,100.83,6476227.0
-2017-12-01,105.86,106.87,103.95,106.02,3810130.0,0.0,1.0,105.86,106.87,103.95,106.02,3810130.0
-2017-11-30,106.11,106.5,105.06,106.35,5338599.0,0.0,1.0,106.11,106.5,105.06,106.35,5338599.0
-2017-11-29,109.21,109.39,104.95,105.49,5484734.0,0.0,1.0,109.21,109.39,104.95,105.49,5484734.0
-2017-11-28,106.99,110.52,106.74,109.47,5362601.0,0.0,1.0,106.99,110.52,106.74,109.47,5362601.0
-2017-11-27,107.86,108.285,106.79,106.99,2398540.0,0.0,1.0,107.86,108.285,106.79,106.99,2398540.0
-2017-11-24,107.66,108.58,107.59,107.94,1306290.0,0.0,1.0,107.66,108.58,107.59,107.94,1306290.0
-2017-11-22,108.04,108.44,106.61,107.32,2512190.0,0.0,1.0,108.04,108.44,106.61,107.32,2512190.0
-2017-11-21,107.78,108.7699,107.54,107.71,3089096.0,0.0,1.0,107.78,108.7699,107.54,107.71,3089096.0
-2017-11-20,108.28,108.45,106.75,107.64,5948591.0,0.0,1.0,108.28,108.45,106.75,107.64,5948591.0
-2017-11-17,108.99,109.55,107.5,108.82,8476713.0,0.0,1.0,108.99,109.55,107.5,108.82,8476713.0
-2017-11-16,111.85,113.13,111.21,111.6,2308873.0,0.0,1.0,111.85,113.13,111.21,111.6,2308873.0
-2017-11-15,112.72,112.87,110.52,111.48,2483272.0,0.0,1.0,112.72,112.87,110.52,111.48,2483272.0
-2017-11-14,110.6,113.9,110.39,112.27,3554816.0,0.0,1.0,110.6,113.9,110.39,112.27,3554816.0
-2017-11-13,112.0,113.24,111.19,112.01,3157879.0,0.0,1.0,112.0,113.24,111.19,112.01,3157879.0
-2017-11-10,111.26,112.83,110.82,112.75,2515313.0,0.0,1.0,111.26,112.83,110.82,112.75,2515313.0
-2017-11-09,112.99,113.3,110.94,111.89,3331403.0,0.0,1.0,112.99,113.3,110.94,111.89,3331403.0
-2017-11-07,112.29,112.72,110.08,111.7,2671700.0,0.0,1.0,112.29,112.72,110.08,111.7,2671700.0
-2017-11-06,112.99,113.5,110.76,112.46,3571671.0,0.0,1.0,112.99,113.5,110.76,112.46,3571671.0
-2017-11-03,113.47,113.76,112.57,113.2,2859092.0,0.0,1.0,113.47,113.76,112.57,113.2,2859092.0
-2017-11-02,114.35,114.52,112.6,112.69,3405672.0,0.0,1.0,114.35,114.52,112.6,112.69,3405672.0
-2017-11-01,116.0,116.6,111.28,114.47,9639100.0,0.0,1.0,116.0,116.6,111.28,114.47,9639100.0
-2017-10-31,118.125,119.84,116.37,119.6,4762517.0,0.0,1.0,118.125,119.84,116.37,119.6,4762517.0
-2017-10-30,117.13,117.77,116.64,117.58,2599653.0,0.0,1.0,117.13,117.77,116.64,117.58,2599653.0
-2017-10-27,116.83,117.55,115.41,116.89,2883562.0,0.0,1.0,116.83,117.55,115.41,116.89,2883562.0
-2017-10-26,115.07,117.06,115.02,115.83,2443955.0,0.0,1.0,115.07,117.06,115.02,115.83,2443955.0
-2017-10-25,113.2,114.88,112.59,114.56,2963441.0,0.0,1.0,113.2,114.88,112.59,114.56,2963441.0
-2017-10-24,113.68,114.72,112.763,113.39,1847039.0,0.0,1.0,113.68,114.72,112.763,113.39,1847039.0
-2017-10-23,113.81,114.43,112.73,113.68,2060904.0,0.0,1.0,113.81,114.43,112.73,113.68,2060904.0
-2017-10-20,113.6,114.28,113.15,113.62,1921562.0,0.0,1.0,113.6,114.28,113.15,113.62,1921562.0
-2017-10-19,112.0,113.08,111.12,113.07,3023265.0,0.0,1.0,112.0,113.08,111.12,113.07,3023265.0
-2017-10-18,113.41,113.75,110.31,113.16,9671971.0,0.0,1.0,113.41,113.75,110.31,113.16,9671971.0
-2017-10-17,117.2,118.15,115.63,115.98,3116041.0,0.0,1.0,117.2,118.15,115.63,115.98,3116041.0
-2017-10-16,118.81,119.0,117.05,117.48,2581184.0,0.0,1.0,118.81,119.0,117.05,117.48,2581184.0
-2017-10-13,117.76,118.92,117.55,118.62,1883150.0,0.0,1.0,117.76,118.92,117.55,118.62,1883150.0
-2017-10-12,115.97,117.78,115.7701,117.14,2031131.0,0.0,1.0,115.97,117.78,115.7701,117.14,2031131.0
-2017-10-11,117.33,118.0,115.52,116.05,2917782.0,0.0,1.0,117.33,118.0,115.52,116.05,2917782.0
-2017-10-10,119.03,119.49,116.71,117.82,1511975.0,0.0,1.0,119.03,119.49,116.71,117.82,1511975.0
-2017-10-09,119.24,119.3,117.67,118.62,1513237.0,0.0,1.0,119.24,119.3,117.67,118.62,1513237.0
-2017-10-06,119.03,120.29,118.44,120.09,1503375.0,0.0,1.0,119.03,120.29,118.44,120.09,1503375.0
-2017-10-05,118.63,119.75,117.93,119.52,1430493.0,0.0,1.0,118.63,119.75,117.93,119.52,1430493.0
-2017-10-04,117.52,118.75,116.41,118.56,1587004.0,0.0,1.0,117.52,118.75,116.41,118.56,1587004.0
-2017-10-03,117.92,118.1,116.76,117.96,1227392.0,0.0,1.0,117.92,118.1,116.76,117.96,1227392.0
-2017-10-02,118.89,119.72,116.94,117.95,1822193.0,0.0,1.0,118.89,119.72,116.94,117.95,1822193.0
-2017-09-29,116.71,118.17,116.3,118.06,1730832.0,0.0,1.0,116.71,118.17,116.3,118.06,1730832.0
-2017-09-28,115.82,116.79,115.24,116.61,1395076.0,0.0,1.0,115.82,116.79,115.24,116.61,1395076.0
-2017-09-27,115.4,116.65,115.4,115.97,1728987.0,0.0,1.0,115.4,116.65,115.4,115.97,1728987.0
-2017-09-26,114.5,114.67,112.833,113.92,2886349.0,0.0,1.0,114.5,114.67,112.833,113.92,2886349.0
-2017-09-25,118.05,118.29,112.85,114.2,4019941.0,0.0,1.0,118.05,118.29,112.85,114.2,4019941.0
-2017-09-22,117.46,120.18,117.15,118.5,2074145.0,0.0,1.0,117.46,120.18,117.15,118.5,2074145.0
-2017-09-21,120.49,120.49,117.82,118.02,1857324.0,0.0,1.0,120.49,120.49,117.82,118.02,1857324.0
-2017-09-20,120.77,121.4,118.74,120.34,2290740.0,0.0,1.0,120.77,121.4,118.74,120.34,2290740.0
-2017-09-19,120.25,121.2,119.37,120.21,2147853.0,0.0,1.0,120.25,121.2,119.37,120.21,2147853.0
-2017-09-18,119.5,120.87,119.5,119.96,2562195.0,0.0,1.0,119.5,120.87,119.5,119.96,2562195.0
-2017-09-15,119.29,119.915,117.75,119.42,3161686.0,0.0,1.0,119.29,119.915,117.75,119.42,3161686.0
-2017-09-14,118.74,119.66,117.71,119.19,2453409.0,0.0,1.0,118.74,119.66,117.71,119.19,2453409.0
-2017-09-13,119.86,120.45,119.0,119.6,2468517.0,0.0,1.0,119.86,120.45,119.0,119.6,2468517.0
-2017-09-12,121.61,122.125,118.675,120.41,2568453.0,0.0,1.0,121.61,122.125,118.675,120.41,2568453.0
-2017-09-11,119.88,121.35,119.28,121.19,2184608.0,0.0,1.0,119.88,121.35,119.28,121.19,2184608.0
-2017-09-08,119.99,120.16,117.71,118.28,2334882.0,0.0,1.0,119.99,120.16,117.71,118.28,2334882.0
-2017-09-07,117.2,119.1,116.59,118.93,1717120.0,0.0,1.0,117.2,119.1,116.59,118.93,1717120.0
-2017-09-06,118.77,119.15,116.47,117.0,1711537.0,0.0,1.0,118.77,119.15,116.47,117.0,1711537.0
-2017-09-05,118.8,119.3,116.32,118.21,2269814.0,0.0,1.0,118.8,119.3,116.32,118.21,2269814.0
-2017-09-01,121.27,121.77,118.51,119.31,2696421.0,0.0,1.0,121.27,121.77,118.51,119.31,2696421.0
-2017-08-31,122.0,122.79,120.94,121.5,2580446.0,0.0,1.0,122.0,122.79,120.94,121.5,2580446.0
-2017-08-30,119.42,122.08,119.065,121.97,2097613.0,0.0,1.0,119.42,122.08,119.065,121.97,2097613.0
-2017-08-29,117.47,119.43,117.2201,119.23,1223068.0,0.0,1.0,117.47,119.43,117.2201,119.23,1223068.0
-2017-08-28,117.52,119.04,116.95,118.73,1756217.0,0.0,1.0,117.52,119.04,116.95,118.73,1756217.0
-2017-08-25,118.19,118.71,115.71,116.93,2155476.0,0.0,1.0,118.19,118.71,115.71,116.93,2155476.0
-2017-08-24,118.49,118.92,116.0,117.82,1303354.0,0.0,1.0,118.49,118.92,116.0,117.82,1303354.0
-2017-08-23,118.65,119.37,117.55,118.18,1235965.0,0.0,1.0,118.65,119.37,117.55,118.18,1235965.0
-2017-08-22,117.28,120.45,117.22,119.03,2476188.0,0.0,1.0,117.28,120.45,117.22,119.03,2476188.0
-2017-08-21,116.85,117.4,116.12,116.84,1479440.0,0.0,1.0,116.85,117.4,116.12,116.84,1479440.0
-2017-08-18,116.0,117.84,115.46,116.88,1906661.0,0.0,1.0,116.0,117.84,115.46,116.88,1906661.0
-2017-08-17,119.19,119.4745,116.46,116.47,1755405.0,0.0,1.0,119.19,119.4745,116.46,116.47,1755405.0
-2017-08-16,117.49,119.59,117.03,119.25,2039136.0,0.0,1.0,117.49,119.59,117.03,119.25,2039136.0
-2017-08-15,117.23,117.62,116.58,117.43,1036988.0,0.0,1.0,117.23,117.62,116.58,117.43,1036988.0
-2017-08-14,116.71,118.0,116.4,117.11,2858947.0,0.0,1.0,116.71,118.0,116.4,117.11,2858947.0
-2017-08-11,113.74,115.98,113.51,115.45,1541337.0,0.0,1.0,113.74,115.98,113.51,115.45,1541337.0
-2017-08-10,115.41,115.715,113.69,113.99,2591680.0,0.0,1.0,115.41,115.715,113.69,113.99,2591680.0
-2017-08-09,115.55,116.84,114.75,116.11,1572284.0,0.0,1.0,115.55,116.84,114.75,116.11,1572284.0
-2017-08-08,116.5,117.13,116.02,116.5,1298672.0,0.0,1.0,116.5,117.13,116.02,116.5,1298672.0
-2017-08-07,117.6,117.96,116.49,116.96,1878689.0,0.0,1.0,117.6,117.96,116.49,116.96,1878689.0
-2017-08-04,119.15,119.18,116.9,117.22,2329950.0,0.0,1.0,119.15,119.18,116.9,117.22,2329950.0
-2017-08-03,117.38,119.23,116.98,118.85,2807213.0,0.0,1.0,117.38,119.23,116.98,118.85,2807213.0
-2017-08-02,117.11,117.42,113.83,116.83,3035692.0,0.0,1.0,117.11,117.42,113.83,116.83,3035692.0
-2017-08-01,117.57,117.65,116.44,116.92,2434299.0,0.0,1.0,117.57,117.65,116.44,116.92,2434299.0
-2017-07-31,119.05,119.25,116.5,116.74,2874265.0,0.0,1.0,119.05,119.25,116.5,116.74,2874265.0
-2017-07-28,114.0,118.75,113.5,118.25,4996998.0,0.0,1.0,114.0,118.75,113.5,118.25,4996998.0
-2017-07-27,119.01,120.25,116.06,117.6,8804997.0,0.0,1.0,119.01,120.25,116.06,117.6,8804997.0
-2017-07-26,115.46,118.11,115.19,118.0,4476211.0,0.0,1.0,115.46,118.11,115.19,118.0,4476211.0
-2017-07-25,113.97,114.52,113.31,113.66,2731441.0,0.0,1.0,113.97,114.52,113.31,113.66,2731441.0
-2017-07-24,112.22,113.97,112.22,113.75,2719644.0,0.0,1.0,112.22,113.97,112.22,113.75,2719644.0
-2017-07-21,111.5,112.91,111.27,112.22,2412908.0,0.0,1.0,111.5,112.91,111.27,112.22,2412908.0
-2017-07-20,111.61,112.18,110.38,111.97,2137684.0,0.0,1.0,111.61,112.18,110.38,111.97,2137684.0
-2017-07-19,110.43,111.65,109.81,111.58,2306302.0,0.0,1.0,110.43,111.65,109.81,111.58,2306302.0
-2017-07-18,110.0,110.93,109.48,110.28,1902014.0,0.0,1.0,110.0,110.93,109.48,110.28,1902014.0
-2017-07-17,109.02,110.43,108.715,109.44,1600888.0,0.0,1.0,109.02,110.43,108.715,109.44,1600888.0
-2017-07-14,109.61,110.34,108.75,108.99,1319830.0,0.0,1.0,109.61,110.34,108.75,108.99,1319830.0
-2017-07-13,110.83,111.61,108.92,108.98,1705243.0,0.0,1.0,110.83,111.61,108.92,108.98,1705243.0
-2017-07-12,109.5,110.9,109.05,110.68,1929711.0,0.0,1.0,109.5,110.9,109.05,110.68,1929711.0
-2017-07-11,107.63,109.71,107.1001,108.42,2254636.0,0.0,1.0,107.63,109.71,107.1001,108.42,2254636.0
-2017-07-10,107.84,108.69,107.01,107.84,1829832.0,0.0,1.0,107.84,108.69,107.01,107.84,1829832.0
-2017-07-07,106.28,108.47,105.54,107.45,2113210.0,0.0,1.0,106.28,108.47,105.54,107.45,2113210.0
-2017-07-06,106.06,107.12,105.5,105.75,2418406.0,0.0,1.0,106.06,107.12,105.5,105.75,2418406.0
-2017-07-05,105.95,107.31,105.35,106.76,2790438.0,0.0,1.0,105.95,107.31,105.35,106.76,2790438.0
-2017-07-03,106.51,107.0,105.21,105.42,1656433.0,0.0,1.0,106.51,107.0,105.21,105.42,1656433.0
-2017-06-30,107.1,107.56,105.65,105.72,3193822.0,0.0,1.0,107.1,107.56,105.65,105.72,3193822.0
-2017-06-29,108.16,108.72,105.47,106.68,3801546.0,0.0,1.0,108.16,108.72,105.47,106.68,3801546.0
-2017-06-28,108.7,109.2,106.74,108.81,3666366.0,0.0,1.0,108.7,109.2,106.74,108.81,3666366.0
-2017-06-27,111.35,111.93,108.13,108.32,3051541.0,0.0,1.0,111.35,111.93,108.13,108.32,3051541.0
-2017-06-26,111.0,112.64,110.375,111.86,2433287.0,0.0,1.0,111.0,112.64,110.375,111.86,2433287.0
-2017-06-23,112.51,112.95,110.77,110.83,5488299.0,0.0,1.0,112.51,112.95,110.77,110.83,5488299.0
-2017-06-22,113.51,113.52,111.36,112.62,2233674.0,0.0,1.0,113.51,113.52,111.36,112.62,2233674.0
-2017-06-21,114.33,114.69,111.83,113.17,3048981.0,0.0,1.0,114.33,114.69,111.83,113.17,3048981.0
-2017-06-20,113.43,115.12,113.29,113.47,2694325.0,0.0,1.0,113.43,115.12,113.29,113.47,2694325.0
-2017-06-19,111.18,113.86,111.18,113.65,2863975.0,0.0,1.0,111.18,113.86,111.18,113.65,2863975.0
-2017-06-16,110.72,112.51,110.07,110.51,9457081.0,0.0,1.0,110.72,112.51,110.07,110.51,9457081.0
-2017-06-15,108.24,111.03,107.32,110.53,3062302.0,0.0,1.0,108.24,111.03,107.32,110.53,3062302.0
-2017-06-14,110.16,111.11,108.68,110.02,2161626.0,0.0,1.0,110.16,111.11,108.68,110.02,2161626.0
-2017-06-13,110.33,110.96,108.08,109.98,2727219.0,0.0,1.0,110.33,110.96,108.08,109.98,2727219.0
-2017-06-12,109.3,111.175,105.54,108.9,5802602.0,0.0,1.0,109.3,111.175,105.54,108.9,5802602.0
-2017-06-09,114.84,115.36,107.03,110.46,5712259.0,0.0,1.0,114.84,115.36,107.03,110.46,5712259.0
-2017-06-08,116.04,116.04,113.24,114.29,3268285.0,0.0,1.0,116.04,116.04,113.24,114.29,3268285.0
-2017-06-07,114.84,115.54,114.23,115.37,2466012.0,0.0,1.0,114.84,115.54,114.23,115.37,2466012.0
-2017-06-06,114.54,115.39,113.59,113.69,2492255.0,0.0,1.0,114.54,115.39,113.59,113.69,2492255.0
-2017-06-05,114.68,115.13,114.19,114.69,1858473.0,0.0,1.0,114.68,115.13,114.19,114.69,1858473.0
-2017-06-02,113.85,114.54,113.2,114.52,1867350.0,0.0,1.0,113.85,114.54,113.2,114.52,1867350.0
-2017-06-01,113.96,114.94,113.175,113.87,2226980.0,0.0,1.0,113.96,114.94,113.175,113.87,2226980.0
diff --git a/examples/quick/demos/stocqt/content/data/EBAY.csv b/examples/quick/demos/stocqt/content/data/EBAY.csv
deleted file mode 100644
index 9254489791..0000000000
--- a/examples/quick/demos/stocqt/content/data/EBAY.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,37.82,38.03,37.65,37.74,4476821.0,0.0,1.0,37.82,38.03,37.65,37.74,4476821.0
-2017-12-28,37.46,37.93,37.4501,37.92,3379374.0,0.0,1.0,37.46,37.93,37.4501,37.92,3379374.0
-2017-12-27,38.07,38.08,37.56,37.61,4091574.0,0.0,1.0,38.07,38.08,37.56,37.61,4091574.0
-2017-12-26,37.79,38.01,37.605,37.94,4493535.0,0.0,1.0,37.79,38.01,37.605,37.94,4493535.0
-2017-12-22,37.69,37.905,37.53,37.76,7145144.0,0.0,1.0,37.69,37.905,37.53,37.76,7145144.0
-2017-12-21,38.11,38.24,37.77,37.81,9594664.0,0.0,1.0,38.11,38.24,37.77,37.81,9594664.0
-2017-12-20,37.87,38.1,37.745,37.93,6480341.0,0.0,1.0,37.87,38.1,37.745,37.93,6480341.0
-2017-12-19,38.15,38.23,37.72,37.82,7711342.0,0.0,1.0,38.15,38.23,37.72,37.82,7711342.0
-2017-12-18,38.5,38.66,38.12,38.18,7566184.0,0.0,1.0,38.5,38.66,38.12,38.18,7566184.0
-2017-12-15,37.72,38.42,37.39,38.37,12791334.0,0.0,1.0,37.72,38.42,37.39,38.37,12791334.0
-2017-12-14,37.41,37.77,37.41,37.6,5346581.0,0.0,1.0,37.41,37.77,37.41,37.6,5346581.0
-2017-12-13,37.46,37.64,37.33,37.4,5742256.0,0.0,1.0,37.46,37.64,37.33,37.4,5742256.0
-2017-12-12,37.44,37.49,37.1,37.44,6223963.0,0.0,1.0,37.44,37.49,37.1,37.44,6223963.0
-2017-12-11,37.51,37.69,37.32,37.52,6245593.0,0.0,1.0,37.51,37.69,37.32,37.52,6245593.0
-2017-12-08,37.25,37.99,37.16,37.65,12217992.0,0.0,1.0,37.25,37.99,37.16,37.65,12217992.0
-2017-12-07,36.72,37.15,36.5,36.85,7364150.0,0.0,1.0,36.72,37.15,36.5,36.85,7364150.0
-2017-12-06,36.64,36.91,36.36,36.83,8813063.0,0.0,1.0,36.64,36.91,36.36,36.83,8813063.0
-2017-12-05,35.94,37.19,35.75,36.81,18630500.0,0.0,1.0,35.94,37.19,35.75,36.81,18630500.0
-2017-12-04,35.58,36.08,35.38,35.7,11046784.0,0.0,1.0,35.58,36.08,35.38,35.7,11046784.0
-2017-12-01,34.38,35.25,34.31,35.2,11236547.0,0.0,1.0,34.38,35.25,34.31,35.2,11236547.0
-2017-11-30,34.48,35.19,34.4612,34.67,16173978.0,0.0,1.0,34.48,35.19,34.4612,34.67,16173978.0
-2017-11-29,35.42,35.45,33.945,34.38,21446119.0,0.0,1.0,35.42,35.45,33.945,34.38,21446119.0
-2017-11-28,35.99,36.2,35.42,35.5,10191191.0,0.0,1.0,35.99,36.2,35.42,35.5,10191191.0
-2017-11-27,35.88,36.2,35.7905,35.99,6981252.0,0.0,1.0,35.88,36.2,35.7905,35.99,6981252.0
-2017-11-24,36.07,36.11,35.7,35.84,3123070.0,0.0,1.0,36.07,36.11,35.7,35.84,3123070.0
-2017-11-22,36.05,36.195,35.84,35.94,4563054.0,0.0,1.0,36.05,36.195,35.84,35.94,4563054.0
-2017-11-21,35.72,36.11,35.56,35.96,5807385.0,0.0,1.0,35.72,36.11,35.56,35.96,5807385.0
-2017-11-20,35.62,35.97,35.42,35.53,5964478.0,0.0,1.0,35.62,35.97,35.42,35.53,5964478.0
-2017-11-17,35.64,35.71,35.31,35.58,7458295.0,0.0,1.0,35.64,35.71,35.31,35.58,7458295.0
-2017-11-16,35.37,35.815,35.32,35.62,7632669.0,0.0,1.0,35.37,35.815,35.32,35.62,7632669.0
-2017-11-15,35.03,35.47,34.79,35.3,7871444.0,0.0,1.0,35.03,35.47,34.79,35.3,7871444.0
-2017-11-14,35.71,35.79,35.18,35.22,10858859.0,0.0,1.0,35.71,35.79,35.18,35.22,10858859.0
-2017-11-13,35.7,36.1,35.32,35.85,7047371.0,0.0,1.0,35.7,36.1,35.32,35.85,7047371.0
-2017-11-10,35.51,36.045,35.34,35.97,8276878.0,0.0,1.0,35.51,36.045,35.34,35.97,8276878.0
-2017-11-09,36.26,36.36,35.21,35.69,16766871.0,0.0,1.0,36.26,36.36,35.21,35.69,16766871.0
-2017-11-07,37.6,37.6,37.1,37.41,5564092.0,0.0,1.0,37.6,37.6,37.1,37.41,5564092.0
-2017-11-06,37.38,37.61,37.3,37.37,4338972.0,0.0,1.0,37.38,37.61,37.3,37.37,4338972.0
-2017-11-03,37.44,37.545,37.11,37.5,5708840.0,0.0,1.0,37.44,37.545,37.11,37.5,5708840.0
-2017-11-02,37.49,37.5,36.995,37.4,5341879.0,0.0,1.0,37.49,37.5,36.995,37.4,5341879.0
-2017-11-01,37.85,38.09,37.435,37.54,7052554.0,0.0,1.0,37.85,38.09,37.435,37.54,7052554.0
-2017-10-31,37.11,37.68,37.02,37.64,6678430.0,0.0,1.0,37.11,37.68,37.02,37.64,6678430.0
-2017-10-30,36.86,37.13,36.74,37.0,7988838.0,0.0,1.0,36.86,37.13,36.74,37.0,7988838.0
-2017-10-27,37.07,37.36,36.635,36.8,10660803.0,0.0,1.0,37.07,37.36,36.635,36.8,10660803.0
-2017-10-26,36.74,37.24,36.72,36.9,7622668.0,0.0,1.0,36.74,37.24,36.72,36.9,7622668.0
-2017-10-25,36.66,36.92,36.45,36.68,7839488.0,0.0,1.0,36.66,36.92,36.45,36.68,7839488.0
-2017-10-24,36.51,37.03,36.51,36.74,8439952.0,0.0,1.0,36.51,37.03,36.51,36.74,8439952.0
-2017-10-23,37.66,37.85,36.74,36.83,10318056.0,0.0,1.0,37.66,37.85,36.74,36.83,10318056.0
-2017-10-20,37.34,37.86,37.3,37.61,14821200.0,0.0,1.0,37.34,37.86,37.3,37.61,14821200.0
-2017-10-19,36.48,37.49,36.19,37.29,28992713.0,0.0,1.0,36.48,37.49,36.19,37.29,28992713.0
-2017-10-18,37.68,38.22,37.54,37.97,13424086.0,0.0,1.0,37.68,38.22,37.54,37.97,13424086.0
-2017-10-17,37.76,37.84,37.42,37.49,11904108.0,0.0,1.0,37.76,37.84,37.42,37.49,11904108.0
-2017-10-16,38.29,38.5,37.725,37.77,8645585.0,0.0,1.0,38.29,38.5,37.725,37.77,8645585.0
-2017-10-13,38.35,38.53,38.16,38.35,9392998.0,0.0,1.0,38.35,38.53,38.16,38.35,9392998.0
-2017-10-12,38.31,38.5,38.055,38.09,10020870.0,0.0,1.0,38.31,38.5,38.055,38.09,10020870.0
-2017-10-11,38.85,38.98,38.17,38.31,10841024.0,0.0,1.0,38.85,38.98,38.17,38.31,10841024.0
-2017-10-10,39.02,39.275,38.77,38.84,5998658.0,0.0,1.0,39.02,39.275,38.77,38.84,5998658.0
-2017-10-09,38.8,39.265,38.8,38.99,4982743.0,0.0,1.0,38.8,39.265,38.8,38.99,4982743.0
-2017-10-06,39.05,39.08,38.67,38.81,6947721.0,0.0,1.0,39.05,39.08,38.67,38.81,6947721.0
-2017-10-05,38.76,39.035,38.675,38.99,5155812.0,0.0,1.0,38.76,39.035,38.675,38.99,5155812.0
-2017-10-04,38.8,38.83,38.5,38.66,5590600.0,0.0,1.0,38.8,38.83,38.5,38.66,5590600.0
-2017-10-03,38.78,39.05,38.485,38.71,5103669.0,0.0,1.0,38.78,39.05,38.485,38.71,5103669.0
-2017-10-02,38.51,38.78,38.37,38.73,7220120.0,0.0,1.0,38.51,38.78,38.37,38.73,7220120.0
-2017-09-29,37.73,38.6,37.71,38.46,9573477.0,0.0,1.0,37.73,38.6,37.71,38.46,9573477.0
-2017-09-28,37.44,37.96,37.44,37.73,7683377.0,0.0,1.0,37.44,37.96,37.44,37.73,7683377.0
-2017-09-27,38.03,38.29,37.76,38.05,9331736.0,0.0,1.0,38.03,38.29,37.76,38.05,9331736.0
-2017-09-26,37.85,38.19,37.75,37.85,5348200.0,0.0,1.0,37.85,38.19,37.75,37.85,5348200.0
-2017-09-25,38.22,38.31,37.54,37.78,7053896.0,0.0,1.0,38.22,38.31,37.54,37.78,7053896.0
-2017-09-22,38.13,38.31,38.05,38.29,4851365.0,0.0,1.0,38.13,38.31,38.05,38.29,4851365.0
-2017-09-21,38.55,38.67,38.19,38.25,5673772.0,0.0,1.0,38.55,38.67,38.19,38.25,5673772.0
-2017-09-20,38.67,38.87,38.21,38.54,5703686.0,0.0,1.0,38.67,38.87,38.21,38.54,5703686.0
-2017-09-19,38.5,38.75,38.32,38.59,5131286.0,0.0,1.0,38.5,38.75,38.32,38.59,5131286.0
-2017-09-18,38.3,38.665,38.18,38.39,5127823.0,0.0,1.0,38.3,38.665,38.18,38.39,5127823.0
-2017-09-15,38.27,38.865,38.07,38.4,10869179.0,0.0,1.0,38.27,38.865,38.07,38.4,10869179.0
-2017-09-14,38.24,38.585,38.13,38.31,6478656.0,0.0,1.0,38.24,38.585,38.13,38.31,6478656.0
-2017-09-13,38.0,38.5,38.0,38.27,4960915.0,0.0,1.0,38.0,38.5,38.0,38.27,4960915.0
-2017-09-12,38.07,38.3,37.98,38.18,4170327.0,0.0,1.0,38.07,38.3,37.98,38.18,4170327.0
-2017-09-11,38.04,38.26,38.0,38.09,5945142.0,0.0,1.0,38.04,38.26,38.0,38.09,5945142.0
-2017-09-08,38.04,38.3,37.725,37.79,9052735.0,0.0,1.0,38.04,38.3,37.725,37.79,9052735.0
-2017-09-07,36.95,38.19,36.84,38.01,13980230.0,0.0,1.0,36.95,38.19,36.84,38.01,13980230.0
-2017-09-06,36.08,36.98,36.08,36.76,12653446.0,0.0,1.0,36.08,36.98,36.08,36.76,12653446.0
-2017-09-05,36.19,36.48,35.77,36.09,6296438.0,0.0,1.0,36.19,36.48,35.77,36.09,6296438.0
-2017-09-01,36.2,36.58,36.14,36.35,5037396.0,0.0,1.0,36.2,36.58,36.14,36.35,5037396.0
-2017-08-31,35.85,36.32,35.821,36.13,8522717.0,0.0,1.0,35.85,36.32,35.821,36.13,8522717.0
-2017-08-30,35.14,35.955,35.1,35.69,8205167.0,0.0,1.0,35.14,35.955,35.1,35.69,8205167.0
-2017-08-29,34.48,35.315,34.42,35.2,7089389.0,0.0,1.0,34.48,35.315,34.42,35.2,7089389.0
-2017-08-28,34.75,34.9,34.66,34.81,5005834.0,0.0,1.0,34.75,34.9,34.66,34.81,5005834.0
-2017-08-25,34.98,35.07,34.56,34.68,6720164.0,0.0,1.0,34.98,35.07,34.56,34.68,6720164.0
-2017-08-24,34.86,35.04,34.51,34.88,5638387.0,0.0,1.0,34.86,35.04,34.51,34.88,5638387.0
-2017-08-23,34.62,34.98,34.51,34.89,6295975.0,0.0,1.0,34.62,34.98,34.51,34.89,6295975.0
-2017-08-22,34.37,34.81,34.31,34.81,6144284.0,0.0,1.0,34.37,34.81,34.31,34.81,6144284.0
-2017-08-21,35.13,35.13,34.09,34.24,7592681.0,0.0,1.0,35.13,35.13,34.09,34.24,7592681.0
-2017-08-18,34.83,35.14,34.75,34.79,8521640.0,0.0,1.0,34.83,35.14,34.75,34.79,8521640.0
-2017-08-17,35.5,35.5,34.8,34.85,6290987.0,0.0,1.0,35.5,35.5,34.8,34.85,6290987.0
-2017-08-16,35.23,35.48,35.07,35.36,3809705.0,0.0,1.0,35.23,35.48,35.07,35.36,3809705.0
-2017-08-15,35.24,35.42,35.12,35.25,4487094.0,0.0,1.0,35.24,35.42,35.12,35.25,4487094.0
-2017-08-14,35.44,35.45,34.88,35.2,6932178.0,0.0,1.0,35.44,35.45,34.88,35.2,6932178.0
-2017-08-11,35.16,35.32,34.76,35.05,7688311.0,0.0,1.0,35.16,35.32,34.76,35.05,7688311.0
-2017-08-10,35.95,35.9845,34.88,35.0,12151126.0,0.0,1.0,35.95,35.9845,34.88,35.0,12151126.0
-2017-08-09,36.13,36.225,35.72,36.08,7540671.0,0.0,1.0,36.13,36.225,35.72,36.08,7540671.0
-2017-08-08,35.96,36.64,35.89,36.36,9441402.0,0.0,1.0,35.96,36.64,35.89,36.36,9441402.0
-2017-08-07,35.61,36.15,35.38,36.11,5309161.0,0.0,1.0,35.61,36.15,35.38,36.11,5309161.0
-2017-08-04,35.86,35.86,35.55,35.62,5036090.0,0.0,1.0,35.86,35.86,35.55,35.62,5036090.0
-2017-08-03,35.97,35.98,35.57,35.71,5592728.0,0.0,1.0,35.97,35.98,35.57,35.71,5592728.0
-2017-08-02,35.69,35.95,35.42,35.9,6395959.0,0.0,1.0,35.69,35.95,35.42,35.9,6395959.0
-2017-08-01,35.82,36.02,35.75,35.91,4598532.0,0.0,1.0,35.82,36.02,35.75,35.91,4598532.0
-2017-07-31,36.09,36.13,35.65,35.73,6117033.0,0.0,1.0,36.09,36.13,35.65,35.73,6117033.0
-2017-07-28,36.08,36.21,35.73,35.94,7097225.0,0.0,1.0,36.08,36.21,35.73,35.94,7097225.0
-2017-07-27,37.09,37.265,35.54,36.17,15261765.0,0.0,1.0,37.09,37.265,35.54,36.17,15261765.0
-2017-07-26,36.36,37.07,36.36,37.04,10987896.0,0.0,1.0,36.36,37.07,36.36,37.04,10987896.0
-2017-07-25,36.33,36.485,36.06,36.32,6191010.0,0.0,1.0,36.33,36.485,36.06,36.32,6191010.0
-2017-07-24,36.45,36.73,36.22,36.39,9661599.0,0.0,1.0,36.45,36.73,36.22,36.39,9661599.0
-2017-07-21,36.2,36.9,36.05,36.61,22131224.0,0.0,1.0,36.2,36.9,36.05,36.61,22131224.0
-2017-07-20,37.17,37.48,37.0,37.18,13467628.0,0.0,1.0,37.17,37.48,37.0,37.18,13467628.0
-2017-07-19,36.95,37.26,36.645,37.08,8510278.0,0.0,1.0,36.95,37.26,36.645,37.08,8510278.0
-2017-07-18,36.94,36.94,36.57,36.8,12755207.0,0.0,1.0,36.94,36.94,36.57,36.8,12755207.0
-2017-07-17,37.03,37.17,36.57,37.05,8151725.0,0.0,1.0,37.03,37.17,36.57,37.05,8151725.0
-2017-07-14,36.91,37.2,36.83,37.08,9654192.0,0.0,1.0,36.91,37.2,36.83,37.08,9654192.0
-2017-07-13,36.61,37.13,36.26,36.5,12877614.0,0.0,1.0,36.61,37.13,36.26,36.5,12877614.0
-2017-07-12,35.53,36.2,35.53,36.03,13411174.0,0.0,1.0,35.53,36.2,35.53,36.03,13411174.0
-2017-07-11,34.97,35.45,34.89,35.19,8306962.0,0.0,1.0,34.97,35.45,34.89,35.19,8306962.0
-2017-07-10,34.31,35.14,34.28,35.04,8695234.0,0.0,1.0,34.31,35.14,34.28,35.04,8695234.0
-2017-07-07,34.02,34.55,34.01,34.23,6747508.0,0.0,1.0,34.02,34.55,34.01,34.23,6747508.0
-2017-07-06,34.39,34.5,33.95,34.03,8551358.0,0.0,1.0,34.39,34.5,33.95,34.03,8551358.0
-2017-07-05,34.73,34.86,34.505,34.72,7381884.0,0.0,1.0,34.73,34.86,34.505,34.72,7381884.0
-2017-07-03,35.15,35.305,34.55,34.6,4517402.0,0.0,1.0,35.15,35.305,34.55,34.6,4517402.0
-2017-06-30,34.78,35.07,34.52,34.92,10561065.0,0.0,1.0,34.78,35.07,34.52,34.92,10561065.0
-2017-06-29,35.3,35.3,34.09,34.51,8166989.0,0.0,1.0,35.3,35.3,34.09,34.51,8166989.0
-2017-06-28,35.0,35.33,34.615,35.31,4791632.0,0.0,1.0,35.0,35.33,34.615,35.31,4791632.0
-2017-06-27,35.0,35.32,34.85,34.91,8598433.0,0.0,1.0,35.0,35.32,34.85,34.91,8598433.0
-2017-06-26,35.89,35.97,35.0,35.09,6634019.0,0.0,1.0,35.89,35.97,35.0,35.09,6634019.0
-2017-06-23,35.12,35.735,34.96,35.58,8872359.0,0.0,1.0,35.12,35.735,34.96,35.58,8872359.0
-2017-06-22,34.99,35.285,34.84,35.12,5120718.0,0.0,1.0,34.99,35.285,34.84,35.12,5120718.0
-2017-06-21,35.0,35.12,34.75,34.96,5400949.0,0.0,1.0,35.0,35.12,34.75,34.96,5400949.0
-2017-06-20,34.74,35.34,34.74,34.93,10506559.0,0.0,1.0,34.74,35.34,34.74,34.93,10506559.0
-2017-06-19,34.12,34.99,34.0,34.9,5760279.0,0.0,1.0,34.12,34.99,34.0,34.9,5760279.0
-2017-06-16,33.92,34.32,33.91,33.96,9640312.0,0.0,1.0,33.92,34.32,33.91,33.96,9640312.0
-2017-06-15,34.26,34.29,33.89,34.09,5344405.0,0.0,1.0,34.26,34.29,33.89,34.09,5344405.0
-2017-06-14,34.63,34.73,34.11,34.5,6371265.0,0.0,1.0,34.63,34.73,34.11,34.5,6371265.0
-2017-06-13,34.21,34.55,34.08,34.47,7302410.0,0.0,1.0,34.21,34.55,34.08,34.47,7302410.0
-2017-06-12,34.7,34.77,33.975,34.15,12807616.0,0.0,1.0,34.7,34.77,33.975,34.15,12807616.0
-2017-06-09,36.25,36.5,34.69,34.94,10974043.0,0.0,1.0,36.25,36.5,34.69,34.94,10974043.0
-2017-06-08,36.07,36.315,35.865,36.14,8767604.0,0.0,1.0,36.07,36.315,35.865,36.14,8767604.0
-2017-06-07,35.65,35.87,35.56,35.77,5280007.0,0.0,1.0,35.65,35.87,35.56,35.77,5280007.0
-2017-06-06,35.41,35.805,35.35,35.47,5463513.0,0.0,1.0,35.41,35.805,35.35,35.47,5463513.0
-2017-06-05,36.02,36.02,35.39,35.55,5946671.0,0.0,1.0,36.02,36.02,35.39,35.55,5946671.0
-2017-06-02,34.92,35.44,34.61,35.32,6843000.0,0.0,1.0,34.92,35.44,34.61,35.32,6843000.0
-2017-06-01,34.44,34.89,34.2,34.79,6463818.0,0.0,1.0,34.44,34.89,34.2,34.79,6463818.0
diff --git a/examples/quick/demos/stocqt/content/data/FB.csv b/examples/quick/demos/stocqt/content/data/FB.csv
deleted file mode 100644
index d9ebf9eeba..0000000000
--- a/examples/quick/demos/stocqt/content/data/FB.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,178.0,178.85,176.46,176.46,10028758.0,0.0,1.0,178.0,178.85,176.46,176.46,10028758.0
-2017-12-28,177.95,178.9367,177.68,177.92,11008996.0,0.0,1.0,177.95,178.9367,177.68,177.92,11008996.0
-2017-12-27,176.55,178.44,176.26,177.62,9296258.0,0.0,1.0,176.55,178.44,176.26,177.62,9296258.0
-2017-12-26,176.63,177.0,174.67,175.99,8726829.0,0.0,1.0,176.63,177.0,174.67,175.99,8726829.0
-2017-12-22,177.14,177.53,176.23,177.2,8462491.0,0.0,1.0,177.14,177.53,176.23,177.2,8462491.0
-2017-12-21,177.94,178.68,177.05,177.45,11050969.0,0.0,1.0,177.94,178.68,177.05,177.45,11050969.0
-2017-12-20,179.81,179.81,177.36,177.89,11754823.0,0.0,1.0,179.81,179.81,177.36,177.89,11754823.0
-2017-12-19,179.95,180.08,178.22,179.51,14769239.0,0.0,1.0,179.95,180.08,178.22,179.51,14769239.0
-2017-12-18,181.01,181.3,179.75,180.82,17014337.0,0.0,1.0,181.01,181.3,179.75,180.82,17014337.0
-2017-12-15,179.02,180.4934,178.36,180.18,26225100.0,0.0,1.0,179.02,180.4934,178.36,180.18,26225100.0
-2017-12-14,178.29,180.3601,177.68,178.39,13393757.0,0.0,1.0,178.29,180.3601,177.68,178.39,13393757.0
-2017-12-13,177.3,179.16,177.25,178.3,14406776.0,0.0,1.0,177.3,179.16,177.25,178.3,14406776.0
-2017-12-12,178.6,179.18,176.6,176.96,16675275.0,0.0,1.0,178.6,179.18,176.6,176.96,16675275.0
-2017-12-11,179.3,180.22,178.8,179.04,12630207.0,0.0,1.0,179.3,180.22,178.8,179.04,12630207.0
-2017-12-08,181.53,182.28,178.7401,179.0,19377310.0,0.0,1.0,181.53,182.28,178.7401,179.0,19377310.0
-2017-12-07,175.8,180.39,175.8,180.14,19588217.0,0.0,1.0,175.8,180.39,175.8,180.14,19588217.0
-2017-12-06,172.5,176.77,171.9,176.06,20059293.0,0.0,1.0,172.5,176.77,171.9,176.06,20059293.0
-2017-12-05,170.45,175.38,169.01,172.83,20028656.0,0.0,1.0,170.45,175.38,169.01,172.83,20028656.0
-2017-12-04,176.29,176.57,170.79,171.47,24184006.0,0.0,1.0,176.29,176.57,170.79,171.47,24184006.0
-2017-12-01,176.03,177.48,172.34,175.1,19824531.0,0.0,1.0,176.03,177.48,172.34,175.1,19824531.0
-2017-11-30,176.85,178.275,175.2,177.18,24613431.0,0.0,1.0,176.85,178.275,175.2,177.18,24613431.0
-2017-11-29,181.89,181.97,174.0,175.13,41651953.0,0.0,1.0,181.89,181.97,174.0,175.13,41651953.0
-2017-11-28,183.51,184.25,182.09,182.42,13761926.0,0.0,1.0,183.51,184.25,182.09,182.42,13761926.0
-2017-11-27,182.56,183.73,181.99,183.03,12249740.0,0.0,1.0,182.56,183.73,181.99,183.03,12249740.0
-2017-11-24,180.4,183.15,180.29,182.78,9426010.0,0.0,1.0,180.4,183.15,180.29,182.78,9426010.0
-2017-11-22,181.3,181.73,180.44,180.87,10238140.0,0.0,1.0,181.3,181.73,180.44,180.87,10238140.0
-2017-11-21,179.15,181.89,178.99,181.86,14409305.0,0.0,1.0,179.15,181.89,178.99,181.86,14409305.0
-2017-11-20,178.87,179.5,178.1,178.74,9476502.0,0.0,1.0,178.87,179.5,178.1,178.74,9476502.0
-2017-11-17,179.3,179.98,178.9,179.0,12722802.0,0.0,1.0,179.3,179.98,178.9,179.0,12722802.0
-2017-11-16,178.76,179.83,178.5,179.59,14655982.0,0.0,1.0,178.76,179.83,178.5,179.59,14655982.0
-2017-11-15,176.66,178.57,176.4,177.95,10131051.0,0.0,1.0,176.66,178.57,176.4,177.95,10131051.0
-2017-11-14,178.13,178.97,177.18,178.07,9465112.0,0.0,1.0,178.13,178.97,177.18,178.07,9465112.0
-2017-11-13,177.5,179.04,177.3,178.77,9431449.0,0.0,1.0,177.5,179.04,177.3,178.77,9431449.0
-2017-11-10,178.35,179.0999,177.96,178.46,10933405.0,0.0,1.0,178.35,179.0999,177.96,178.46,10933405.0
-2017-11-09,178.31,179.4,177.09,179.3,12460345.0,0.0,1.0,178.31,179.4,177.09,179.3,12460345.0
-2017-11-07,180.5,180.7478,178.96,180.25,12679885.0,0.0,1.0,180.5,180.7478,178.96,180.25,12679885.0
-2017-11-06,178.56,180.45,178.31,180.17,13065077.0,0.0,1.0,178.56,180.45,178.31,180.17,13065077.0
-2017-11-03,179.29,179.86,176.71,178.92,17572587.0,0.0,1.0,179.29,179.86,176.71,178.92,17572587.0
-2017-11-02,180.63,181.94,177.34,178.92,35119841.0,0.0,1.0,180.63,181.94,177.34,178.92,35119841.0
-2017-11-01,182.36,182.9,180.57,182.66,28922959.0,0.0,1.0,182.36,182.9,180.57,182.66,28922959.0
-2017-10-31,180.57,180.8,178.94,180.06,19766043.0,0.0,1.0,180.57,180.8,178.94,180.06,19766043.0
-2017-10-30,179.26,180.69,177.61,179.87,24179258.0,0.0,1.0,179.26,180.69,177.61,179.87,24179258.0
-2017-10-27,174.15,178.21,173.9,177.88,29867490.0,0.0,1.0,174.15,178.21,173.9,177.88,29867490.0
-2017-10-26,171.38,172.285,170.39,170.63,10932929.0,0.0,1.0,171.38,172.285,170.39,170.63,10932929.0
-2017-10-25,171.9,172.25,168.89,170.6,15095603.0,0.0,1.0,171.9,172.25,168.89,170.6,15095603.0
-2017-10-24,172.3,173.24,171.5,171.8,11629341.0,0.0,1.0,172.3,173.24,171.5,171.8,11629341.0
-2017-10-23,175.2,175.34,171.25,171.27,13622072.0,0.0,1.0,175.2,175.34,171.25,171.27,13622072.0
-2017-10-20,175.5,175.88,174.63,174.98,11861307.0,0.0,1.0,175.5,175.88,174.63,174.98,11861307.0
-2017-10-19,174.93,176.03,172.63,174.56,13602869.0,0.0,1.0,174.93,176.03,172.63,174.56,13602869.0
-2017-10-18,176.65,176.74,175.75,176.03,12655492.0,0.0,1.0,176.65,176.74,175.75,176.03,12655492.0
-2017-10-17,174.71,176.13,174.36,176.11,15381990.0,0.0,1.0,174.71,176.13,174.36,176.11,15381990.0
-2017-10-16,174.49,175.0,174.06,174.52,11225293.0,0.0,1.0,174.49,175.0,174.06,174.52,11225293.0
-2017-10-13,173.45,174.65,173.2,173.74,13305724.0,0.0,1.0,173.45,174.65,173.2,173.74,13305724.0
-2017-10-12,172.61,173.85,172.29,172.55,10312488.0,0.0,1.0,172.61,173.85,172.29,172.55,10312488.0
-2017-10-11,171.95,172.78,171.4,172.74,11023310.0,0.0,1.0,171.95,172.78,171.4,172.74,11023310.0
-2017-10-10,173.0,173.2,170.8,171.59,11231234.0,0.0,1.0,173.0,173.2,170.8,171.59,11231234.0
-2017-10-09,172.7,174.88,172.0,172.5,14472612.0,0.0,1.0,172.7,174.88,172.0,172.5,14472612.0
-2017-10-06,170.25,172.37,169.75,172.23,12670089.0,0.0,1.0,170.25,172.37,169.75,172.23,12670089.0
-2017-10-05,169.18,171.31,168.6,171.24,14013869.0,0.0,1.0,169.18,171.31,168.6,171.24,14013869.0
-2017-10-04,169.83,170.67,168.29,168.42,11829323.0,0.0,1.0,169.83,170.67,168.29,168.42,11829323.0
-2017-10-03,169.3,170.73,169.2,169.96,8054219.0,0.0,1.0,169.3,170.73,169.2,169.96,8054219.0
-2017-10-02,171.39,171.87,168.75,169.47,13104304.0,0.0,1.0,171.39,171.87,168.75,169.47,13104304.0
-2017-09-29,168.83,171.66,168.81,170.81,15114619.0,0.0,1.0,168.83,171.66,168.81,170.81,15114619.0
-2017-09-28,167.94,169.0696,167.16,168.73,12084865.0,0.0,1.0,167.94,169.0696,167.16,168.73,12084865.0
-2017-09-27,165.9,168.34,165.57,167.68,18963276.0,0.0,1.0,165.9,168.34,165.57,167.68,18963276.0
-2017-09-26,164.5,165.5,162.78,164.21,22866403.0,0.0,1.0,164.5,165.5,162.78,164.21,22866403.0
-2017-09-25,169.24,169.3,161.56,162.87,40538994.0,0.0,1.0,169.24,169.3,161.56,162.87,40538994.0
-2017-09-22,170.21,171.73,169.22,170.54,11835708.0,0.0,1.0,170.21,171.73,169.22,170.54,11835708.0
-2017-09-21,171.69,172.27,170.01,171.11,11054545.0,0.0,1.0,171.69,172.27,170.01,171.11,11054545.0
-2017-09-20,172.5,173.05,170.7,172.17,11899057.0,0.0,1.0,172.5,173.05,170.7,172.17,11899057.0
-2017-09-19,170.62,172.56,170.36,172.52,12911661.0,0.0,1.0,170.62,172.56,170.36,172.52,12911661.0
-2017-09-18,171.99,172.07,169.34,170.01,12785437.0,0.0,1.0,171.99,172.07,169.34,170.01,12785437.0
-2017-09-15,170.88,172.34,170.26,171.58,15468473.0,0.0,1.0,170.88,172.34,170.26,171.58,15468473.0
-2017-09-14,172.26,172.28,170.5,170.96,15496424.0,0.0,1.0,172.26,172.28,170.5,170.96,15496424.0
-2017-09-13,173.01,173.17,172.06,173.05,8908633.0,0.0,1.0,173.01,173.17,172.06,173.05,8908633.0
-2017-09-12,173.76,174.0,171.75,172.96,11051768.0,0.0,1.0,173.76,174.0,171.75,172.96,11051768.0
-2017-09-11,172.4,173.89,172.2,173.51,12183568.0,0.0,1.0,172.4,173.89,172.2,173.51,12183568.0
-2017-09-08,173.09,173.49,170.8,170.95,10936358.0,0.0,1.0,173.09,173.49,170.8,170.95,10936358.0
-2017-09-07,171.94,173.3067,170.27,173.21,17922494.0,0.0,1.0,171.94,173.3067,170.27,173.21,17922494.0
-2017-09-06,170.91,172.48,169.57,172.09,13659317.0,0.0,1.0,170.91,172.48,169.57,172.09,13659317.0
-2017-09-05,171.27,172.3875,169.55,170.72,13175866.0,0.0,1.0,171.27,172.3875,169.55,170.72,13175866.0
-2017-09-01,172.4,172.915,171.31,172.02,11614185.0,0.0,1.0,172.4,172.915,171.31,172.02,11614185.0
-2017-08-31,170.4,172.145,170.06,172.0,16873901.0,0.0,1.0,170.4,172.145,170.06,172.0,16873901.0
-2017-08-30,168.17,170.18,167.63,169.92,10850005.0,0.0,1.0,168.17,170.18,167.63,169.92,10850005.0
-2017-08-29,165.25,168.425,165.0,168.05,10992617.0,0.0,1.0,165.25,168.425,165.0,168.05,10992617.0
-2017-08-28,166.91,167.7,166.33,167.24,8360380.0,0.0,1.0,166.91,167.7,166.33,167.24,8360380.0
-2017-08-25,167.86,168.38,166.18,166.32,12391910.0,0.0,1.0,167.86,168.38,166.18,166.32,12391910.0
-2017-08-24,168.88,169.29,166.41,167.74,13552865.0,0.0,1.0,168.88,169.29,166.41,167.74,13552865.0
-2017-08-23,168.84,169.36,168.2,168.71,9756817.0,0.0,1.0,168.84,169.36,168.2,168.71,9756817.0
-2017-08-22,168.28,169.87,167.15,169.64,11333260.0,0.0,1.0,168.28,169.87,167.15,169.64,11333260.0
-2017-08-21,167.16,168.0,165.82,167.78,11880823.0,0.0,1.0,167.16,168.0,165.82,167.78,11880823.0
-2017-08-18,166.84,168.67,166.21,167.41,14933261.0,0.0,1.0,166.84,168.67,166.21,167.41,14933261.0
-2017-08-17,169.34,169.86,166.85,166.91,16791591.0,0.0,1.0,169.34,169.86,166.85,166.91,16791591.0
-2017-08-16,171.25,171.38,169.24,170.0,15580549.0,0.0,1.0,171.25,171.38,169.24,170.0,15580549.0
-2017-08-15,171.49,171.5,170.01,171.0,8621787.0,0.0,1.0,171.49,171.5,170.01,171.0,8621787.0
-2017-08-14,170.09,171.08,169.29,170.75,12786286.0,0.0,1.0,170.09,171.08,169.29,170.75,12786286.0
-2017-08-11,167.95,168.82,166.85,168.08,13664032.0,0.0,1.0,167.95,168.82,166.85,168.08,13664032.0
-2017-08-10,170.06,170.59,166.85,167.4,20353485.0,0.0,1.0,170.06,170.59,166.85,167.4,20353485.0
-2017-08-09,169.98,171.45,169.56,171.18,10597084.0,0.0,1.0,169.98,171.45,169.56,171.18,10597084.0
-2017-08-08,171.88,173.05,170.62,171.23,13813683.0,0.0,1.0,171.88,173.05,170.62,171.23,13813683.0
-2017-08-07,169.95,172.06,169.66,171.98,12504157.0,0.0,1.0,169.95,172.06,169.66,171.98,12504157.0
-2017-08-04,168.97,170.06,168.69,169.62,10360774.0,0.0,1.0,168.97,170.06,168.69,169.62,10360774.0
-2017-08-03,169.3,169.7,168.25,168.59,10316246.0,0.0,1.0,169.3,169.7,168.25,168.59,10316246.0
-2017-08-02,170.3,170.55,166.91,169.25,17061845.0,0.0,1.0,170.3,170.55,166.91,169.25,17061845.0
-2017-08-01,169.82,170.47,169.05,169.86,14051379.0,0.0,1.0,169.82,170.47,169.05,169.86,14051379.0
-2017-07-31,172.0,172.72,168.55,169.25,25157896.0,0.0,1.0,172.0,172.72,168.55,169.25,25157896.0
-2017-07-28,169.07,173.43,169.05,172.45,24036502.0,0.0,1.0,169.07,173.43,169.05,172.45,24036502.0
-2017-07-27,174.7,175.49,167.5,170.44,68065163.0,0.0,1.0,174.7,175.49,167.5,170.44,68065163.0
-2017-07-26,166.01,166.01,164.1,165.61,24081060.0,0.0,1.0,166.01,166.01,164.1,165.61,24081060.0
-2017-07-25,165.01,165.54,163.8619,165.28,15164613.0,0.0,1.0,165.01,165.54,163.8619,165.28,15164613.0
-2017-07-24,164.64,166.17,164.31,166.0,16595460.0,0.0,1.0,164.64,166.17,164.31,166.0,16595460.0
-2017-07-21,164.16,165.05,163.75,164.43,14494667.0,0.0,1.0,164.16,165.05,163.75,164.43,14494667.0
-2017-07-20,164.8,165.0,162.81,164.53,18293111.0,0.0,1.0,164.8,165.0,162.81,164.53,18293111.0
-2017-07-19,163.59,165.7,163.17,164.14,25915988.0,0.0,1.0,163.59,165.7,163.17,164.14,25915988.0
-2017-07-18,159.66,163.73,159.42,162.86,23621711.0,0.0,1.0,159.66,163.73,159.42,162.86,23621711.0
-2017-07-17,160.25,160.78,158.81,159.73,12567935.0,0.0,1.0,160.25,160.78,158.81,159.73,12567935.0
-2017-07-14,160.13,160.32,159.3254,159.97,16172560.0,0.0,1.0,160.13,160.32,159.3254,159.97,16172560.0
-2017-07-13,158.74,159.78,158.4227,159.26,13839891.0,0.0,1.0,158.74,159.78,158.4227,159.26,13839891.0
-2017-07-12,156.49,159.16,156.2,158.9,22483868.0,0.0,1.0,156.49,159.16,156.2,158.9,22483868.0
-2017-07-11,153.37,155.4225,152.91,155.27,13208251.0,0.0,1.0,153.37,155.4225,152.91,155.27,13208251.0
-2017-07-10,151.69,153.98,151.51,153.5,13296447.0,0.0,1.0,151.69,153.98,151.51,153.5,13296447.0
-2017-07-07,149.25,151.99,149.19,151.44,13229352.0,0.0,1.0,149.25,151.99,149.19,151.44,13229352.0
-2017-07-06,149.03,150.04,148.0,148.82,14788811.0,0.0,1.0,149.03,150.04,148.0,148.82,14788811.0
-2017-07-05,149.0,150.85,148.13,150.34,14037692.0,0.0,1.0,149.0,150.85,148.13,150.34,14037692.0
-2017-07-03,151.72,152.15,147.8,148.43,13860113.0,0.0,1.0,151.72,152.15,147.8,148.43,13860113.0
-2017-06-30,151.9,151.92,150.06,150.98,14540013.0,0.0,1.0,151.9,151.92,150.06,150.98,14540013.0
-2017-06-29,152.28,152.5,148.9175,151.04,23771610.0,0.0,1.0,152.28,152.5,148.9175,151.04,23771610.0
-2017-06-28,150.92,153.47,149.86,153.24,16621566.0,0.0,1.0,150.92,153.47,149.86,153.24,16621566.0
-2017-06-27,152.84,153.31,150.39,150.58,19274022.0,0.0,1.0,152.84,153.31,150.39,150.58,19274022.0
-2017-06-26,156.25,156.5,153.1954,153.59,17934289.0,0.0,1.0,156.25,156.5,153.1954,153.59,17934289.0
-2017-06-23,152.72,155.2,152.65,155.07,16192249.0,0.0,1.0,152.72,155.2,152.65,155.07,16192249.0
-2017-06-22,153.01,154.55,152.91,153.4,12783958.0,0.0,1.0,153.01,154.55,152.91,153.4,12783958.0
-2017-06-21,152.36,154.08,151.88,153.91,14760242.0,0.0,1.0,152.36,154.08,151.88,153.91,14760242.0
-2017-06-20,152.88,153.84,152.21,152.25,14557895.0,0.0,1.0,152.88,153.84,152.21,152.25,14557895.0
-2017-06-19,151.71,153.57,151.71,152.87,18678807.0,0.0,1.0,151.71,153.57,151.71,152.87,18678807.0
-2017-06-16,149.59,150.83,148.6,150.64,22169800.0,0.0,1.0,149.59,150.83,148.6,150.64,22169800.0
-2017-06-15,147.67,150.0366,146.3747,149.8,18877305.0,0.0,1.0,147.67,150.0366,146.3747,149.8,18877305.0
-2017-06-14,151.26,152.4,149.05,150.25,20552981.0,0.0,1.0,151.26,152.4,149.05,150.25,20552981.0
-2017-06-13,150.15,151.18,148.9,150.68,20316202.0,0.0,1.0,150.15,151.18,148.9,150.68,20316202.0
-2017-06-12,148.17,149.195,144.56,148.44,33238543.0,0.0,1.0,148.17,149.195,144.56,148.44,33238543.0
-2017-06-09,154.77,155.59,146.61,149.63,35256368.0,0.0,1.0,154.77,155.59,146.61,149.63,35256368.0
-2017-06-08,154.08,154.73,153.1,154.71,17539521.0,0.0,1.0,154.08,154.73,153.1,154.71,17539521.0
-2017-06-07,153.27,153.75,152.34,153.12,11822136.0,0.0,1.0,153.27,153.75,152.34,153.12,11822136.0
-2017-06-06,153.41,154.52,152.48,152.81,13291727.0,0.0,1.0,153.41,154.52,152.48,152.81,13291727.0
-2017-06-05,153.64,154.7088,153.41,153.63,12279871.0,0.0,1.0,153.64,154.7088,153.41,153.63,12279871.0
-2017-06-02,151.85,153.63,151.3,153.61,16787255.0,0.0,1.0,151.85,153.63,151.3,153.61,16787255.0
-2017-06-01,151.75,152.29,150.3,151.53,14459173.0,0.0,1.0,151.75,152.29,150.3,151.53,14459173.0
diff --git a/examples/quick/demos/stocqt/content/data/GOOG.csv b/examples/quick/demos/stocqt/content/data/GOOG.csv
deleted file mode 100644
index bde72eafe9..0000000000
--- a/examples/quick/demos/stocqt/content/data/GOOG.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,1046.72,1049.7,1044.9,1046.4,867943.0,0.0,1.0,1046.72,1049.7,1044.9,1046.4,867943.0
-2017-12-28,1051.6,1054.75,1044.77,1048.14,829623.0,0.0,1.0,1051.6,1054.75,1044.77,1048.14,829623.0
-2017-12-27,1057.39,1058.37,1048.05,1049.37,1214775.0,0.0,1.0,1057.39,1058.37,1048.05,1049.37,1214775.0
-2017-12-26,1058.07,1060.12,1050.2,1056.74,756324.0,0.0,1.0,1058.07,1060.12,1050.2,1056.74,756324.0
-2017-12-22,1061.11,1064.2,1059.44,1060.12,734566.0,0.0,1.0,1061.11,1064.2,1059.44,1060.12,734566.0
-2017-12-21,1064.95,1069.33,1061.79,1063.63,974594.0,0.0,1.0,1064.95,1069.33,1061.79,1063.63,974594.0
-2017-12-20,1071.78,1073.38,1061.52,1064.95,1266115.0,0.0,1.0,1071.78,1073.38,1061.52,1064.95,1266115.0
-2017-12-19,1075.2,1076.84,1063.55,1070.68,1254615.0,0.0,1.0,1075.2,1076.84,1063.55,1070.68,1254615.0
-2017-12-18,1066.08,1078.49,1062.0,1077.14,1531522.0,0.0,1.0,1066.08,1078.49,1062.0,1077.14,1531522.0
-2017-12-15,1054.61,1067.62,1049.5,1064.19,3142760.0,0.0,1.0,1054.61,1067.62,1049.5,1064.19,3142760.0
-2017-12-14,1045.0,1058.5,1043.11,1049.15,1545616.0,0.0,1.0,1045.0,1058.5,1043.11,1049.15,1545616.0
-2017-12-13,1046.12,1046.66,1038.38,1040.61,1207286.0,0.0,1.0,1046.12,1046.66,1038.38,1040.61,1207286.0
-2017-12-12,1039.63,1050.31,1033.69,1040.48,1269883.0,0.0,1.0,1039.63,1050.31,1033.69,1040.48,1269883.0
-2017-12-11,1035.5,1043.8,1032.05,1041.1,1119052.0,0.0,1.0,1035.5,1043.8,1032.05,1041.1,1119052.0
-2017-12-08,1037.49,1042.05,1032.52,1037.05,1277894.0,0.0,1.0,1037.49,1042.05,1032.52,1037.05,1277894.0
-2017-12-07,1020.43,1034.24,1018.07,1030.93,1387107.0,0.0,1.0,1020.43,1034.24,1018.07,1030.93,1387107.0
-2017-12-06,1001.5,1024.97,1001.14,1018.38,1254837.0,0.0,1.0,1001.5,1024.97,1001.14,1018.38,1254837.0
-2017-12-05,995.94,1020.61,988.28,1005.15,2023376.0,0.0,1.0,995.94,1020.61,988.28,1005.15,2023376.0
-2017-12-04,1012.66,1016.1,995.57,998.68,1891408.0,0.0,1.0,1012.66,1016.1,995.57,998.68,1891408.0
-2017-12-01,1015.8,1022.49,1002.02,1010.17,1895786.0,0.0,1.0,1015.8,1022.49,1002.02,1010.17,1895786.0
-2017-11-30,1022.37,1028.49,1015.0,1021.41,1684292.0,0.0,1.0,1022.37,1028.49,1015.0,1021.41,1684292.0
-2017-11-29,1042.68,1044.08,1015.65,1021.66,2414465.0,0.0,1.0,1042.68,1044.08,1015.65,1021.66,2414465.0
-2017-11-28,1055.09,1062.38,1040.0,1047.41,1341000.0,0.0,1.0,1055.09,1062.38,1040.0,1047.41,1341000.0
-2017-11-27,1040.0,1055.46,1038.44,1054.21,1284354.0,0.0,1.0,1040.0,1055.46,1038.44,1054.21,1284354.0
-2017-11-24,1035.87,1043.18,1035.0,1040.61,536958.0,0.0,1.0,1035.87,1043.18,1035.0,1040.61,536958.0
-2017-11-22,1035.0,1039.71,1031.43,1035.96,716661.0,0.0,1.0,1035.0,1039.71,1031.43,1035.96,716661.0
-2017-11-21,1023.31,1035.11,1022.66,1034.49,1083715.0,0.0,1.0,1023.31,1035.11,1022.66,1034.49,1083715.0
-2017-11-20,1020.26,1022.61,1017.5,1018.38,894844.0,0.0,1.0,1020.26,1022.61,1017.5,1018.38,894844.0
-2017-11-17,1034.01,1034.42,1017.75,1019.09,1350144.0,0.0,1.0,1034.01,1034.42,1017.75,1019.09,1350144.0
-2017-11-16,1022.52,1035.92,1022.52,1032.5,1117578.0,0.0,1.0,1022.52,1035.92,1022.52,1032.5,1117578.0
-2017-11-15,1019.21,1024.09,1015.42,1020.91,859951.0,0.0,1.0,1019.21,1024.09,1015.42,1020.91,859951.0
-2017-11-14,1022.59,1026.81,1014.15,1026.0,947273.0,0.0,1.0,1022.59,1026.81,1014.15,1026.0,947273.0
-2017-11-13,1023.42,1031.58,1022.57,1025.75,878969.0,0.0,1.0,1023.42,1031.58,1022.57,1025.75,878969.0
-2017-11-10,1026.46,1030.76,1025.28,1028.07,719227.0,0.0,1.0,1026.46,1030.76,1025.28,1028.07,719227.0
-2017-11-09,1033.99,1033.99,1019.67,1031.26,1236903.0,0.0,1.0,1033.99,1033.99,1019.67,1031.26,1236903.0
-2017-11-07,1027.27,1033.97,1025.13,1033.33,1089887.0,0.0,1.0,1027.27,1033.97,1025.13,1033.33,1089887.0
-2017-11-06,1028.99,1034.87,1025.0,1025.9,1119131.0,0.0,1.0,1028.99,1034.87,1025.0,1025.9,1119131.0
-2017-11-03,1022.11,1032.65,1020.31,1032.48,1058037.0,0.0,1.0,1022.11,1032.65,1020.31,1032.48,1058037.0
-2017-11-02,1021.76,1028.09,1013.01,1025.58,1008190.0,0.0,1.0,1021.76,1028.09,1013.01,1025.58,1008190.0
-2017-11-01,1017.21,1029.67,1016.95,1025.5,1360900.0,0.0,1.0,1017.21,1029.67,1016.95,1025.5,1360900.0
-2017-10-31,1015.22,1024.0,1010.42,1016.64,1324961.0,0.0,1.0,1015.22,1024.0,1010.42,1016.64,1324961.0
-2017-10-30,1014.0,1024.97,1007.5,1017.11,2074619.0,0.0,1.0,1014.0,1024.97,1007.5,1017.11,2074619.0
-2017-10-27,1009.19,1048.39,1008.2,1019.27,5125791.0,0.0,1.0,1009.19,1048.39,1008.2,1019.27,5125791.0
-2017-10-26,980.0,987.6,972.2,972.56,1660850.0,0.0,1.0,980.0,987.6,972.2,972.56,1660850.0
-2017-10-25,968.37,976.09,960.5201,973.33,1162606.0,0.0,1.0,968.37,976.09,960.5201,973.33,1162606.0
-2017-10-24,970.0,972.23,961.0,970.54,1155231.0,0.0,1.0,970.0,972.23,961.0,970.54,1155231.0
-2017-10-23,989.52,989.52,966.12,968.45,1431886.0,0.0,1.0,989.52,989.52,966.12,968.45,1431886.0
-2017-10-20,989.44,991.0,984.58,988.2,1120038.0,0.0,1.0,989.44,991.0,984.58,988.2,1120038.0
-2017-10-19,986.0,988.88,978.39,984.45,1282755.0,0.0,1.0,986.0,988.88,978.39,984.45,1282755.0
-2017-10-18,991.77,996.72,986.9747,992.81,1022521.0,0.0,1.0,991.77,996.72,986.9747,992.81,1022521.0
-2017-10-17,990.29,996.44,988.59,992.18,1266399.0,0.0,1.0,990.29,996.44,988.59,992.18,1266399.0
-2017-10-16,992.1,993.9065,984.0,992.0,900751.0,0.0,1.0,992.1,993.9065,984.0,992.0,900751.0
-2017-10-13,992.0,997.21,989.0,989.68,1143907.0,0.0,1.0,992.0,997.21,989.0,989.68,1143907.0
-2017-10-12,987.45,994.12,985.0,987.83,1259082.0,0.0,1.0,987.45,994.12,985.0,987.83,1259082.0
-2017-10-11,973.72,990.71,972.25,989.25,1663731.0,0.0,1.0,973.72,990.71,972.25,989.25,1663731.0
-2017-10-10,980.0,981.57,966.0801,972.6,956419.0,0.0,1.0,980.0,981.57,966.0801,972.6,956419.0
-2017-10-09,980.0,985.425,976.11,977.0,886700.0,0.0,1.0,980.0,985.425,976.11,977.0,886700.0
-2017-10-06,966.7,979.46,963.36,978.89,1142699.0,0.0,1.0,966.7,979.46,963.36,978.89,1142699.0
-2017-10-05,955.49,970.91,955.18,969.96,1202101.0,0.0,1.0,955.49,970.91,955.18,969.96,1202101.0
-2017-10-04,957.0,960.39,950.69,951.68,881380.0,0.0,1.0,957.0,960.39,950.69,951.68,881380.0
-2017-10-03,954.0,958.0,949.14,957.79,881562.0,0.0,1.0,954.0,958.0,949.14,957.79,881562.0
-2017-10-02,959.98,962.54,947.84,953.27,1222026.0,0.0,1.0,959.98,962.54,947.84,953.27,1222026.0
-2017-09-29,952.0,959.7864,951.51,959.11,1533133.0,0.0,1.0,952.0,959.7864,951.51,959.11,1533133.0
-2017-09-28,941.36,950.69,940.55,949.5,959648.0,0.0,1.0,941.36,950.69,940.55,949.5,959648.0
-2017-09-27,927.74,949.9,927.74,944.49,2202959.0,0.0,1.0,927.74,949.9,927.74,944.49,2202959.0
-2017-09-26,923.72,930.82,921.14,924.86,1652848.0,0.0,1.0,923.72,930.82,921.14,924.86,1652848.0
-2017-09-25,925.45,926.4,909.7,920.97,1822881.0,0.0,1.0,925.45,926.4,909.7,920.97,1822881.0
-2017-09-22,927.75,934.73,926.48,928.53,1038551.0,0.0,1.0,927.75,934.73,926.48,928.53,1038551.0
-2017-09-21,933.0,936.53,923.83,932.45,1207656.0,0.0,1.0,933.0,936.53,923.83,932.45,1207656.0
-2017-09-20,922.98,933.88,922.0,931.58,1518166.0,0.0,1.0,922.98,933.88,922.0,931.58,1518166.0
-2017-09-19,917.42,922.4199,912.55,921.81,902415.0,0.0,1.0,917.42,922.4199,912.55,921.81,902415.0
-2017-09-18,920.01,922.08,910.6,915.0,1263456.0,0.0,1.0,920.01,922.08,910.6,915.0,1263456.0
-2017-09-15,924.66,926.49,916.36,920.29,2475031.0,0.0,1.0,924.66,926.49,916.36,920.29,2475031.0
-2017-09-14,931.25,932.77,924.0,925.11,1389012.0,0.0,1.0,931.25,932.77,924.0,925.11,1389012.0
-2017-09-13,930.66,937.25,929.86,935.09,1066051.0,0.0,1.0,930.66,937.25,929.86,935.09,1066051.0
-2017-09-12,932.59,933.48,923.861,932.07,1120449.0,0.0,1.0,932.59,933.48,923.861,932.07,1120449.0
-2017-09-11,934.25,938.38,926.92,929.08,1247138.0,0.0,1.0,934.25,938.38,926.92,929.08,1247138.0
-2017-09-08,936.49,936.99,924.88,926.5,993832.0,0.0,1.0,936.49,936.99,924.88,926.5,993832.0
-2017-09-07,931.73,936.41,923.62,935.95,1200257.0,0.0,1.0,931.73,936.41,923.62,935.95,1200257.0
-2017-09-06,930.15,930.915,919.27,927.81,1468808.0,0.0,1.0,930.15,930.915,919.27,927.81,1468808.0
-2017-09-05,933.08,937.0,921.96,928.45,1202163.0,0.0,1.0,933.08,937.0,921.96,928.45,1202163.0
-2017-09-01,941.13,942.48,935.15,937.34,913404.0,0.0,1.0,941.13,942.48,935.15,937.34,913404.0
-2017-08-31,931.76,941.98,931.76,939.33,1553301.0,0.0,1.0,931.76,941.98,931.76,939.33,1553301.0
-2017-08-30,920.05,930.819,919.65,929.57,1282093.0,0.0,1.0,920.05,930.819,919.65,929.57,1282093.0
-2017-08-29,905.1,923.33,905.0,921.29,1180160.0,0.0,1.0,905.1,923.33,905.0,921.29,1180160.0
-2017-08-28,916.0,919.245,911.87,913.81,1072467.0,0.0,1.0,916.0,919.245,911.87,913.81,1072467.0
-2017-08-25,923.49,925.555,915.5,915.89,1040693.0,0.0,1.0,923.49,925.555,915.5,915.89,1040693.0
-2017-08-24,928.66,930.84,915.5,921.28,1218875.0,0.0,1.0,928.66,930.84,915.5,921.28,1218875.0
-2017-08-23,921.93,929.93,919.36,927.0,1077809.0,0.0,1.0,921.93,929.93,919.36,927.0,1077809.0
-2017-08-22,912.72,925.86,911.4751,924.69,1145571.0,0.0,1.0,912.72,925.86,911.4751,924.69,1145571.0
-2017-08-21,910.0,913.0,903.4,906.66,932903.0,0.0,1.0,910.0,913.0,903.4,906.66,932903.0
-2017-08-18,910.31,915.275,907.1543,910.67,1333572.0,0.0,1.0,910.31,915.275,907.1543,910.67,1333572.0
-2017-08-17,925.78,926.86,910.98,910.98,1218963.0,0.0,1.0,925.78,926.86,910.98,910.98,1218963.0
-2017-08-16,925.29,932.7,923.445,926.96,988604.0,0.0,1.0,925.29,932.7,923.445,926.96,988604.0
-2017-08-15,924.23,926.5499,919.82,922.22,873070.0,0.0,1.0,924.23,926.5499,919.82,922.22,873070.0
-2017-08-14,922.53,924.668,918.19,922.67,1047828.0,0.0,1.0,922.53,924.668,918.19,922.67,1047828.0
-2017-08-11,907.97,917.78,905.58,914.39,1190458.0,0.0,1.0,907.97,917.78,905.58,914.39,1190458.0
-2017-08-10,917.55,919.26,906.13,907.24,1722296.0,0.0,1.0,917.55,919.26,906.13,907.24,1722296.0
-2017-08-09,920.61,925.98,917.2501,922.9,1169431.0,0.0,1.0,920.61,925.98,917.2501,922.9,1169431.0
-2017-08-08,927.09,935.814,925.6095,926.79,1039394.0,0.0,1.0,927.09,935.814,925.6095,926.79,1039394.0
-2017-08-07,929.06,931.7,926.5,929.36,1012296.0,0.0,1.0,929.06,931.7,926.5,929.36,1012296.0
-2017-08-04,926.75,930.3068,923.03,927.96,1019159.0,0.0,1.0,926.75,930.3068,923.03,927.96,1019159.0
-2017-08-03,930.34,932.24,922.24,923.65,1179126.0,0.0,1.0,930.34,932.24,922.24,923.65,1179126.0
-2017-08-02,928.61,932.6,916.68,930.39,1816343.0,0.0,1.0,928.61,932.6,916.68,930.39,1816343.0
-2017-08-01,932.38,937.447,929.26,930.83,1211553.0,0.0,1.0,932.38,937.447,929.26,930.83,1211553.0
-2017-07-31,941.89,943.59,926.04,930.5,1952716.0,0.0,1.0,941.89,943.59,926.04,930.5,1952716.0
-2017-07-28,929.4,943.83,927.5,941.53,1775076.0,0.0,1.0,929.4,943.83,927.5,941.53,1775076.0
-2017-07-27,951.78,951.78,920.0,934.09,3095263.0,0.0,1.0,951.78,951.78,920.0,934.09,3095263.0
-2017-07-26,954.68,955.0,942.2788,947.8,2056013.0,0.0,1.0,954.68,955.0,942.2788,947.8,2056013.0
-2017-07-25,953.81,959.7,945.4,950.7,4626086.0,0.0,1.0,953.81,959.7,945.4,950.7,4626086.0
-2017-07-24,972.22,986.2,970.77,980.34,2634669.0,0.0,1.0,972.22,986.2,970.77,980.34,2634669.0
-2017-07-21,962.25,973.23,960.15,972.92,1665103.0,0.0,1.0,962.25,973.23,960.15,972.92,1665103.0
-2017-07-20,975.0,975.9,961.51,968.15,1577103.0,0.0,1.0,975.0,975.9,961.51,968.15,1577103.0
-2017-07-19,967.84,973.04,964.03,970.89,1212814.0,0.0,1.0,967.84,973.04,964.03,970.89,1212814.0
-2017-07-18,953.0,968.04,950.6,965.4,1131130.0,0.0,1.0,953.0,968.04,950.6,965.4,1131130.0
-2017-07-17,957.0,960.74,949.2407,953.42,1141026.0,0.0,1.0,957.0,960.74,949.2407,953.42,1141026.0
-2017-07-14,952.0,956.91,948.005,955.99,1017632.0,0.0,1.0,952.0,956.91,948.005,955.99,1017632.0
-2017-07-13,946.29,954.45,943.01,947.16,1291782.0,0.0,1.0,946.29,954.45,943.01,947.16,1291782.0
-2017-07-12,938.68,946.3,934.47,943.83,1505982.0,0.0,1.0,938.68,946.3,934.47,943.83,1505982.0
-2017-07-11,929.54,931.43,922.0,930.09,1093281.0,0.0,1.0,929.54,931.43,922.0,930.09,1093281.0
-2017-07-10,921.77,930.38,919.59,928.8,1189085.0,0.0,1.0,921.77,930.38,919.59,928.8,1189085.0
-2017-07-07,908.85,921.54,908.85,918.59,1588034.0,0.0,1.0,908.85,921.54,908.85,918.59,1588034.0
-2017-07-06,904.12,914.9444,899.7,906.69,1409533.0,0.0,1.0,904.12,914.9444,899.7,906.69,1409533.0
-2017-07-05,901.76,914.51,898.5,911.94,1743497.0,0.0,1.0,901.76,914.51,898.5,911.94,1743497.0
-2017-07-03,912.18,913.94,894.79,898.7,1710189.0,0.0,1.0,912.18,913.94,894.79,898.7,1710189.0
-2017-06-30,926.05,926.05,908.31,908.73,2035931.0,0.0,1.0,926.05,926.05,908.31,908.73,2035931.0
-2017-06-29,929.92,931.26,910.62,917.79,3248393.0,0.0,1.0,929.92,931.26,910.62,917.79,3248393.0
-2017-06-28,929.0,942.75,916.0,940.49,2712222.0,0.0,1.0,929.0,942.75,916.0,940.49,2712222.0
-2017-06-27,942.46,948.29,926.85,927.33,2553771.0,0.0,1.0,942.46,948.29,926.85,927.33,2553771.0
-2017-06-26,969.9,973.31,950.79,952.27,1581031.0,0.0,1.0,969.9,973.31,950.79,952.27,1581031.0
-2017-06-23,956.83,966.0,954.2,965.59,1394008.0,0.0,1.0,956.83,966.0,954.2,965.59,1394008.0
-2017-06-22,958.7,960.72,954.55,957.09,940373.0,0.0,1.0,958.7,960.72,954.55,957.09,940373.0
-2017-06-21,953.64,960.1,950.76,959.45,1192342.0,0.0,1.0,953.64,960.1,950.76,959.45,1192342.0
-2017-06-20,957.52,961.62,950.01,950.63,1111840.0,0.0,1.0,957.52,961.62,950.01,950.63,1111840.0
-2017-06-19,949.96,959.99,949.05,957.37,1494191.0,0.0,1.0,949.96,959.99,949.05,957.37,1494191.0
-2017-06-16,940.0,942.04,931.595,939.78,2921393.0,0.0,1.0,940.0,942.04,931.595,939.78,2921393.0
-2017-06-15,933.97,943.339,924.44,942.31,2055953.0,0.0,1.0,933.97,943.339,924.44,942.31,2055953.0
-2017-06-14,959.92,961.15,942.25,950.76,1477033.0,0.0,1.0,959.92,961.15,942.25,950.76,1477033.0
-2017-06-13,951.91,959.98,944.09,953.4,1995350.0,0.0,1.0,951.91,959.98,944.09,953.4,1995350.0
-2017-06-12,939.56,949.355,915.2328,942.9,3731589.0,0.0,1.0,939.56,949.355,915.2328,942.9,3731589.0
-2017-06-09,984.5,984.5,935.63,949.83,3270248.0,0.0,1.0,984.5,984.5,935.63,949.83,3270248.0
-2017-06-08,982.35,984.57,977.2,983.41,1451232.0,0.0,1.0,982.35,984.57,977.2,983.41,1451232.0
-2017-06-07,979.65,984.15,975.77,981.08,1429834.0,0.0,1.0,979.65,984.15,975.77,981.08,1429834.0
-2017-06-06,983.16,988.25,975.14,976.57,1796904.0,0.0,1.0,983.16,988.25,975.14,976.57,1796904.0
-2017-06-05,976.55,986.91,975.1,983.68,1221971.0,0.0,1.0,976.55,986.91,975.1,983.68,1221971.0
-2017-06-02,969.46,975.88,966.0,975.6,1717212.0,0.0,1.0,969.46,975.88,966.0,975.6,1717212.0
-2017-06-01,968.95,971.5,960.01,966.95,1403200.0,0.0,1.0,968.95,971.5,960.01,966.95,1403200.0
diff --git a/examples/quick/demos/stocqt/content/data/GOOGL.csv b/examples/quick/demos/stocqt/content/data/GOOGL.csv
deleted file mode 100644
index 883f78e5f5..0000000000
--- a/examples/quick/demos/stocqt/content/data/GOOGL.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,1055.49,1058.05,1052.7,1053.4,1156357.0,0.0,1.0,1055.49,1058.05,1052.7,1053.4,1156357.0
-2017-12-28,1062.25,1064.84,1053.38,1055.95,982285.0,0.0,1.0,1062.25,1064.84,1053.38,1055.95,982285.0
-2017-12-27,1066.6,1068.27,1058.38,1060.2,1027634.0,0.0,1.0,1066.6,1068.27,1058.38,1060.2,1027634.0
-2017-12-26,1068.64,1068.86,1058.64,1065.85,914574.0,0.0,1.0,1068.64,1068.86,1058.64,1065.85,914574.0
-2017-12-22,1070.0,1071.72,1067.64,1068.86,860800.0,0.0,1.0,1070.0,1071.72,1067.64,1068.86,860800.0
-2017-12-21,1075.39,1077.52,1069.0,1070.85,1211012.0,0.0,1.0,1075.39,1077.52,1069.0,1070.85,1211012.0
-2017-12-20,1080.92,1081.23,1068.6,1073.56,1429035.0,0.0,1.0,1080.92,1081.23,1068.6,1073.56,1429035.0
-2017-12-19,1083.02,1084.97,1072.27,1079.78,1287930.0,0.0,1.0,1083.02,1084.97,1072.27,1079.78,1287930.0
-2017-12-18,1076.45,1086.49,1070.37,1085.09,1482768.0,0.0,1.0,1076.45,1086.49,1070.37,1085.09,1482768.0
-2017-12-15,1063.78,1075.25,1060.09,1072.0,3080738.0,0.0,1.0,1063.78,1075.25,1060.09,1072.0,3080738.0
-2017-12-14,1055.49,1067.08,1053.6,1057.47,1531504.0,0.0,1.0,1055.49,1067.08,1053.6,1057.47,1531504.0
-2017-12-13,1052.08,1055.48,1046.58,1051.39,1369580.0,0.0,1.0,1052.08,1055.48,1046.58,1051.39,1369580.0
-2017-12-12,1050.0,1062.5,1044.87,1048.77,1684977.0,0.0,1.0,1050.0,1062.5,1044.87,1048.77,1684977.0
-2017-12-11,1051.11,1056.0,1044.12,1051.97,1096997.0,0.0,1.0,1051.11,1056.0,1044.12,1051.97,1096997.0
-2017-12-08,1051.81,1056.42,1045.86,1049.38,1479665.0,0.0,1.0,1051.81,1056.42,1045.86,1049.38,1479665.0
-2017-12-07,1036.07,1048.92,1035.36,1044.57,1437448.0,0.0,1.0,1036.07,1048.92,1035.36,1044.57,1437448.0
-2017-12-06,1016.52,1039.58,1015.31,1032.72,1369276.0,0.0,1.0,1016.52,1039.58,1015.31,1032.72,1369276.0
-2017-12-05,1010.99,1036.68,1002.32,1019.6,1927802.0,0.0,1.0,1010.99,1036.68,1002.32,1019.6,1927802.0
-2017-12-04,1027.8,1031.34,1009.22,1011.87,1896325.0,0.0,1.0,1027.8,1031.34,1009.22,1011.87,1896325.0
-2017-12-01,1030.41,1037.24,1016.9,1025.07,1850541.0,0.0,1.0,1030.41,1037.24,1016.9,1025.07,1850541.0
-2017-11-30,1039.94,1044.14,1030.07,1036.17,2190379.0,0.0,1.0,1039.94,1044.14,1030.07,1036.17,2190379.0
-2017-11-29,1056.18,1058.77,1029.65,1037.38,2737664.0,0.0,1.0,1056.18,1058.77,1029.65,1037.38,2737664.0
-2017-11-28,1073.99,1080.0,1054.54,1063.29,1694098.0,0.0,1.0,1073.99,1080.0,1054.54,1063.29,1694098.0
-2017-11-27,1058.57,1073.04,1054.77,1072.01,1708195.0,0.0,1.0,1058.57,1073.04,1054.77,1072.01,1708195.0
-2017-11-24,1054.39,1060.07,1051.92,1056.52,825342.0,0.0,1.0,1054.39,1060.07,1051.92,1056.52,825342.0
-2017-11-22,1051.16,1055.43,1047.25,1051.92,721498.0,0.0,1.0,1051.16,1055.43,1047.25,1051.92,721498.0
-2017-11-21,1040.04,1050.39,1039.14,1050.3,1075568.0,0.0,1.0,1040.04,1050.39,1039.14,1050.3,1075568.0
-2017-11-20,1036.0,1038.7,1032.68,1034.66,850423.0,0.0,1.0,1036.0,1038.7,1032.68,1034.66,850423.0
-2017-11-17,1049.8,1051.0,1033.73,1035.89,1286044.0,0.0,1.0,1049.8,1051.0,1033.73,1035.89,1286044.0
-2017-11-16,1038.75,1051.76,1038.0,1048.47,1125995.0,0.0,1.0,1038.75,1051.76,1038.0,1048.47,1125995.0
-2017-11-15,1035.0,1039.63,1030.76,1036.41,900695.0,0.0,1.0,1035.0,1039.63,1030.76,1036.41,900695.0
-2017-11-14,1037.72,1042.3,1029.33,1041.64,982782.0,0.0,1.0,1037.72,1042.3,1029.33,1041.64,982782.0
-2017-11-13,1040.8,1048.74,1039.26,1041.2,914852.0,0.0,1.0,1040.8,1048.74,1039.26,1041.2,914852.0
-2017-11-10,1043.87,1046.63,1041.22,1044.15,955500.0,0.0,1.0,1043.87,1046.63,1041.22,1044.15,955500.0
-2017-11-09,1048.0,1050.88,1035.85,1047.72,1776722.0,0.0,1.0,1048.0,1050.88,1035.85,1047.72,1776722.0
-2017-11-07,1049.65,1053.41,1043.0,1052.39,1254965.0,0.0,1.0,1049.65,1053.41,1043.0,1052.39,1254965.0
-2017-11-06,1049.1,1052.59,1042.0,1042.68,897897.0,0.0,1.0,1049.1,1052.59,1042.0,1042.68,897897.0
-2017-11-03,1042.75,1050.66,1037.65,1049.99,1370874.0,0.0,1.0,1042.75,1050.66,1037.65,1049.99,1370874.0
-2017-11-02,1039.99,1045.52,1028.66,1042.97,1233333.0,0.0,1.0,1039.99,1045.52,1028.66,1042.97,1233333.0
-2017-11-01,1036.32,1047.86,1034.0,1042.6,2105729.0,0.0,1.0,1036.32,1047.86,1034.0,1042.6,2105729.0
-2017-10-31,1033.0,1041.0,1026.3,1033.04,1490660.0,0.0,1.0,1033.0,1041.0,1026.3,1033.04,1490660.0
-2017-10-30,1029.16,1039.83,1022.33,1033.13,2245352.0,0.0,1.0,1029.16,1039.83,1022.33,1033.13,2245352.0
-2017-10-27,1030.99,1063.62,1026.85,1033.67,5139945.0,0.0,1.0,1030.99,1063.62,1026.85,1033.67,5139945.0
-2017-10-26,998.47,1006.51,990.47,991.42,1827682.0,0.0,1.0,998.47,1006.51,990.47,991.42,1827682.0
-2017-10-25,986.27,994.43,977.722,991.46,1368042.0,0.0,1.0,986.27,994.43,977.722,991.46,1368042.0
-2017-10-24,986.5,989.26,977.08,988.49,1416283.0,0.0,1.0,986.5,989.26,977.08,988.49,1416283.0
-2017-10-23,1005.18,1005.79,983.1,985.54,1623580.0,0.0,1.0,1005.18,1005.79,983.1,985.54,1623580.0
-2017-10-20,1007.05,1008.65,1002.27,1005.07,1568454.0,0.0,1.0,1007.05,1008.65,1002.27,1005.07,1568454.0
-2017-10-19,1004.75,1007.32,997.3,1001.84,1677021.0,0.0,1.0,1004.75,1007.32,997.3,1001.84,1677021.0
-2017-10-18,1011.05,1016.31,1005.32,1012.74,1270218.0,0.0,1.0,1011.05,1016.31,1005.32,1012.74,1270218.0
-2017-10-17,1007.44,1014.56,1006.05,1011.0,991412.0,0.0,1.0,1007.44,1014.56,1006.05,1011.0,991412.0
-2017-10-16,1009.63,1012.0,1001.52,1009.35,1066744.0,0.0,1.0,1009.63,1012.0,1001.52,1009.35,1066744.0
-2017-10-13,1009.11,1014.76,1007.06,1007.87,1308881.0,0.0,1.0,1009.11,1014.76,1007.06,1007.87,1308881.0
-2017-10-12,1003.84,1011.54,1001.1,1005.65,1521137.0,0.0,1.0,1003.84,1011.54,1001.1,1005.65,1521137.0
-2017-10-11,989.04,1007.56,987.94,1005.65,1748443.0,0.0,1.0,989.04,1007.56,987.94,1005.65,1748443.0
-2017-10-10,995.3,997.47,981.11,987.8,1158864.0,0.0,1.0,995.3,997.47,981.11,987.8,1158864.0
-2017-10-09,995.0,1000.46,991.5,992.31,1151035.0,0.0,1.0,995.0,1000.46,991.5,992.31,1151035.0
-2017-10-06,980.0,994.26,978.51,993.64,1490744.0,0.0,1.0,980.0,994.26,978.51,993.64,1490744.0
-2017-10-05,972.79,986.5085,970.27,985.19,1627255.0,0.0,1.0,972.79,986.5085,970.27,985.19,1627255.0
-2017-10-04,971.76,974.4,965.61,966.78,896531.0,0.0,1.0,971.76,974.4,965.61,966.78,896531.0
-2017-10-03,967.56,972.44,962.705,972.08,1080312.0,0.0,1.0,967.56,972.44,962.705,972.08,1080312.0
-2017-10-02,975.65,977.74,961.95,967.47,1466444.0,0.0,1.0,975.65,977.74,961.95,967.47,1466444.0
-2017-09-29,966.0,975.81,966.0,973.72,1906445.0,0.0,1.0,966.0,975.81,966.0,973.72,1906445.0
-2017-09-28,956.25,966.18,955.55,964.81,1347750.0,0.0,1.0,956.25,966.18,955.55,964.81,1347750.0
-2017-09-27,942.74,965.43,941.95,959.9,2313498.0,0.0,1.0,942.74,965.43,941.95,959.9,2313498.0
-2017-09-26,936.69,944.08,935.12,937.43,1618182.0,0.0,1.0,936.69,944.08,935.12,937.43,1618182.0
-2017-09-25,939.45,939.75,924.5101,934.28,1847436.0,0.0,1.0,939.45,939.75,924.5101,934.28,1847436.0
-2017-09-22,942.77,950.0,940.835,943.26,1067617.0,0.0,1.0,942.77,950.0,940.835,943.26,1067617.0
-2017-09-21,948.13,952.8,939.38,947.55,1302726.0,0.0,1.0,948.13,952.8,939.38,947.55,1302726.0
-2017-09-20,937.73,950.0,937.5,947.54,1896919.0,0.0,1.0,937.73,950.0,937.5,947.54,1896919.0
-2017-09-19,933.41,937.94,926.66,936.86,1217430.0,0.0,1.0,933.41,937.94,926.66,936.86,1217430.0
-2017-09-18,935.01,936.86,925.4,929.75,1445532.0,0.0,1.0,935.01,936.86,925.4,929.75,1445532.0
-2017-09-15,940.09,941.75,931.25,935.29,1940047.0,0.0,1.0,940.09,941.75,931.25,935.29,1940047.0
-2017-09-14,946.0,948.03,938.356,940.13,1415168.0,0.0,1.0,946.0,948.03,938.356,940.13,1415168.0
-2017-09-13,945.5,952.85,944.74,950.44,1092849.0,0.0,1.0,945.5,952.85,944.74,950.44,1092849.0
-2017-09-12,946.92,948.085,937.5,946.65,1245767.0,0.0,1.0,946.92,948.085,937.5,946.65,1245767.0
-2017-09-11,947.2,952.68,941.0,943.29,1317796.0,0.0,1.0,947.2,952.68,941.0,943.29,1317796.0
-2017-09-08,949.7,950.7,940.01,941.41,996449.0,0.0,1.0,949.7,950.7,940.01,941.41,996449.0
-2017-09-07,944.25,950.4965,937.53,949.89,1103286.0,0.0,1.0,944.25,950.4965,937.53,949.89,1103286.0
-2017-09-06,943.87,944.5,932.68,942.02,1375952.0,0.0,1.0,943.87,944.5,932.68,942.02,1375952.0
-2017-09-05,946.86,951.3854,935.6,941.48,1455058.0,0.0,1.0,946.86,951.3854,935.6,941.48,1455058.0
-2017-09-01,957.47,958.33,950.28,951.99,1034769.0,0.0,1.0,957.47,958.33,950.28,951.99,1034769.0
-2017-08-31,946.3,957.195,946.25,955.24,1672387.0,0.0,1.0,946.3,957.195,946.25,955.24,1672387.0
-2017-08-30,935.67,945.86,934.05,943.63,1112814.0,0.0,1.0,935.67,945.86,934.05,943.63,1112814.0
-2017-08-29,919.95,938.19,919.31,935.75,1144834.0,0.0,1.0,919.95,938.19,919.31,935.75,1144834.0
-2017-08-28,931.88,934.85,926.11,928.13,1025199.0,0.0,1.0,931.88,934.85,926.11,928.13,1025199.0
-2017-08-25,939.21,940.73,930.1,930.5,1169101.0,0.0,1.0,939.21,940.73,930.1,930.5,1169101.0
-2017-08-24,943.71,946.31,930.74,936.89,1249098.0,0.0,1.0,943.71,946.31,930.74,936.89,1249098.0
-2017-08-23,937.0,945.425,935.24,942.58,1126487.0,0.0,1.0,937.0,945.425,935.24,942.58,1126487.0
-2017-08-22,926.96,941.9617,926.17,940.4,1711377.0,0.0,1.0,926.96,941.9617,926.17,940.4,1711377.0
-2017-08-21,925.77,928.25,918.6,920.87,1292624.0,0.0,1.0,925.77,928.25,918.6,920.87,1292624.0
-2017-08-18,926.98,931.02,923.45,926.18,1327288.0,0.0,1.0,926.98,931.02,923.45,926.18,1327288.0
-2017-08-17,942.95,943.81,927.64,927.66,1653779.0,0.0,1.0,942.95,943.81,927.64,927.66,1653779.0
-2017-08-16,941.25,949.9,940.0391,944.27,1329301.0,0.0,1.0,941.25,949.9,940.0391,944.27,1329301.0
-2017-08-15,941.03,943.07,936.64,938.08,1006064.0,0.0,1.0,941.03,943.07,936.64,938.08,1006064.0
-2017-08-14,939.07,941.04,934.485,938.93,1140212.0,0.0,1.0,939.07,941.04,934.485,938.93,1140212.0
-2017-08-11,923.71,933.36,921.22,930.09,1589808.0,0.0,1.0,923.71,933.36,921.22,930.09,1589808.0
-2017-08-10,935.0,936.3,921.7768,923.59,2657279.0,0.0,1.0,935.0,936.3,921.7768,923.59,2657279.0
-2017-08-09,938.45,943.76,933.92,940.08,1360604.0,0.0,1.0,938.45,943.76,933.92,940.08,1360604.0
-2017-08-08,944.29,952.49,942.48,944.19,1438418.0,0.0,1.0,944.29,952.49,942.48,944.19,1438418.0
-2017-08-07,947.52,948.96,943.5,945.75,1405132.0,0.0,1.0,947.52,948.96,943.5,945.75,1405132.0
-2017-08-04,943.95,947.54,939.795,945.79,1192871.0,0.0,1.0,943.95,947.54,939.795,945.79,1192871.0
-2017-08-03,949.1,950.0,939.44,940.3,1028591.0,0.0,1.0,949.1,950.0,939.44,940.3,1028591.0
-2017-08-02,948.37,949.1,932.521,947.64,2019979.0,0.0,1.0,948.37,949.1,932.521,947.64,2019979.0
-2017-08-01,947.81,954.49,944.96,946.56,1205799.0,0.0,1.0,947.81,954.49,944.96,946.56,1205799.0
-2017-07-31,960.0,961.1925,941.725,945.5,2268160.0,0.0,1.0,960.0,961.1925,941.725,945.5,2268160.0
-2017-07-28,947.99,961.79,945.31,958.33,1795477.0,0.0,1.0,947.99,961.79,945.31,958.33,1795477.0
-2017-07-27,969.18,969.52,937.06,952.51,3685905.0,0.0,1.0,969.18,969.52,937.06,952.51,3685905.0
-2017-07-26,972.78,973.95,960.23,965.31,2166225.0,0.0,1.0,972.78,973.95,960.23,965.31,2166225.0
-2017-07-25,970.7,976.73,963.8,969.03,5793414.0,0.0,1.0,970.7,976.73,963.8,969.03,5793414.0
-2017-07-24,994.1,1006.19,990.2728,998.31,3053176.0,0.0,1.0,994.1,1006.19,990.2728,998.31,3053176.0
-2017-07-21,989.0,995.11,984.17,993.84,1412108.0,0.0,1.0,989.0,995.11,984.17,993.84,1412108.0
-2017-07-20,997.0,998.68,984.62,992.19,1410290.0,0.0,1.0,997.0,998.68,984.62,992.19,1410290.0
-2017-07-19,990.01,995.6,987.01,992.77,1392709.0,0.0,1.0,990.01,995.6,987.01,992.77,1392709.0
-2017-07-18,973.36,990.85,972.04,986.95,1398920.0,0.0,1.0,973.36,990.85,972.04,986.95,1398920.0
-2017-07-17,976.32,983.35,970.8,975.96,1644618.0,0.0,1.0,976.32,983.35,970.8,975.96,1644618.0
-2017-07-14,974.0,977.54,970.15,976.91,1048240.0,0.0,1.0,974.0,977.54,970.15,976.91,1048240.0
-2017-07-13,970.8,978.7,964.8,968.7175,1519987.0,0.0,1.0,970.8,978.7,964.8,968.7175,1519987.0
-2017-07-12,960.86,969.63,957.04,967.66,1589548.0,0.0,1.0,960.86,969.63,957.04,967.66,1589548.0
-2017-07-11,950.52,954.89,945.12,953.53,1444540.0,0.0,1.0,950.52,954.89,945.12,953.53,1444540.0
-2017-07-10,941.95,953.13,941.95,951.0,1409850.0,0.0,1.0,941.95,953.13,941.95,951.0,1409850.0
-2017-07-07,930.985,944.66,929.79,940.81,1614080.0,0.0,1.0,930.985,944.66,929.79,940.81,1614080.0
-2017-07-06,925.0,936.14,919.85,927.69,1941822.0,0.0,1.0,925.0,936.14,919.85,927.69,1941822.0
-2017-07-05,924.2,936.29,918.6305,932.26,2054927.0,0.0,1.0,924.2,936.29,918.6305,932.26,2054927.0
-2017-07-03,933.22,934.24,915.31,919.46,1694587.0,0.0,1.0,933.22,934.24,915.31,919.46,1694587.0
-2017-06-30,943.99,944.9995,929.61,929.68,2185444.0,0.0,1.0,943.99,944.9995,929.61,929.68,2185444.0
-2017-06-29,951.35,951.66,929.6,937.82,3182331.0,0.0,1.0,951.35,951.66,929.6,937.82,3182331.0
-2017-06-28,950.66,963.24,936.16,961.01,2713366.0,0.0,1.0,950.66,963.24,936.16,961.01,2713366.0
-2017-06-27,961.6,967.22,947.09,948.09,2428048.0,0.0,1.0,961.6,967.22,947.09,948.09,2428048.0
-2017-06-26,990.0,993.99,970.33,972.09,1505655.0,0.0,1.0,990.0,993.99,970.33,972.09,1505655.0
-2017-06-23,975.5,986.62,974.46,986.09,1439728.0,0.0,1.0,975.5,986.62,974.46,986.09,1439728.0
-2017-06-22,976.87,980.5,973.3148,976.62,940086.0,0.0,1.0,976.87,980.5,973.3148,976.62,940086.0
-2017-06-21,970.79,979.67,969.16,978.59,1141315.0,0.0,1.0,970.79,979.67,969.16,978.59,1141315.0
-2017-06-20,975.31,980.79,968.2,968.99,1273013.0,0.0,1.0,975.31,980.79,968.2,968.99,1273013.0
-2017-06-19,969.65,979.3,968.2,975.22,1449343.0,0.0,1.0,969.65,979.3,968.2,975.22,1449343.0
-2017-06-16,957.91,959.95,948.7,958.62,2484914.0,0.0,1.0,957.91,959.95,948.7,958.62,2484914.0
-2017-06-15,948.02,960.6775,940.37,960.18,2349212.0,0.0,1.0,948.02,960.6775,940.37,960.18,2349212.0
-2017-06-14,975.5,979.7,959.5103,967.93,1489046.0,0.0,1.0,975.5,979.7,959.5103,967.93,1489046.0
-2017-06-13,972.04,977.91,962.01,970.5,1992456.0,0.0,1.0,972.04,977.91,962.01,970.5,1992456.0
-2017-06-12,958.72,968.0,936.795,961.81,4167184.0,0.0,1.0,958.72,968.0,936.795,961.81,4167184.0
-2017-06-09,1005.49,1005.5,953.37,970.12,3613964.0,0.0,1.0,1005.49,1005.5,953.37,970.12,3613964.0
-2017-06-08,1004.23,1005.6,996.62,1004.28,1657881.0,0.0,1.0,1004.23,1005.6,996.62,1004.28,1657881.0
-2017-06-07,998.82,1003.91,995.81,1001.59,1348198.0,0.0,1.0,998.82,1003.91,995.81,1001.59,1348198.0
-2017-06-06,1003.31,1008.61,994.8,996.68,1517356.0,0.0,1.0,1003.31,1008.61,994.8,996.68,1517356.0
-2017-06-05,997.89,1007.4,995.45,1003.88,1353264.0,0.0,1.0,997.89,1007.4,995.45,1003.88,1353264.0
-2017-06-02,988.59,996.48,987.07,996.12,1719720.0,0.0,1.0,988.59,996.48,987.07,996.12,1719720.0
-2017-06-01,990.96,993.14,981.29,988.29,1295552.0,0.0,1.0,990.96,993.14,981.29,988.29,1295552.0
diff --git a/examples/quick/demos/stocqt/content/data/INTC.csv b/examples/quick/demos/stocqt/content/data/INTC.csv
deleted file mode 100644
index 9e762ffb43..0000000000
--- a/examples/quick/demos/stocqt/content/data/INTC.csv
+++ /dev/null
@@ -1,147 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,46.21,46.49,46.09,46.16,17136416.0,0.0,1.0,46.21,46.49,46.09,46.16,17136416.0
-2017-12-28,46.36,46.36,45.95,46.22,9279766.0,0.0,1.0,46.36,46.36,45.95,46.22,9279766.0
-2017-12-27,46.11,46.36,46.0,46.11,12412977.0,0.0,1.0,46.11,46.36,46.0,46.11,12412977.0
-2017-12-26,46.28,46.47,45.95,46.08,15477747.0,0.0,1.0,46.28,46.47,45.95,46.08,15477747.0
-2017-12-22,46.33,47.02,46.02,46.7,33404280.0,0.0,1.0,46.33,47.02,46.02,46.7,33404280.0
-2017-12-21,47.54,47.59,46.56,46.76,42113273.0,0.0,1.0,47.54,47.59,46.56,46.76,42113273.0
-2017-12-20,47.47,47.64,46.66,47.56,39536777.0,0.0,1.0,47.47,47.64,46.66,47.56,39536777.0
-2017-12-19,46.3,47.26,45.89,47.04,39973826.0,0.0,1.0,46.3,47.26,45.89,47.04,39973826.0
-2017-12-18,45.15,46.35,45.04,46.26,49305190.0,0.0,1.0,45.15,46.35,45.04,46.26,49305190.0
-2017-12-15,43.4,44.84,43.07,44.56,44377039.0,0.0,1.0,43.4,44.84,43.07,44.56,44377039.0
-2017-12-14,43.43,43.57,43.015,43.26,18871565.0,0.0,1.0,43.43,43.57,43.015,43.26,18871565.0
-2017-12-13,43.65,43.66,43.24,43.34,21055298.0,0.0,1.0,43.65,43.66,43.24,43.34,21055298.0
-2017-12-12,43.47,43.62,43.08,43.33,15571482.0,0.0,1.0,43.47,43.62,43.08,43.33,15571482.0
-2017-12-11,43.28,43.78,43.25,43.66,18840783.0,0.0,1.0,43.28,43.78,43.25,43.66,18840783.0
-2017-12-08,43.35,43.58,43.11,43.35,22833083.0,0.0,1.0,43.35,43.58,43.11,43.35,22833083.0
-2017-12-07,43.46,43.6,42.78,43.08,31193561.0,0.0,1.0,43.46,43.6,42.78,43.08,31193561.0
-2017-12-06,43.14,43.72,42.67,43.45,24497550.0,0.0,1.0,43.14,43.72,42.67,43.45,24497550.0
-2017-12-05,44.6,44.9,43.23,43.44,30112131.0,0.0,1.0,44.6,44.9,43.23,43.44,30112131.0
-2017-12-04,45.02,45.3,44.33,44.49,26829460.0,0.0,1.0,45.02,45.3,44.33,44.49,26829460.0
-2017-12-01,44.73,44.84,43.53,44.68,26393385.0,0.0,1.0,44.73,44.84,43.53,44.68,26393385.0
-2017-11-30,44.36,45.2,44.33,44.84,32735416.0,0.0,1.0,44.36,45.2,44.33,44.84,32735416.0
-2017-11-29,44.85,45.09,43.77,43.95,26246867.0,0.0,1.0,44.85,45.09,43.77,43.95,26246867.0
-2017-11-28,44.65,44.84,44.32,44.73,19084500.0,0.0,1.0,44.65,44.84,44.32,44.73,19084500.0
-2017-11-27,44.42,44.61,44.2736,44.49,17187942.0,0.0,1.0,44.42,44.61,44.2736,44.49,17187942.0
-2017-11-24,44.55,44.775,44.43,44.75,6465615.0,0.0,1.0,44.55,44.775,44.43,44.75,6465615.0
-2017-11-22,44.94,44.95,44.535,44.65,19191241.0,0.0,1.0,44.94,44.95,44.535,44.65,19191241.0
-2017-11-21,44.72,45.22,44.71,44.94,20730988.0,0.0,1.0,44.72,45.22,44.71,44.94,20730988.0
-2017-11-20,44.73,45.115,44.5,44.62,22162614.0,0.0,1.0,44.73,45.115,44.5,44.62,22162614.0
-2017-11-17,45.5,45.62,44.62,44.63,62637555.0,0.0,1.0,45.5,45.62,44.62,44.63,62637555.0
-2017-11-16,45.63,46.07,45.46,45.65,21446297.0,0.0,1.0,45.63,46.07,45.46,45.65,21446297.0
-2017-11-15,45.39,45.805,45.1725,45.46,16781344.0,0.0,1.0,45.39,45.805,45.1725,45.46,16781344.0
-2017-11-14,45.7,45.92,45.32,45.86,20747874.0,0.0,1.0,45.7,45.92,45.32,45.86,20747874.0
-2017-11-13,45.26,45.94,45.25,45.75,18923183.0,0.0,1.0,45.26,45.94,45.25,45.75,18923183.0
-2017-11-10,46.04,46.09,45.38,45.58,23953470.0,0.0,1.0,46.04,46.09,45.38,45.58,23953470.0
-2017-11-09,46.05,46.39,45.65,46.3,24830309.0,0.0,1.0,46.05,46.39,45.65,46.3,24830309.0
-2017-11-07,46.7,47.09,46.39,46.78,23074092.0,0.0,1.0,46.7,47.09,46.39,46.78,23074092.0
-2017-11-06,46.6,46.74,46.09,46.7,31865449.0,0.273,1.0,46.329167819811,46.468354160901,45.822131862985,46.428586634875,31865449.0
-2017-11-03,47.2,47.3,45.6,46.34,38647115.0,0.0,1.0,46.652955722779,46.751796730667,45.071499596583,45.802923054949,38647115.0
-2017-11-02,46.61,47.23,46.213,47.1,37260192.0,0.0,1.0,46.069793776245,46.682608025146,45.677394974932,46.554114714892,37260192.0
-2017-11-01,45.97,46.71,45.59,46.71,47077781.0,0.0,1.0,45.437211325766,46.168634784132,45.061615495795,46.168634784132,47077781.0
-2017-10-31,45.2,45.8,44.65,45.49,46206973.0,0.0,1.0,44.676135565035,45.269181612358,44.132510021655,44.962774487908,46206973.0
-2017-10-30,44.48,45.19,43.88,44.37,46012316.0,0.0,1.0,43.964480308246,44.666251464246,43.371434260923,43.85575519957,46012316.0
-2017-10-27,43.3,45.0,43.1,44.4,88413551.0,0.0,1.0,42.798156415177,44.47845354926,42.600474399402,43.885407501937,88413551.0
-2017-10-26,40.91,41.575,40.71,41.35,35618913.0,0.0,1.0,40.435856326672,41.093149029122,40.238174310897,40.870756761376,35618913.0
-2017-10-25,40.89,41.055,40.49,40.78,23079947.0,0.0,1.0,40.416088125094,40.579175788108,40.020724093545,40.307363016418,23079947.0
-2017-10-24,41.0,41.05,40.72,40.95,18616857.0,0.0,1.0,40.52481323377,40.574233737714,40.248058411686,40.475392729827,18616857.0
-2017-10-23,40.55,41.04,40.395,40.83,28306520.0,0.0,1.0,40.080028698278,40.564349636925,39.926825136052,40.356783520362,28306520.0
-2017-10-20,40.33,40.45,40.1,40.43,17556315.0,0.0,1.0,39.862578480926,39.98118769039,39.635244162785,39.961419488813,17556315.0
-2017-10-19,39.88,40.33,39.83,40.09,18541779.0,0.0,1.0,39.417793945433,39.862578480926,39.368373441489,39.625360061996,18541779.0
-2017-10-18,39.8,40.29,39.6,40.25,20592939.0,0.0,1.0,39.338721139123,39.823042077771,39.141039123349,39.783505674616,20592939.0
-2017-10-17,39.56,39.865,39.37,39.79,15300505.0,0.0,1.0,39.101502720194,39.40296779425,38.913704805208,39.328837038335,15300505.0
-2017-10-16,39.71,39.79,39.44,39.76,12448746.0,0.0,1.0,39.249764232025,39.328837038335,38.982893510729,39.299184735968,12448746.0
-2017-10-13,39.44,39.81,39.28,39.67,16611521.0,0.0,1.0,38.982893510729,39.348605239912,38.82474789811,39.21022782887,16611521.0
-2017-10-12,39.35,39.39,38.98,39.19,18236204.0,0.0,1.0,38.893936603631,38.933473006786,38.528224874448,38.735790991011,18236204.0
-2017-10-11,39.48,39.67,39.06,39.3,30452182.0,0.0,1.0,39.022429913884,39.21022782887,38.607297680758,38.844516099687,30452182.0
-2017-10-10,39.93,39.95,39.38,39.65,29838331.0,0.0,1.0,39.467214449377,39.486982650954,38.923588905997,39.190459627292,29838331.0
-2017-10-09,39.68,39.88,39.52,39.86,18372360.0,0.0,1.0,39.220111929659,39.417793945433,39.061966317039,39.398025743856,18372360.0
-2017-10-06,39.6,39.89,39.42,39.63,18063051.0,0.0,1.0,39.141039123349,39.427678046222,38.963125309152,39.170691425715,18063051.0
-2017-10-05,39.5,39.65,39.21,39.53,17588371.0,0.0,1.0,39.042198115462,39.190459627292,38.755559192589,39.071850417828,17588371.0
-2017-10-04,39.39,39.4,38.8606,39.34,27900633.0,0.0,1.0,38.933473006786,38.943357107574,38.410208711031,38.884052502842,27900633.0
-2017-10-03,38.95,39.7,38.95,39.38,33266885.0,0.0,1.0,38.498572572082,39.239880131236,38.498572572082,38.923588905997,33266885.0
-2017-10-02,38.12,39.09,38.08,39.04,36985170.0,0.0,1.0,37.678192206618,38.636949983124,37.638655803463,38.58752947918,36985170.0
-2017-09-29,37.84,38.15,37.7,38.08,22617651.0,0.0,1.0,37.401437384533,37.707844508984,37.263059973491,37.638655803463,22617651.0
-2017-09-28,37.32,37.88,37.29,37.83,20601061.0,0.0,1.0,36.88746414352,37.440973787688,36.857811841153,37.391553283745,20601061.0
-2017-09-27,37.62,37.69,37.1,37.54,25457387.0,0.0,1.0,37.183987167181,37.253175872702,36.670013926168,37.104914360872,25457387.0
-2017-09-26,37.21,37.64,37.0,37.47,29198356.0,0.0,1.0,36.778739034844,37.203755368759,36.57117291828,37.035725655351,29198356.0
-2017-09-25,37.05,37.23,36.85,37.16,22158905.0,0.0,1.0,36.620593422224,36.798507236421,36.42291140645,36.7293185309,22158905.0
-2017-09-22,36.95,37.22,36.95,37.18,20928369.0,0.0,1.0,36.521752414337,36.788623135632,36.521752414337,36.749086732477,20928369.0
-2017-09-21,36.99,37.27,36.85,37.2,20175216.0,0.0,1.0,36.561288817492,36.838043639576,36.42291140645,36.768854934055,20175216.0
-2017-09-20,37.23,37.29,36.655,37.07,23127098.0,0.0,1.0,36.798507236421,36.857811841153,36.230171441069,36.640361623802,23127098.0
-2017-09-19,37.2,37.295,37.02,37.23,21823446.0,0.0,1.0,36.768854934055,36.862753891548,36.590941119858,36.798507236421,21823446.0
-2017-09-18,37.0,37.33,36.8,37.0,19083499.0,0.0,1.0,36.57117291828,36.897348244308,36.373490902506,36.57117291828,19083499.0
-2017-09-15,36.55,37.08,36.22,37.0,32109972.0,0.0,1.0,36.126388382788,36.65024572459,35.80021305676,36.57117291828,32109972.0
-2017-09-14,36.19,36.695,36.16,36.48,17902903.0,0.0,1.0,35.770560754394,36.269707844224,35.740908452028,36.057199677267,17902903.0
-2017-09-13,36.0,36.4,35.97,36.33,15069601.0,0.0,1.0,35.582762839408,35.978126870957,35.553110537042,35.908938165436,15069601.0
-2017-09-12,35.88,36.34,35.74,36.09,19061818.0,0.0,1.0,35.464153629943,35.918822266225,35.325776218901,35.671719746507,19061818.0
-2017-09-11,35.49,36.0,35.14,35.77,18895979.0,0.0,1.0,35.078673699183,35.582762839408,34.732730171578,35.355428521267,18895979.0
-2017-09-08,35.42,35.54,35.08,35.19,13881093.0,0.0,1.0,35.009484993662,35.128094203127,34.673425566845,34.782150675521,13881093.0
-2017-09-07,35.88,35.95,35.33,35.54,16045217.0,0.0,1.0,35.464153629943,35.533342335464,34.920528086563,35.128094203127,16045217.0
-2017-09-06,35.22,35.94,35.11,35.76,26811090.0,0.0,1.0,34.811802977888,35.523458234676,34.703077869212,35.345544420479,26811090.0
-2017-09-05,35.02,35.33,34.93,35.02,18665229.0,0.0,1.0,34.614120962113,34.920528086563,34.525164055014,34.614120962113,18665229.0
-2017-09-01,35.24,35.39,35.07,35.085,12713069.0,0.0,1.0,34.831571179465,34.979832691296,34.663541466057,34.67836761724,12713069.0
-2017-08-31,34.94,35.18,34.87,35.07,15959145.0,0.0,1.0,34.535048155803,34.772266574733,34.465859450282,34.663541466057,15959145.0
-2017-08-30,34.75,34.96,34.63,34.89,18230633.0,0.0,1.0,34.347250240817,34.554816357381,34.228641031353,34.48562765186,18230633.0
-2017-08-29,34.51,34.75,34.455,34.73,15605382.0,0.0,1.0,34.110031821888,34.347250240817,34.05566926755,34.32748203924,15605382.0
-2017-08-28,34.78,34.8,34.59,34.65,20463229.0,0.0,1.0,34.376902543184,34.396670744761,34.189104628198,34.24840923293,20463229.0
-2017-08-25,34.82,34.93,34.58,34.67,14126663.0,0.0,1.0,34.416438946339,34.525164055014,34.179220527409,34.268177434508,14126663.0
-2017-08-24,34.7,34.89,34.55,34.71,13495890.0,0.0,1.0,34.297829736874,34.48562765186,34.149568225043,34.307713837663,13495890.0
-2017-08-23,34.54,34.81,34.38,34.66,19439392.0,0.0,1.0,34.139684124254,34.40655484555,33.981538511635,34.258293333719,19439392.0
-2017-08-22,35.02,35.19,34.62,34.65,25496798.0,0.0,1.0,34.614120962113,34.782150675521,34.218756930564,34.24840923293,25496798.0
-2017-08-21,35.09,35.28,34.7,34.92,25642017.0,0.0,1.0,34.683309667634,34.87110758262,34.297829736874,34.515279954226,25642017.0
-2017-08-18,35.29,35.31,34.99,35.01,15556756.0,0.0,1.0,34.880991683409,34.900759884986,34.584468659747,34.604236861324,15556756.0
-2017-08-17,35.6,35.68,35.17,35.17,18464078.0,0.0,1.0,35.187398807859,35.266471614169,34.762382473944,34.762382473944,18464078.0
-2017-08-16,35.98,36.07,35.56,35.82,21319536.0,0.0,1.0,35.562994637831,35.651951544929,35.147862404704,35.404849025211,21319536.0
-2017-08-15,36.3,36.32,35.815,36.0,20630421.0,0.0,1.0,35.87928586307,35.899054064647,35.399906974817,35.582762839408,20630421.0
-2017-08-14,36.12,36.47,36.08,36.34,16255600.0,0.0,1.0,35.701372048873,36.047315576478,35.661835645718,35.918822266225,16255600.0
-2017-08-11,36.26,36.4,35.79,35.87,18697159.0,0.0,1.0,35.839749459915,35.978126870957,35.375196722845,35.454269529155,18697159.0
-2017-08-10,36.4,36.56,36.11,36.12,22414962.0,0.0,1.0,35.978126870957,36.136272483577,35.691487948084,35.701372048873,22414962.0
-2017-08-09,36.28,36.66,36.02,36.59,22596679.0,0.0,1.0,35.859517661492,36.235113491464,35.602531040985,36.165924785943,22596679.0
-2017-08-08,36.37,36.7,36.3,36.41,21067835.0,0.0,1.0,35.948474568591,36.274649894619,35.87928586307,35.988010971746,21067835.0
-2017-08-04,36.45,36.56,36.1,36.3,20312844.0,0.0,1.0,36.027547374901,36.136272483577,35.681603847295,35.87928586307,20312844.0
-2017-08-03,36.55,36.59,36.15,36.49,26377878.0,0.273,1.0,36.126388382788,36.165924785943,35.731024351239,36.067083778056,26377878.0
-2017-08-02,36.33,36.67,36.055,36.64,34502824.0,0.0,1.0,35.642280381273,35.975844249416,35.372486076158,35.946412143404,34502824.0
-2017-08-01,35.66,36.43,35.57,36.35,37556349.0,0.0,1.0,34.984963346992,35.740387401316,34.896667028954,35.661901785282,37556349.0
-2017-07-31,35.47,35.74,35.32,35.47,26748090.0,0.0,1.0,34.798560008912,35.063448963025,34.651399478849,34.798560008912,26748090.0
-2017-07-28,35.13,35.86,35.0,35.31,35538732.0,0.0,1.0,34.464996140769,35.181177387076,34.337457014714,34.641588776845,35538732.0
-2017-07-27,34.78,35.25,34.67,34.97,39239149.0,0.0,1.0,34.121621570622,34.582724564819,34.013703848576,34.308024908702,39239149.0
-2017-07-26,34.7,34.97,34.59,34.75,15400452.0,0.0,1.0,34.043135954588,34.308024908702,33.935218232542,34.092189464609,15400452.0
-2017-07-25,34.55,34.735,34.4,34.67,17569006.0,0.0,1.0,33.895975424525,34.077473411603,33.748814894462,34.013703848576,17569006.0
-2017-07-24,34.73,34.8,34.38,34.5,15114242.0,0.0,1.0,34.072568060601,34.14124297463,33.729193490454,33.846921914504,15114242.0
-2017-07-21,34.54,34.82,34.395,34.73,21682999.0,0.0,1.0,33.886164722521,34.160864378639,33.74390954346,34.072568060601,21682999.0
-2017-07-20,34.54,34.84,34.475,34.75,16643270.0,0.0,1.0,33.886164722521,34.180485782647,33.822395159494,34.092189464609,16643270.0
-2017-07-19,34.68,34.68,34.46,34.56,15923372.0,0.0,1.0,34.02351455058,34.02351455058,33.807679106487,33.905786126529,15923372.0
-2017-07-18,34.43,34.58,34.25,34.53,14031968.0,0.0,1.0,33.778247000475,33.925407530538,33.601654364399,33.876354020517,14031968.0
-2017-07-17,34.74,34.74,34.36,34.47,20910434.0,0.0,1.0,34.082378762605,34.082378762605,33.709572086445,33.817489808492,20910434.0
-2017-07-14,34.48,34.71,34.265,34.68,16039785.0,0.0,1.0,33.827300510496,34.052946656592,33.616370417405,34.02351455058,16039785.0
-2017-07-13,34.33,34.4,34.12,34.24,14978889.0,0.0,1.0,33.680139980433,33.748814894462,33.474115238344,33.591843662395,14978889.0
-2017-07-12,34.28,34.39,33.94,34.25,23430086.0,0.0,1.0,33.631086470412,33.739004192458,33.297522602269,33.601654364399,23430086.0
-2017-07-11,33.64,33.93,33.4311,33.92,24800985.0,0.0,1.0,33.003201542143,33.287711900264,32.798255977275,33.27790119826,24800985.0
-2017-07-10,33.25,33.74,33.23,33.65,26781949.0,0.0,1.0,32.620584163979,33.101308562185,32.60096275997,33.013012244147,26781949.0
-2017-07-07,33.7,34.12,33.7,33.88,17702383.0,0.0,1.0,33.062065754168,33.474115238344,33.062065754168,33.238658390243,17702383.0
-2017-07-06,34.12,34.29,33.56,33.63,20161025.0,0.0,1.0,33.474115238344,33.640897172416,32.924715926109,32.993390840138,20161025.0
-2017-07-05,33.52,34.43,33.485,34.34,29307289.0,0.0,1.0,32.885473118092,33.778247000475,32.851135661077,33.689950682437,29307289.0
-2017-07-03,33.51,34.03,33.43,33.46,12676069.0,0.0,1.0,32.875662416088,33.385818920307,32.797176800054,32.826608906067,12676069.0
-2017-06-30,33.87,33.93,33.535,33.74,23636451.0,0.0,1.0,33.228847688239,33.287711900264,32.900189171098,33.101308562185,23636451.0
-2017-06-29,33.92,34.1,33.34,33.54,24613002.0,0.0,1.0,33.27790119826,33.454493834336,32.708880482016,32.905094522101,24613002.0
-2017-06-28,33.77,34.24,33.74,34.2,25777730.0,0.0,1.0,33.130740668197,33.591843662395,33.101308562185,33.552600854378,25777730.0
-2017-06-27,34.0,34.145,33.65,33.65,26891930.0,0.0,1.0,33.356386814294,33.498641993355,33.013012244147,33.013012244147,26891930.0
-2017-06-26,34.26,34.51,34.03,34.07,18379220.0,0.0,1.0,33.611465066403,33.856732616508,33.385818920307,33.425061728323,18379220.0
-2017-06-23,34.21,34.55,34.095,34.19,24381873.0,0.0,1.0,33.562411556382,33.895975424525,33.449588483334,33.542790152374,24381873.0
-2017-06-22,34.56,34.63,34.29,34.36,23744016.0,0.0,1.0,33.905786126529,33.974461040559,33.640897172416,33.709572086445,23744016.0
-2017-06-21,34.33,34.6,34.09,34.58,26338267.0,0.0,1.0,33.680139980433,33.945028934546,33.444683132332,33.925407530538,26338267.0
-2017-06-20,35.45,35.45,34.84,34.86,21024240.0,0.0,1.0,34.778938604904,34.778938604904,34.180485782647,34.200107186655,21024240.0
-2017-06-19,35.61,35.61,35.32,35.51,20336817.0,0.0,1.0,34.935909836971,34.935909836971,34.651399478849,34.837802816929,20336817.0
-2017-06-16,35.28,35.33,35.01,35.21,28353654.0,0.0,1.0,34.612156670832,34.661210180853,34.347267716719,34.543481756803,28353654.0
-2017-06-15,35.21,35.48,35.14,35.31,19954738.0,0.0,1.0,34.543481756803,34.808370710916,34.474806842773,34.641588776845,19954738.0
-2017-06-14,35.99,36.05,35.22,35.53,19001268.0,0.0,1.0,35.308716513131,35.367580725156,34.553292458807,34.857424220937,19001268.0
-2017-06-13,35.68,35.95,35.53,35.88,20398500.0,0.0,1.0,35.004584751,35.269473705114,34.857424220937,35.200798791084,20398500.0
-2017-06-12,35.59,36.01,35.41,35.73,27374877.0,0.0,1.0,34.916288432962,35.328337917139,34.739695796887,35.053638261021,27374877.0
-2017-06-09,36.5,36.56,35.31,35.71,32858966.0,0.0,1.0,35.809062315345,35.86792652737,34.641588776845,35.034016857013,32858966.0
-2017-06-08,36.34,36.53,36.16,36.48,16202388.0,0.0,1.0,35.652091083278,35.838494421358,35.475498447202,35.789440911337,16202388.0
-2017-06-07,36.13,36.57,36.1,36.26,16521287.0,0.0,1.0,35.446066341189,35.877737229374,35.416634235177,35.573605467244,16521287.0
-2017-06-06,36.16,36.45,35.98,36.13,18153646.0,0.0,1.0,35.475498447202,35.760008805324,35.298905811126,35.446066341189,18153646.0
-2017-06-05,36.3,36.5,36.2,36.34,11288983.0,0.0,1.0,35.612848275261,35.809062315345,35.514741255219,35.652091083278,11288983.0
-2017-06-02,36.27,36.33,36.0,36.32,18902927.0,0.0,1.0,35.583416169248,35.642280381273,35.318527215135,35.632469679269,18902927.0
-2017-06-01,36.12,36.13,35.8,36.12,17288864.0,0.0,1.0,35.436255639185,35.446066341189,35.122313175051,35.436255639185,17288864.0
diff --git a/examples/quick/demos/stocqt/content/data/MSFT.csv b/examples/quick/demos/stocqt/content/data/MSFT.csv
deleted file mode 100644
index 056639e4c2..0000000000
--- a/examples/quick/demos/stocqt/content/data/MSFT.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,85.63,86.05,85.5,85.54,18162779.0,0.0,1.0,85.63,86.05,85.5,85.54,18162779.0
-2017-12-28,85.9,85.93,85.55,85.72,9872795.0,0.0,1.0,85.9,85.93,85.55,85.72,9872795.0
-2017-12-27,85.65,85.98,85.215,85.71,13000828.0,0.0,1.0,85.65,85.98,85.215,85.71,13000828.0
-2017-12-26,85.31,85.5346,85.03,85.4,9737412.0,0.0,1.0,85.31,85.5346,85.03,85.4,9737412.0
-2017-12-22,85.4,85.63,84.92,85.51,14033977.0,0.0,1.0,85.4,85.63,84.92,85.51,14033977.0
-2017-12-21,86.05,86.1,85.4,85.5,16638402.0,0.0,1.0,86.05,86.1,85.4,85.5,16638402.0
-2017-12-20,86.2,86.3,84.71,85.52,23425009.0,0.0,1.0,86.2,86.3,84.71,85.52,23425009.0
-2017-12-19,86.35,86.35,85.27,85.83,23241979.0,0.0,1.0,86.35,86.35,85.27,85.83,23241979.0
-2017-12-18,87.12,87.4999,86.23,86.38,21551076.0,0.0,1.0,87.12,87.4999,86.23,86.38,21551076.0
-2017-12-15,85.26,87.09,84.88,86.85,52430167.0,0.0,1.0,85.26,87.09,84.88,86.85,52430167.0
-2017-12-14,85.43,85.8739,84.53,84.69,19080106.0,0.0,1.0,85.43,85.8739,84.53,84.69,19080106.0
-2017-12-13,85.74,86.0,85.17,85.35,21307911.0,0.0,1.0,85.74,86.0,85.17,85.35,21307911.0
-2017-12-12,85.31,86.05,85.08,85.58,23534946.0,0.0,1.0,85.31,86.05,85.08,85.58,23534946.0
-2017-12-11,84.29,85.37,84.12,85.23,19909119.0,0.0,1.0,84.29,85.37,84.12,85.23,19909119.0
-2017-12-08,83.63,84.58,83.33,84.16,23825056.0,0.0,1.0,83.63,84.58,83.33,84.16,23825056.0
-2017-12-07,82.54,82.8,82.0,82.49,20378114.0,0.0,1.0,82.54,82.8,82.0,82.49,20378114.0
-2017-12-06,81.55,83.14,81.43,82.78,24821403.0,0.0,1.0,81.55,83.14,81.43,82.78,24821403.0
-2017-12-05,81.34,82.68,80.9801,81.59,25512120.0,0.0,1.0,81.34,82.68,80.9801,81.59,25512120.0
-2017-12-04,84.42,84.4299,80.7,81.08,37977732.0,0.0,1.0,84.42,84.4299,80.7,81.08,37977732.0
-2017-12-01,83.6,84.81,83.22,84.26,29113662.0,0.0,1.0,83.6,84.81,83.22,84.26,29113662.0
-2017-11-30,83.51,84.52,83.34,84.17,32074914.0,0.0,1.0,83.51,84.52,83.34,84.17,32074914.0
-2017-11-29,84.71,84.9172,83.175,83.34,26401761.0,0.0,1.0,84.71,84.9172,83.175,83.34,26401761.0
-2017-11-28,84.07,85.06,84.02,84.88,21162639.0,0.0,1.0,84.07,85.06,84.02,84.88,21162639.0
-2017-11-27,83.31,83.98,83.3,83.87,17603760.0,0.0,1.0,83.31,83.98,83.3,83.87,17603760.0
-2017-11-24,83.01,83.43,82.78,83.26,7425503.0,0.0,1.0,83.01,83.43,82.78,83.26,7425503.0
-2017-11-22,83.83,83.9,83.04,83.11,20213704.0,0.0,1.0,83.83,83.9,83.04,83.11,20213704.0
-2017-11-21,82.74,83.84,82.74,83.72,21033981.0,0.0,1.0,82.74,83.84,82.74,83.72,21033981.0
-2017-11-20,82.4,82.59,82.25,82.53,16072495.0,0.0,1.0,82.4,82.59,82.25,82.53,16072495.0
-2017-11-17,83.12,83.12,82.24,82.4,21715498.0,0.0,1.0,83.12,83.12,82.24,82.4,21715498.0
-2017-11-16,83.1,83.42,82.94,83.2,20659209.0,0.0,1.0,83.1,83.42,82.94,83.2,20659209.0
-2017-11-15,83.47,83.69,82.69,82.98,19097333.0,0.42,1.0,83.47,83.69,82.69,82.98,19097333.0
-2017-11-14,83.5,84.1,82.98,84.05,18604034.0,0.0,1.0,83.079496402878,83.676474820144,82.562115107914,83.626726618705,18604034.0
-2017-11-13,83.66,83.94,83.46,83.93,14080820.0,0.0,1.0,83.238690647482,83.51728057554,83.039697841727,83.507330935252,14080820.0
-2017-11-10,83.79,84.095,83.23,83.87,19340435.0,0.0,1.0,83.368035971223,83.6715,82.810856115108,83.447633093525,19340435.0
-2017-11-09,84.11,84.27,82.9,84.09,20924172.0,0.0,1.0,83.686424460432,83.845618705036,82.482517985612,83.666525179856,20924172.0
-2017-11-07,84.77,84.9,83.93,84.27,17152583.0,0.0,1.0,84.343100719424,84.472446043165,83.507330935252,83.845618705036,17152583.0
-2017-11-06,84.2,84.7,84.0825,84.47,19039847.0,0.0,1.0,83.775971223022,84.27345323741,83.65906294964,84.044611510791,19039847.0
-2017-11-03,84.08,84.54,83.4,84.14,17569120.0,0.0,1.0,83.656575539568,84.114258992806,82.98,83.716273381295,17569120.0
-2017-11-02,83.35,84.46,83.12,84.05,23822964.0,0.0,1.0,82.930251798561,84.034661870504,82.701410071942,83.626726618705,23822964.0
-2017-11-01,83.68,83.76,82.88,83.18,22039635.0,0.0,1.0,83.258589928058,83.33818705036,82.462618705036,82.761107913669,22039635.0
-2017-10-31,84.36,84.36,83.11,83.18,26728947.0,0.0,1.0,83.935165467626,83.935165467626,82.691460431655,82.761107913669,26728947.0
-2017-10-30,83.7,84.325,83.105,83.89,31291801.0,0.0,1.0,83.278489208633,83.900341726619,82.686485611511,83.467532374101,31291801.0
-2017-10-27,84.37,86.2,83.61,83.81,70877350.0,0.0,1.0,83.945115107914,85.765899280576,83.188942446043,83.387935251799,70877350.0
-2017-10-26,79.2,79.42,78.75,78.76,29181652.0,0.0,1.0,78.801151079137,79.020043165468,78.353417266187,78.363366906475,29181652.0
-2017-10-25,78.58,79.1,78.01,78.63,19714512.0,0.0,1.0,78.184273381295,78.701654676259,77.617143884892,78.234021582734,19714512.0
-2017-10-24,78.9,79.2,78.46,78.86,16613928.0,0.0,1.0,78.502661870504,78.801151079137,78.064877697842,78.462863309353,16613928.0
-2017-10-23,78.99,79.34,78.76,78.83,20479731.0,0.0,1.0,78.592208633094,78.940446043165,78.363366906475,78.433014388489,20479731.0
-2017-10-20,78.32,78.97,78.22,78.81,22517092.0,0.0,1.0,77.925582733813,78.572309352518,77.826086330935,78.413115107914,22517092.0
-2017-10-19,77.57,77.93,77.35,77.91,14982129.0,0.0,1.0,77.17935971223,77.53754676259,76.960467625899,77.517647482014,14982129.0
-2017-10-18,77.67,77.85,77.37,77.61,13147124.0,0.0,1.0,77.278856115108,77.457949640288,76.980366906475,77.219158273381,13147124.0
-2017-10-17,77.47,77.62,77.25,77.59,15953665.0,0.0,1.0,77.079863309353,77.229107913669,76.860971223022,77.199258992806,15953665.0
-2017-10-16,77.42,77.81,77.35,77.65,12331147.0,0.0,1.0,77.030115107914,77.418151079137,76.960467625899,77.258956834532,12331147.0
-2017-10-13,77.59,77.87,77.29,77.49,15250772.0,0.0,1.0,77.199258992806,77.477848920863,76.900769784173,77.099762589928,15250772.0
-2017-10-12,76.49,77.29,76.37,77.12,16778148.0,0.0,1.0,76.104798561151,76.900769784173,75.985402877698,76.731625899281,16778148.0
-2017-10-11,76.36,76.46,75.95,76.42,14780652.0,0.0,1.0,75.97545323741,76.074949640288,75.567517985612,76.035151079137,14780652.0
-2017-10-10,76.33,76.63,76.14,76.29,13734627.0,0.0,1.0,75.945604316547,76.24409352518,75.756561151079,75.905805755396,13734627.0
-2017-10-09,75.97,76.55,75.86,76.29,11364275.0,0.0,1.0,75.587417266187,76.164496402878,75.477971223022,75.905805755396,11364275.0
-2017-10-06,75.67,76.03,75.54,76.0,13692791.0,0.0,1.0,75.288928057554,75.647115107914,75.159582733813,75.61726618705,13692791.0
-2017-10-05,75.22,76.12,74.96,75.97,20656238.0,0.0,1.0,74.841194244604,75.736661870504,74.582503597122,75.587417266187,20656238.0
-2017-10-04,74.0,74.72,73.71,74.69,13287346.0,0.0,1.0,73.627338129496,74.343712230216,73.338798561151,74.313863309353,13287346.0
-2017-10-03,74.67,74.88,74.195,74.26,11935853.0,0.0,1.0,74.293964028777,74.50290647482,73.821356115108,73.886028776978,11935853.0
-2017-10-02,74.71,75.01,74.295,74.61,15210338.0,0.0,1.0,74.333762589928,74.632251798561,73.920852517986,74.23426618705,15210338.0
-2017-09-29,73.94,74.535,73.88,74.49,16700435.0,0.0,1.0,73.56764028777,74.159643884892,73.507942446043,74.114870503597,16700435.0
-2017-09-28,73.54,73.97,73.31,73.87,10814063.0,0.0,1.0,73.169654676259,73.597489208633,72.94081294964,73.497992805755,10814063.0
-2017-09-27,73.55,74.17,73.17,73.85,18934048.0,0.0,1.0,73.179604316547,73.796482014388,72.801517985612,73.47809352518,18934048.0
-2017-09-26,73.67,73.81,72.99,73.26,17105469.0,0.0,1.0,73.299,73.438294964029,72.622424460432,72.891064748201,17105469.0
-2017-09-25,74.09,74.25,72.92,73.26,23502422.0,0.0,1.0,73.716884892086,73.876079136691,72.552776978417,72.891064748201,23502422.0
-2017-09-22,73.99,74.51,73.85,74.41,13969937.0,0.0,1.0,73.617388489209,74.134769784173,73.47809352518,74.035273381295,13969937.0
-2017-09-21,75.11,75.24,74.11,74.21,19038998.0,0.0,1.0,74.731748201439,74.86109352518,73.736784172662,73.83628057554,19038998.0
-2017-09-20,75.35,75.55,74.31,74.94,20415084.0,0.0,1.0,74.970539568345,75.169532374101,73.935776978417,74.562604316547,20415084.0
-2017-09-19,75.21,75.71,75.01,75.44,15606870.0,0.0,1.0,74.831244604317,75.328726618705,74.632251798561,75.060086330935,15606870.0
-2017-09-18,75.23,75.97,75.04,75.16,22730355.0,0.0,1.0,74.851143884892,75.587417266187,74.662100719424,74.781496402878,22730355.0
-2017-09-15,74.83,75.39,74.07,75.31,37901927.0,0.0,1.0,74.453158273381,75.010338129496,73.696985611511,74.930741007194,37901927.0
-2017-09-14,75.0,75.49,74.52,74.77,15373384.0,0.0,1.0,74.622302158273,75.109834532374,74.14471942446,74.393460431655,15373384.0
-2017-09-13,74.93,75.23,74.55,75.21,12998629.0,0.0,1.0,74.552654676259,74.851143884892,74.174568345324,74.831244604317,12998629.0
-2017-09-12,74.76,75.24,74.37,74.68,14003880.0,0.0,1.0,74.383510791367,74.86109352518,73.995474820144,74.303913669065,14003880.0
-2017-09-11,74.31,74.945,74.31,74.76,17428067.0,0.0,1.0,73.935776978417,74.567579136691,73.935776978417,74.383510791367,17428067.0
-2017-09-08,74.33,74.44,73.84,73.98,14474383.0,0.0,1.0,73.955676258993,74.065122302158,73.468143884892,73.607438848921,14474383.0
-2017-09-07,73.68,74.6,73.6,74.34,17165518.0,0.0,1.0,73.308949640288,74.224316546763,73.229352517986,73.965625899281,17165518.0
-2017-09-06,73.74,74.04,73.35,73.4,15945136.0,0.0,1.0,73.368647482014,73.667136690647,72.980611510791,73.03035971223,15945136.0
-2017-09-05,73.34,73.89,72.98,73.61,21432599.0,0.0,1.0,72.970661870504,73.517892086331,72.612474820144,73.239302158273,21432599.0
-2017-09-01,74.71,74.74,73.64,73.94,21593192.0,0.0,1.0,74.333762589928,74.363611510791,73.269151079137,73.56764028777,21593192.0
-2017-08-31,74.03,74.96,73.8,74.77,26688077.0,0.0,1.0,73.65718705036,74.582503597122,73.428345323741,74.393460431655,26688077.0
-2017-08-30,73.01,74.2099,72.8293,74.01,16826094.0,0.0,1.0,72.642323741007,73.836181079137,72.462533741007,73.637287769784,16826094.0
-2017-08-29,72.25,73.16,72.05,73.05,11325418.0,0.0,1.0,71.886151079137,72.791568345324,71.687158273381,72.682122302158,11325418.0
-2017-08-28,73.06,73.09,72.55,72.83,14112777.0,0.0,1.0,72.692071942446,72.721920863309,72.18464028777,72.463230215827,14112777.0
-2017-08-25,72.86,73.35,72.48,72.82,12574503.0,0.0,1.0,72.493079136691,72.980611510791,72.114992805755,72.45328057554,12574503.0
-2017-08-24,72.74,72.86,72.07,72.69,15980144.0,0.0,1.0,72.373683453237,72.493079136691,71.707057553957,72.323935251799,15980144.0
-2017-08-23,72.96,73.15,72.53,72.72,13586784.0,0.0,1.0,72.592575539568,72.781618705036,72.164741007194,72.353784172662,13586784.0
-2017-08-22,72.35,73.24,72.35,73.16,14183146.0,0.0,1.0,71.985647482014,72.871165467626,71.985647482014,72.791568345324,14183146.0
-2017-08-21,72.47,72.48,71.7,72.15,17656716.0,0.0,1.0,72.105043165468,72.114992805755,71.338920863309,71.786654676259,17656716.0
-2017-08-18,72.27,72.84,71.93,72.49,18215276.0,0.0,1.0,71.906050359712,72.473179856115,71.567762589928,72.124942446043,18215276.0
-2017-08-17,73.58,73.87,72.4,72.4,21834250.0,0.0,1.0,73.20945323741,73.497992805755,72.035395683453,72.035395683453,21834250.0
-2017-08-16,73.34,74.1,73.17,73.65,17814317.0,0.0,1.0,72.970661870504,73.726834532374,72.801517985612,73.279100719424,17814317.0
-2017-08-15,73.59,73.59,73.04,73.22,17791179.0,0.39,1.0,73.219402877698,73.219402877698,72.672172661871,72.85126618705,17791179.0
-2017-08-14,73.06,73.72,72.95,73.59,19756773.0,0.0,1.0,72.306935302621,72.960132363936,72.198069125735,72.831472336707,19756773.0
-2017-08-11,71.61,72.7,71.28,72.5,21121250.0,0.0,1.0,70.87188115276,71.950645996448,70.545282622102,71.752707493019,21121250.0
-2017-08-10,71.9,72.19,71.35,71.41,23153711.0,0.0,1.0,71.158891982732,71.445902812704,70.614561098302,70.673942649331,23153711.0
-2017-08-09,72.25,72.51,72.05,72.47,20401071.0,0.0,1.0,71.505284363733,71.762604418191,71.307345860304,71.723016717505,20401071.0
-2017-08-08,72.09,73.13,71.75,72.79,21446993.0,0.0,1.0,71.34693356099,72.376213778821,71.01043810516,72.039718322991,21446993.0
-2017-08-07,72.8,72.9,72.26,72.4,18582345.0,0.0,1.0,72.049615248163,72.148584499877,71.515181288904,71.653738241305,18582345.0
-2017-08-04,72.4,73.04,72.24,72.68,22412719.0,0.0,1.0,71.653738241305,72.287141452278,71.495387438562,71.930852146105,22412719.0
-2017-08-03,72.19,72.44,71.845,72.15,17937522.0,0.0,1.0,71.445902812704,71.693325941991,71.104458894289,71.406315112019,17937522.0
-2017-08-02,72.55,72.56,71.445,72.26,26405096.0,0.0,1.0,71.802192118877,71.812089044048,70.708581887431,71.515181288904,26405096.0
-2017-08-01,73.1,73.42,72.49,72.58,19060885.0,0.0,1.0,72.346523003306,72.663224608793,71.742810567848,71.831882894391,19060885.0
-2017-07-31,73.3,73.44,72.41,72.72,23151962.0,0.0,1.0,72.544461506735,72.683018459136,71.663635166476,71.970439846791,23151962.0
-2017-07-28,72.67,73.31,72.54,73.04,17472880.0,0.0,1.0,71.920955220934,72.554358431907,71.792295193705,72.287141452278,17472880.0
-2017-07-27,73.76,74.42,72.32,73.16,35518251.0,0.0,1.0,72.999720064622,73.652917125938,71.574562839933,72.405904554335,35518251.0
-2017-07-26,74.34,74.38,73.81,74.05,15850344.0,0.0,1.0,73.573741724566,73.613329425252,73.049204690479,73.286730894594,15850344.0
-2017-07-25,73.8,74.31,73.5,74.19,21522189.0,0.0,1.0,73.039307765308,73.544050949052,72.742400010164,73.425287846995,21522189.0
-2017-07-24,73.53,73.75,73.13,73.6,20836422.0,0.0,1.0,72.772090785679,72.989823139451,72.376213778821,72.841369261879,20836422.0
-2017-07-21,73.45,74.29,73.17,73.79,45302930.0,0.0,1.0,72.692915384307,73.524257098709,72.415801479507,73.029410840136,45302930.0
-2017-07-20,74.18,74.3,73.28,74.24,34174677.0,0.0,1.0,73.415390921823,73.53415402388,72.524667656392,73.474772472852,34174677.0
-2017-07-19,73.5,74.04,73.45,73.86,21769229.0,0.0,1.0,72.742400010164,73.276833969423,72.692915384307,73.098689316337,21769229.0
-2017-07-18,73.09,73.39,72.66,73.3,26150272.0,0.0,1.0,72.336626078135,72.633533833278,71.911058295763,72.544461506735,26150272.0
-2017-07-17,72.8,73.45,72.72,73.35,21481069.0,0.0,1.0,72.049615248163,72.692915384307,71.970439846791,72.593946132593,21481069.0
-2017-07-14,72.24,73.27,71.96,72.78,25689303.0,0.0,1.0,71.495387438562,72.514770731221,71.218273533761,72.02982139782,25689303.0
-2017-07-13,71.5,72.0399,71.31,71.77,20149208.0,0.0,1.0,70.763014975874,71.297349965881,70.574973397617,71.030231955503,20149208.0
-2017-07-12,70.69,71.28,70.55,71.15,17382861.0,0.0,1.0,69.961364036987,70.545282622102,69.822807084586,70.416622594873,17382861.0
-2017-07-11,70.0,70.68,69.75,69.99,16880205.0,0.0,1.0,69.278476200157,69.951467111815,69.03105307087,69.268579274985,16880205.0
-2017-07-10,69.46,70.25,69.2,69.98,14903400.0,0.0,1.0,68.744042240898,69.525899329443,68.486722186441,69.258682349814,14903400.0
-2017-07-07,68.7,69.84,68.7,69.46,15897154.0,0.0,1.0,67.991875927868,69.120125397413,67.991875927868,68.744042240898,15897154.0
-2017-07-06,68.27,68.78,68.12,68.57,20776555.0,0.0,1.0,67.566308145496,68.07105132924,67.417854267924,67.863215900639,20776555.0
-2017-07-05,68.255,69.44,68.22,69.08,20174523.0,0.0,1.0,67.551462757738,68.724248390555,67.516823519638,68.367959084383,20174523.0
-2017-07-03,69.33,69.6,68.02,68.17,16164331.0,0.0,1.0,68.615382213669,68.882599193299,67.318885016209,67.467338893781,16164331.0
-2017-06-30,68.78,69.38,68.74,68.93,23039328.0,0.0,1.0,68.07105132924,68.664866839527,68.031463628554,68.219505206811,23039328.0
-2017-06-29,69.38,69.49,68.09,68.49,28231562.0,0.0,1.0,68.664866839527,68.773733016413,67.388163492409,67.784040499267,28231562.0
-2017-06-28,69.21,69.841,68.79,69.8,25226070.0,0.0,1.0,68.496619111612,69.12111508993,68.080948254411,69.080537696728,25226070.0
-2017-06-27,70.11,70.18,69.18,69.21,24862560.0,0.0,1.0,69.387342377043,69.456620853243,68.466928336098,68.496619111612,24862560.0
-2017-06-26,71.4,71.71,70.445,70.53,19308122.0,0.0,1.0,70.66404572416,70.970850404475,69.718889370286,69.803013234243,19308122.0
-2017-06-23,70.09,71.25,69.92,71.21,23176418.0,0.0,1.0,69.3675485267,70.515591846588,69.199300798785,70.476004145902,23176418.0
-2017-06-22,70.54,70.59,69.71,70.26,22222851.0,0.0,1.0,69.812910159415,69.862394785272,68.991465370184,69.535796254614,22222851.0
-2017-06-21,70.21,70.62,69.94,70.27,19190623.0,0.0,1.0,69.486311628757,69.892085560787,69.219094649128,69.545693179786,19190623.0
-2017-06-20,70.82,70.87,69.87,69.91,20775590.0,0.0,1.0,70.090024064216,70.139508690073,69.149816172928,69.189403873614,20775590.0
-2017-06-19,70.5,70.945,70.35,70.87,23146852.0,0.0,1.0,69.773322458729,70.213735628859,69.624868581157,70.139508690073,23146852.0
-2017-06-16,69.73,70.0252,69.22,70.0,46911637.0,0.0,1.0,69.011259220527,69.303416451589,68.506516036783,69.278476200157,46911637.0
-2017-06-15,69.27,70.21,68.8,69.9,25701569.0,0.0,1.0,68.556000662641,69.486311628757,68.090845179582,69.179506948442,25701569.0
-2017-06-14,70.91,71.1,69.43,70.27,25271276.0,0.0,1.0,70.179096390759,70.367137969016,68.714351465384,69.545693179786,25271276.0
-2017-06-13,70.02,70.82,69.96,70.65,24815455.0,0.0,1.0,69.298270050499,70.090024064216,69.238888499471,69.921776336301,24815455.0
-2017-06-12,69.25,69.94,68.13,69.78,47363986.0,0.0,1.0,68.536206812298,69.219094649128,67.427751193095,69.060743846385,47363986.0
-2017-06-09,72.035,72.08,68.59,70.32,48619420.0,0.0,1.0,71.292500472547,71.337036635818,67.883009750982,69.595177805643,48619420.0
-2017-06-08,72.51,72.52,71.5,71.945,23982410.0,0.0,1.0,71.762604418191,71.772501343362,70.763014975874,71.203428146004,23982410.0
-2017-06-07,72.635,72.77,71.95,72.39,21895156.0,0.0,1.0,71.886315982834,72.019924472648,71.20837660859,71.643841316133,21895156.0
-2017-06-06,72.3,72.62,72.27,72.52,31220057.0,0.0,1.0,71.55476898959,71.871470595077,71.525078214076,71.772501343362,31220057.0
-2017-06-05,71.97,72.89,71.81,72.28,29507429.0,0.0,1.0,71.228170458932,72.138687574706,71.069819656189,71.534975139247,29507429.0
-2017-06-02,70.44,71.86,70.24,71.76,34586054.0,0.0,1.0,69.7139409077,71.119304282046,69.516002404271,71.020335030332,34586054.0
-2017-06-01,70.24,70.61,69.451,70.1,21066468.0,0.0,1.0,69.516002404271,69.882188635615,68.735135008244,69.377445451871,21066468.0
diff --git a/examples/quick/demos/stocqt/content/data/NCLH.csv b/examples/quick/demos/stocqt/content/data/NCLH.csv
deleted file mode 100644
index 3827fd20ad..0000000000
--- a/examples/quick/demos/stocqt/content/data/NCLH.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,53.45,53.96,53.2,53.25,889909.0,0.0,1.0,53.45,53.96,53.2,53.25,889909.0
-2017-12-28,54.01,54.03,53.34,53.61,1186989.0,0.0,1.0,54.01,54.03,53.34,53.61,1186989.0
-2017-12-27,53.95,54.19,53.7,54.0,792700.0,0.0,1.0,53.95,54.19,53.7,54.0,792700.0
-2017-12-26,53.93,54.25,53.65,53.73,906947.0,0.0,1.0,53.93,54.25,53.65,53.73,906947.0
-2017-12-22,54.325,54.47,53.72,54.03,1251857.0,0.0,1.0,54.325,54.47,53.72,54.03,1251857.0
-2017-12-21,54.9,55.31,54.01,54.14,1346967.0,0.0,1.0,54.9,55.31,54.01,54.14,1346967.0
-2017-12-20,55.74,56.41,54.74,54.82,1797666.0,0.0,1.0,55.74,56.41,54.74,54.82,1797666.0
-2017-12-19,55.14,56.05,55.02,55.59,1592622.0,0.0,1.0,55.14,56.05,55.02,55.59,1592622.0
-2017-12-18,54.51,55.355,54.5,54.98,2094664.0,0.0,1.0,54.51,55.355,54.5,54.98,2094664.0
-2017-12-15,53.14,54.3,52.58,54.0,6275489.0,0.0,1.0,53.14,54.3,52.58,54.0,6275489.0
-2017-12-14,53.16,53.46,52.7,52.81,1433280.0,0.0,1.0,53.16,53.46,52.7,52.81,1433280.0
-2017-12-13,53.93,53.93,53.09,53.16,1222815.0,0.0,1.0,53.93,53.93,53.09,53.16,1222815.0
-2017-12-12,54.64,54.64,53.55,53.65,1640536.0,0.0,1.0,54.64,54.64,53.55,53.65,1640536.0
-2017-12-11,54.75,55.37,54.33,54.72,1492003.0,0.0,1.0,54.75,55.37,54.33,54.72,1492003.0
-2017-12-08,54.74,55.57,54.36,55.03,1249849.0,0.0,1.0,54.74,55.57,54.36,55.03,1249849.0
-2017-12-07,54.5,54.62,54.08,54.34,1093747.0,0.0,1.0,54.5,54.62,54.08,54.34,1093747.0
-2017-12-06,54.49,54.8,53.7,54.31,1161732.0,0.0,1.0,54.49,54.8,53.7,54.31,1161732.0
-2017-12-05,55.53,55.67,54.265,54.33,938087.0,0.0,1.0,55.53,55.67,54.265,54.33,938087.0
-2017-12-04,55.68,56.84,55.3,55.41,2507341.0,0.0,1.0,55.68,56.84,55.3,55.41,2507341.0
-2017-12-01,53.94,54.91,53.675,54.81,1314538.0,0.0,1.0,53.94,54.91,53.675,54.81,1314538.0
-2017-11-30,54.0,54.69,52.36,54.16,3452181.0,0.0,1.0,54.0,54.69,52.36,54.16,3452181.0
-2017-11-29,55.48,56.21,55.12,55.29,1637536.0,0.0,1.0,55.48,56.21,55.12,55.29,1637536.0
-2017-11-28,55.62,55.83,54.92,55.31,1759104.0,0.0,1.0,55.62,55.83,54.92,55.31,1759104.0
-2017-11-27,55.55,56.03,55.47,55.61,1224822.0,0.0,1.0,55.55,56.03,55.47,55.61,1224822.0
-2017-11-24,55.41,55.74,55.01,55.5,550824.0,0.0,1.0,55.41,55.74,55.01,55.5,550824.0
-2017-11-22,55.42,56.0,55.11,55.31,1270402.0,0.0,1.0,55.42,56.0,55.11,55.31,1270402.0
-2017-11-21,54.93,55.88,54.8,55.48,2014071.0,0.0,1.0,54.93,55.88,54.8,55.48,2014071.0
-2017-11-20,54.78,55.09,54.28,54.69,2306354.0,0.0,1.0,54.78,55.09,54.28,54.69,2306354.0
-2017-11-17,54.12,54.9,53.69,54.84,3943455.0,0.0,1.0,54.12,54.9,53.69,54.84,3943455.0
-2017-11-16,53.85,54.3,53.5,53.97,6186166.0,0.0,1.0,53.85,54.3,53.5,53.97,6186166.0
-2017-11-15,55.09,55.19,54.58,55.07,1345399.0,0.0,1.0,55.09,55.19,54.58,55.07,1345399.0
-2017-11-14,55.08,55.22,54.1,55.1,1301048.0,0.0,1.0,55.08,55.22,54.1,55.1,1301048.0
-2017-11-13,54.91,55.34,54.65,55.27,1717783.0,0.0,1.0,54.91,55.34,54.65,55.27,1717783.0
-2017-11-10,55.75,56.06,54.07,55.23,2272543.0,0.0,1.0,55.75,56.06,54.07,55.23,2272543.0
-2017-11-09,55.74,58.27,55.29,56.89,3115303.0,0.0,1.0,55.74,58.27,55.29,56.89,3115303.0
-2017-11-07,56.55,57.37,54.97,55.36,1793433.0,0.0,1.0,56.55,57.37,54.97,55.36,1793433.0
-2017-11-06,55.0,56.12,54.905,55.26,1518782.0,0.0,1.0,55.0,56.12,54.905,55.26,1518782.0
-2017-11-03,54.91,55.09,54.53,55.03,922980.0,0.0,1.0,54.91,55.09,54.53,55.03,922980.0
-2017-11-02,54.27,55.17,54.205,54.91,2134024.0,0.0,1.0,54.27,55.17,54.205,54.91,2134024.0
-2017-11-01,56.06,56.1,54.04,54.2,2246546.0,0.0,1.0,56.06,56.1,54.04,54.2,2246546.0
-2017-10-31,54.82,55.98,54.715,55.75,1441239.0,0.0,1.0,54.82,55.98,54.715,55.75,1441239.0
-2017-10-30,55.29,55.67,54.67,54.8,972388.0,0.0,1.0,55.29,55.67,54.67,54.8,972388.0
-2017-10-27,54.8,56.28,54.49,55.64,2308873.0,0.0,1.0,54.8,56.28,54.49,55.64,2308873.0
-2017-10-26,54.8,55.25,54.53,54.92,1373500.0,0.0,1.0,54.8,55.25,54.53,54.92,1373500.0
-2017-10-25,54.67,55.19,54.38,54.79,2407822.0,0.0,1.0,54.67,55.19,54.38,54.79,2407822.0
-2017-10-24,53.63,54.78,53.5,54.66,2467749.0,0.0,1.0,53.63,54.78,53.5,54.66,2467749.0
-2017-10-23,53.76,54.1014,53.531,53.72,1984765.0,0.0,1.0,53.76,54.1014,53.531,53.72,1984765.0
-2017-10-20,54.87,54.94,53.45,53.73,3459633.0,0.0,1.0,54.87,54.94,53.45,53.73,3459633.0
-2017-10-19,56.4,56.52,53.8,54.17,7936900.0,0.0,1.0,56.4,56.52,53.8,54.17,7936900.0
-2017-10-18,58.45,58.45,57.13,57.47,4187580.0,0.0,1.0,58.45,58.45,57.13,57.47,4187580.0
-2017-10-17,58.69,59.0,58.44,58.61,2360423.0,0.0,1.0,58.69,59.0,58.44,58.61,2360423.0
-2017-10-16,58.83,59.15,58.4,58.92,2088445.0,0.0,1.0,58.83,59.15,58.4,58.92,2088445.0
-2017-10-13,59.43,59.6,58.22,58.74,3925398.0,0.0,1.0,59.43,59.6,58.22,58.74,3925398.0
-2017-10-12,58.56,59.3,58.43,58.86,29345290.0,0.0,1.0,58.56,59.3,58.43,58.86,29345290.0
-2017-10-11,59.15,59.42,58.58,58.8,2721843.0,0.0,1.0,59.15,59.42,58.58,58.8,2721843.0
-2017-10-10,59.19,59.535,58.985,59.16,2658838.0,0.0,1.0,59.19,59.535,58.985,59.16,2658838.0
-2017-10-09,58.75,59.66,58.71,58.89,2211669.0,0.0,1.0,58.75,59.66,58.71,58.89,2211669.0
-2017-10-06,58.25,59.4,58.25,58.84,3026934.0,0.0,1.0,58.25,59.4,58.25,58.84,3026934.0
-2017-10-05,58.01,58.54,57.53,58.41,7767820.0,0.0,1.0,58.01,58.54,57.53,58.41,7767820.0
-2017-10-04,54.58,56.2,54.53,55.98,1566581.0,0.0,1.0,54.58,56.2,54.53,55.98,1566581.0
-2017-10-03,54.46,55.11,54.03,54.73,1212466.0,0.0,1.0,54.46,55.11,54.03,54.73,1212466.0
-2017-10-02,53.94,54.53,53.6,54.42,1111899.0,0.0,1.0,53.94,54.53,53.6,54.42,1111899.0
-2017-09-29,53.46,54.15,52.44,54.05,2508346.0,0.0,1.0,53.46,54.15,52.44,54.05,2508346.0
-2017-09-28,52.52,53.93,51.99,53.65,2527667.0,0.0,1.0,52.52,53.93,51.99,53.65,2527667.0
-2017-09-27,54.99,55.04,52.74,52.83,1960663.0,0.0,1.0,54.99,55.04,52.74,52.83,1960663.0
-2017-09-26,54.46,55.68,54.26,54.89,2549545.0,0.0,1.0,54.46,55.68,54.26,54.89,2549545.0
-2017-09-25,53.74,54.11,53.23,53.6,1422751.0,0.0,1.0,53.74,54.11,53.23,53.6,1422751.0
-2017-09-22,54.09,54.81,53.75,54.02,1392579.0,0.0,1.0,54.09,54.81,53.75,54.02,1392579.0
-2017-09-21,54.54,54.83,53.95,54.4,1231315.0,0.0,1.0,54.54,54.83,53.95,54.4,1231315.0
-2017-09-20,55.36,55.42,53.71,54.36,2204298.0,0.0,1.0,55.36,55.42,53.71,54.36,2204298.0
-2017-09-19,56.27,56.27,55.29,55.46,1504249.0,0.0,1.0,56.27,56.27,55.29,55.46,1504249.0
-2017-09-18,56.7,57.21,56.28,56.35,1455687.0,0.0,1.0,56.7,57.21,56.28,56.35,1455687.0
-2017-09-15,56.55,56.74,55.28,56.74,3808399.0,0.0,1.0,56.55,56.74,55.28,56.74,3808399.0
-2017-09-14,57.35,58.58,57.25,57.72,1354813.0,0.0,1.0,57.35,58.58,57.25,57.72,1354813.0
-2017-09-13,56.94,57.84,56.75,57.79,1399743.0,0.0,1.0,56.94,57.84,56.75,57.79,1399743.0
-2017-09-12,56.92,57.22,56.41,57.2,1019670.0,0.0,1.0,56.92,57.22,56.41,57.2,1019670.0
-2017-09-11,56.19,58.2,56.0,56.65,2870913.0,0.0,1.0,56.19,58.2,56.0,56.65,2870913.0
-2017-09-08,55.84,56.98,55.01,55.12,1537947.0,0.0,1.0,55.84,56.98,55.01,55.12,1537947.0
-2017-09-07,57.0,57.43,55.77,55.86,1642298.0,0.0,1.0,57.0,57.43,55.77,55.86,1642298.0
-2017-09-06,56.53,57.17,55.91,57.12,1961468.0,0.0,1.0,56.53,57.17,55.91,57.12,1961468.0
-2017-09-05,58.51,58.54,55.3,56.69,2810897.0,0.0,1.0,58.51,58.54,55.3,56.69,2810897.0
-2017-09-01,59.62,60.0,58.48,58.54,1159890.0,0.0,1.0,59.62,60.0,58.48,58.54,1159890.0
-2017-08-31,58.42,59.5,58.41,59.46,1792821.0,0.0,1.0,58.42,59.5,58.41,59.46,1792821.0
-2017-08-30,57.53,58.8,57.25,58.22,1430195.0,0.0,1.0,57.53,58.8,57.25,58.22,1430195.0
-2017-08-29,57.43,57.74,56.47,57.64,1532747.0,0.0,1.0,57.43,57.74,56.47,57.64,1532747.0
-2017-08-28,57.98,58.03,57.48,57.88,878613.0,0.0,1.0,57.98,58.03,57.48,57.88,878613.0
-2017-08-25,57.99,58.0,57.58,57.72,1934962.0,0.0,1.0,57.99,58.0,57.58,57.72,1934962.0
-2017-08-24,57.33,57.905,57.29,57.73,1495111.0,0.0,1.0,57.33,57.905,57.29,57.73,1495111.0
-2017-08-23,56.53,57.91,56.53,57.15,1903662.0,0.0,1.0,56.53,57.91,56.53,57.15,1903662.0
-2017-08-22,56.01,57.03,56.01,56.9,1072763.0,0.0,1.0,56.01,57.03,56.01,56.9,1072763.0
-2017-08-21,55.81,56.15,55.59,55.86,980583.0,0.0,1.0,55.81,56.15,55.59,55.86,980583.0
-2017-08-18,56.33,56.33,55.26,55.78,1424778.0,0.0,1.0,56.33,56.33,55.26,55.78,1424778.0
-2017-08-17,57.98,58.07,56.01,56.18,2067539.0,0.0,1.0,57.98,58.07,56.01,56.18,2067539.0
-2017-08-16,57.8,58.41,57.44,57.9,1434593.0,0.0,1.0,57.8,58.41,57.44,57.9,1434593.0
-2017-08-15,57.61,58.56,57.22,57.45,2822548.0,0.0,1.0,57.61,58.56,57.22,57.45,2822548.0
-2017-08-14,57.14,57.83,57.01,57.46,2619908.0,0.0,1.0,57.14,57.83,57.01,57.46,2619908.0
-2017-08-11,54.75,57.17,54.15,56.77,12874815.0,0.0,1.0,54.75,57.17,54.15,56.77,12874815.0
-2017-08-10,58.04,58.16,56.9,57.07,1656606.0,0.0,1.0,58.04,58.16,56.9,57.07,1656606.0
-2017-08-09,58.88,58.99,58.05,58.36,2075241.0,0.0,1.0,58.88,58.99,58.05,58.36,2075241.0
-2017-08-08,59.05,61.48,58.85,59.42,5341341.0,0.0,1.0,59.05,61.48,58.85,59.42,5341341.0
-2017-08-07,57.15,57.62,56.49,56.65,2833326.0,0.0,1.0,57.15,57.62,56.49,56.65,2833326.0
-2017-08-04,56.47,57.48,56.27,56.9,1265045.0,0.0,1.0,56.47,57.48,56.27,56.9,1265045.0
-2017-08-03,55.77,56.96,55.77,56.25,1152770.0,0.0,1.0,55.77,56.96,55.77,56.25,1152770.0
-2017-08-02,56.89,57.25,55.45,55.84,1255978.0,0.0,1.0,56.89,57.25,55.45,55.84,1255978.0
-2017-08-01,56.49,57.25,56.15,56.91,2486095.0,0.0,1.0,56.49,57.25,56.15,56.91,2486095.0
-2017-07-31,55.45,55.73,54.975,55.07,886281.0,0.0,1.0,55.45,55.73,54.975,55.07,886281.0
-2017-07-28,54.71,55.26,54.39,55.21,983892.0,0.0,1.0,54.71,55.26,54.39,55.21,983892.0
-2017-07-27,55.7,55.85,54.29,55.11,1201890.0,0.0,1.0,55.7,55.85,54.29,55.11,1201890.0
-2017-07-26,56.0,56.01,55.2,55.65,631774.0,0.0,1.0,56.0,56.01,55.2,55.65,631774.0
-2017-07-25,55.9,56.36,55.43,55.75,998410.0,0.0,1.0,55.9,56.36,55.43,55.75,998410.0
-2017-07-24,55.3,55.77,55.04,55.73,1082025.0,0.0,1.0,55.3,55.77,55.04,55.73,1082025.0
-2017-07-21,54.9,55.23,54.7645,55.07,658226.0,0.0,1.0,54.9,55.23,54.7645,55.07,658226.0
-2017-07-20,54.53,55.33,54.33,55.05,972645.0,0.0,1.0,54.53,55.33,54.33,55.05,972645.0
-2017-07-19,54.27,54.51,54.09,54.38,688376.0,0.0,1.0,54.27,54.51,54.09,54.38,688376.0
-2017-07-18,54.22,54.44,53.71,54.18,620018.0,0.0,1.0,54.22,54.44,53.71,54.18,620018.0
-2017-07-17,53.51,54.45,53.16,54.13,1062125.0,0.0,1.0,53.51,54.45,53.16,54.13,1062125.0
-2017-07-14,54.43,54.48,53.4,53.47,923880.0,0.0,1.0,54.43,54.48,53.4,53.47,923880.0
-2017-07-13,54.12,54.49,53.65,54.24,1061017.0,0.0,1.0,54.12,54.49,53.65,54.24,1061017.0
-2017-07-12,54.32,54.64,53.58,54.09,1174740.0,0.0,1.0,54.32,54.64,53.58,54.09,1174740.0
-2017-07-11,53.79,54.3,53.4,53.96,780957.0,0.0,1.0,53.79,54.3,53.4,53.96,780957.0
-2017-07-10,54.53,55.09,53.663,54.03,1253838.0,0.0,1.0,54.53,55.09,53.663,54.03,1253838.0
-2017-07-07,54.2,55.04,54.2,54.68,950235.0,0.0,1.0,54.2,55.04,54.2,54.68,950235.0
-2017-07-06,55.06,55.06,53.925,54.06,1550796.0,0.0,1.0,55.06,55.06,53.925,54.06,1550796.0
-2017-07-05,54.52,55.75,54.495,55.41,973694.0,0.0,1.0,54.52,55.75,54.495,55.41,973694.0
-2017-07-03,54.63,55.21,54.38,54.55,496186.0,0.0,1.0,54.63,55.21,54.38,54.55,496186.0
-2017-06-30,54.96,55.0,54.27,54.29,1025663.0,0.0,1.0,54.96,55.0,54.27,54.29,1025663.0
-2017-06-29,55.16,55.33,54.08,54.42,844905.0,0.0,1.0,55.16,55.33,54.08,54.42,844905.0
-2017-06-28,54.18,55.73,54.18,55.28,1012373.0,0.0,1.0,54.18,55.73,54.18,55.28,1012373.0
-2017-06-27,55.01,55.29,53.84,53.86,1517157.0,0.0,1.0,55.01,55.29,53.84,53.86,1517157.0
-2017-06-26,54.82,56.12,54.82,55.31,1225716.0,0.0,1.0,54.82,56.12,54.82,55.31,1225716.0
-2017-06-23,55.57,55.87,54.74,54.81,2188845.0,0.0,1.0,55.57,55.87,54.74,54.81,2188845.0
-2017-06-22,55.01,56.26,54.9,55.46,2613554.0,0.0,1.0,55.01,56.26,54.9,55.46,2613554.0
-2017-06-21,53.24,55.23,53.2,54.9,2426566.0,0.0,1.0,53.24,55.23,53.2,54.9,2426566.0
-2017-06-20,53.51,53.92,52.95,53.1,1059158.0,0.0,1.0,53.51,53.92,52.95,53.1,1059158.0
-2017-06-19,53.2,53.84,53.06,53.63,1036571.0,0.0,1.0,53.2,53.84,53.06,53.63,1036571.0
-2017-06-16,52.71,53.01,52.09,52.9,2348629.0,0.0,1.0,52.71,53.01,52.09,52.9,2348629.0
-2017-06-15,51.61,52.95,51.61,52.91,1146075.0,0.0,1.0,51.61,52.95,51.61,52.91,1146075.0
-2017-06-14,51.99,52.74,51.7,52.17,1432854.0,0.0,1.0,51.99,52.74,51.7,52.17,1432854.0
-2017-06-13,50.78,52.23,50.77,51.84,1457083.0,0.0,1.0,50.78,52.23,50.77,51.84,1457083.0
-2017-06-12,50.98,51.26,49.52,50.42,2050208.0,0.0,1.0,50.98,51.26,49.52,50.42,2050208.0
-2017-06-09,51.97,52.31,50.8,51.13,2214803.0,0.0,1.0,51.97,52.31,50.8,51.13,2214803.0
-2017-06-08,50.93,52.1,50.68,51.79,2046748.0,0.0,1.0,50.93,52.1,50.68,51.79,2046748.0
-2017-06-07,50.08,50.81,49.75,50.79,1934974.0,0.0,1.0,50.08,50.81,49.75,50.79,1934974.0
-2017-06-06,50.0,50.6,49.66,49.72,2199861.0,0.0,1.0,50.0,50.6,49.66,49.72,2199861.0
-2017-06-05,51.17,51.17,50.07,50.31,1580004.0,0.0,1.0,51.17,51.17,50.07,50.31,1580004.0
-2017-06-02,51.16,51.64,50.97,51.16,1166461.0,0.0,1.0,51.16,51.64,50.97,51.16,1166461.0
-2017-06-01,50.23,51.1,49.98,50.93,1713508.0,0.0,1.0,50.23,51.1,49.98,50.93,1713508.0
diff --git a/examples/quick/demos/stocqt/content/data/NFLX.csv b/examples/quick/demos/stocqt/content/data/NFLX.csv
deleted file mode 100644
index d7a667843c..0000000000
--- a/examples/quick/demos/stocqt/content/data/NFLX.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,192.51,193.95,191.22,191.96,5158845.0,0.0,1.0,192.51,193.95,191.22,191.96,5158845.0
-2017-12-28,187.18,194.49,186.85,192.71,10080261.0,0.0,1.0,187.18,194.49,186.85,192.71,10080261.0
-2017-12-27,187.8,188.1,185.22,186.24,3932094.0,0.0,1.0,187.8,188.1,185.22,186.24,3932094.0
-2017-12-26,189.78,189.94,186.4,187.76,3032707.0,0.0,1.0,189.78,189.94,186.4,187.76,3032707.0
-2017-12-22,188.33,190.95,186.8,189.94,3760922.0,0.0,1.0,188.33,190.95,186.8,189.94,3760922.0
-2017-12-21,189.44,190.95,187.58,188.62,3522551.0,0.0,1.0,189.44,190.95,187.58,188.62,3522551.0
-2017-12-20,187.94,189.11,185.26,188.82,5814609.0,0.0,1.0,187.94,189.11,185.26,188.82,5814609.0
-2017-12-19,190.18,190.2981,185.75,187.02,6526555.0,0.0,1.0,190.18,190.2981,185.75,187.02,6526555.0
-2017-12-18,191.2,191.65,188.9,190.42,4944337.0,0.0,1.0,191.2,191.65,188.9,190.42,4944337.0
-2017-12-15,189.61,191.43,188.01,190.12,7048874.0,0.0,1.0,189.61,191.43,188.01,190.12,7048874.0
-2017-12-14,187.98,192.64,187.2,189.56,7677048.0,0.0,1.0,187.98,192.64,187.2,189.56,7677048.0
-2017-12-13,186.1,188.69,185.41,187.86,4653749.0,0.0,1.0,186.1,188.69,185.41,187.86,4653749.0
-2017-12-12,186.01,187.85,184.8183,185.73,4135595.0,0.0,1.0,186.01,187.85,184.8183,185.73,4135595.0
-2017-12-11,187.85,189.42,185.91,186.22,5131319.0,0.0,1.0,187.85,189.42,185.91,186.22,5131319.0
-2017-12-08,186.5,189.42,186.3,188.54,4909440.0,0.0,1.0,186.5,189.42,186.3,188.54,4909440.0
-2017-12-07,185.71,187.34,183.22,185.2,4543492.0,0.0,1.0,185.71,187.34,183.22,185.2,4543492.0
-2017-12-06,183.38,186.4844,182.88,185.3,5006257.0,0.0,1.0,183.38,186.4844,182.88,185.3,5006257.0
-2017-12-05,183.5,188.14,181.19,184.21,5547802.0,0.0,1.0,183.5,188.14,181.19,184.21,5547802.0
-2017-12-04,189.36,189.72,178.38,184.04,9137873.0,0.0,1.0,189.36,189.72,178.38,184.04,9137873.0
-2017-12-01,186.99,189.8,185.0,186.82,6163366.0,0.0,1.0,186.99,189.8,185.0,186.82,6163366.0
-2017-11-30,190.31,190.86,186.68,187.58,6499326.0,0.0,1.0,190.31,190.86,186.68,187.58,6499326.0
-2017-11-29,198.91,199.029,184.32,188.15,13905339.0,0.0,1.0,198.91,199.029,184.32,188.15,13905339.0
-2017-11-28,195.34,199.68,194.01,199.18,6942358.0,0.0,1.0,195.34,199.68,194.01,199.18,6942358.0
-2017-11-27,195.56,195.85,194.0,195.05,3186677.0,0.0,1.0,195.56,195.85,194.0,195.05,3186677.0
-2017-11-24,196.65,196.9,195.33,195.75,2160300.0,0.0,1.0,196.65,196.9,195.33,195.75,2160300.0
-2017-11-22,196.58,196.75,193.63,196.32,5879771.0,0.0,1.0,196.58,196.75,193.63,196.32,5879771.0
-2017-11-21,195.04,197.52,194.971,196.23,4598017.0,0.0,1.0,195.04,197.52,194.971,196.23,4598017.0
-2017-11-20,193.3,194.32,191.9,194.1,3727412.0,0.0,1.0,193.3,194.32,191.9,194.1,3727412.0
-2017-11-17,195.74,195.95,192.65,193.2,3753775.0,0.0,1.0,195.74,195.95,192.65,193.2,3753775.0
-2017-11-16,194.33,197.7,193.75,195.51,5655042.0,0.0,1.0,194.33,197.7,193.75,195.51,5655042.0
-2017-11-15,194.54,195.42,191.53,192.12,4162712.0,0.0,1.0,194.54,195.42,191.53,192.12,4162712.0
-2017-11-14,193.64,195.88,193.0,195.71,3408535.0,0.0,1.0,193.64,195.88,193.0,195.71,3408535.0
-2017-11-13,191.12,196.05,191.0,195.08,4598005.0,0.0,1.0,191.12,196.05,191.0,195.08,4598005.0
-2017-11-10,191.61,192.59,189.5,192.02,6609739.0,0.0,1.0,191.61,192.59,189.5,192.02,6609739.0
-2017-11-09,194.46,194.49,190.81,193.9,5839579.0,0.0,1.0,194.46,194.49,190.81,193.9,5839579.0
-2017-11-07,200.0,200.61,194.8,195.89,6413310.0,0.0,1.0,200.0,200.61,194.8,195.89,6413310.0
-2017-11-06,200.0,202.48,198.09,200.13,5834857.0,0.0,1.0,200.0,202.48,198.09,200.13,5834857.0
-2017-11-03,199.8,200.55,197.99,200.01,3643216.0,0.0,1.0,199.8,200.55,197.99,200.01,3643216.0
-2017-11-02,197.45,199.44,197.0901,199.32,3578289.0,0.0,1.0,197.45,199.44,197.0901,199.32,3578289.0
-2017-11-01,197.24,199.199,196.0,198.0,4983343.0,0.0,1.0,197.24,199.199,196.0,198.0,4983343.0
-2017-10-31,198.21,198.59,195.218,196.43,5437925.0,0.0,1.0,198.21,198.59,195.218,196.43,5437925.0
-2017-10-30,199.62,201.099,197.0721,198.37,5412277.0,0.0,1.0,199.62,201.099,197.0721,198.37,5412277.0
-2017-10-27,197.2,200.65,196.22,199.54,8088364.0,0.0,1.0,197.2,200.65,196.22,199.54,8088364.0
-2017-10-26,194.66,197.61,194.08,195.21,5101258.0,0.0,1.0,194.66,197.61,194.08,195.21,5101258.0
-2017-10-25,195.38,197.055,193.01,193.77,5231713.0,0.0,1.0,195.38,197.055,193.01,193.77,5231713.0
-2017-10-24,192.75,196.735,191.4,196.02,6985460.0,0.0,1.0,192.75,196.735,191.4,196.02,6985460.0
-2017-10-23,194.17,194.8999,191.0346,192.47,6952997.0,0.0,1.0,194.17,194.8999,191.0346,192.47,6952997.0
-2017-10-20,195.9,196.38,193.77,194.16,5907121.0,0.0,1.0,195.9,196.38,193.77,194.16,5907121.0
-2017-10-19,193.01,195.25,191.16,195.13,7007447.0,0.0,1.0,193.01,195.25,191.16,195.13,7007447.0
-2017-10-18,199.99,200.01,194.25,195.54,11133883.0,0.0,1.0,199.99,200.01,194.25,195.54,11133883.0
-2017-10-17,200.11,204.38,197.77,199.48,23819054.0,0.0,1.0,200.11,204.38,197.77,199.48,23819054.0
-2017-10-16,201.95,202.83,197.86,202.68,18103086.0,0.0,1.0,201.95,202.83,197.86,202.68,18103086.0
-2017-10-13,199.7,200.8199,197.1866,199.49,11929816.0,0.0,1.0,199.7,200.8199,197.1866,199.49,11929816.0
-2017-10-12,196.75,198.62,194.71,195.86,7723224.0,0.0,1.0,196.75,198.62,194.71,195.86,7723224.0
-2017-10-11,195.57,196.2199,193.81,194.95,5544715.0,0.0,1.0,195.57,196.2199,193.81,194.95,5544715.0
-2017-10-10,197.85,198.3,192.1,195.08,6179012.0,0.0,1.0,197.85,198.3,192.1,195.08,6179012.0
-2017-10-09,199.1,199.4,196.56,196.87,6912140.0,0.0,1.0,199.1,199.4,196.56,196.87,6912140.0
-2017-10-06,194.3,198.92,192.05,198.02,15096222.0,0.0,1.0,194.3,198.92,192.05,198.02,15096222.0
-2017-10-05,185.65,194.49,184.49,194.39,19270032.0,0.0,1.0,185.65,194.49,184.49,194.39,19270032.0
-2017-10-04,181.41,186.7,181.25,184.45,9170855.0,0.0,1.0,181.41,186.7,181.25,184.45,9170855.0
-2017-10-03,177.65,179.7,177.55,179.19,3903112.0,0.0,1.0,177.65,179.7,177.55,179.19,3903112.0
-2017-10-02,182.11,182.8,176.58,177.01,7316345.0,0.0,1.0,182.11,182.8,176.58,177.01,7316345.0
-2017-09-29,180.73,182.9,180.65,181.35,4193999.0,0.0,1.0,180.73,182.9,180.65,181.35,4193999.0
-2017-09-28,181.25,181.95,179.36,180.7,4064507.0,0.0,1.0,181.25,181.95,179.36,180.7,4064507.0
-2017-09-27,181.01,183.34,180.7,181.97,4963152.0,0.0,1.0,181.01,183.34,180.7,181.97,4963152.0
-2017-09-26,180.7,180.95,176.55,179.38,5572599.0,0.0,1.0,180.7,180.95,176.55,179.38,5572599.0
-2017-09-25,186.46,186.55,177.7,178.55,9322531.0,0.0,1.0,186.46,186.55,177.7,178.55,9322531.0
-2017-09-22,188.4,189.85,186.39,187.35,5420227.0,0.0,1.0,188.4,189.85,186.39,187.35,5420227.0
-2017-09-21,185.82,189.95,184.51,188.78,7113489.0,0.0,1.0,185.82,189.95,184.51,188.78,7113489.0
-2017-09-20,186.1,186.5,183.2,185.51,4473036.0,0.0,1.0,186.1,186.5,183.2,185.51,4473036.0
-2017-09-19,184.98,186.23,184.17,185.68,4951465.0,0.0,1.0,184.98,186.23,184.17,185.68,4951465.0
-2017-09-18,183.61,185.45,182.73,184.62,5318130.0,0.0,1.0,183.61,185.45,182.73,184.62,5318130.0
-2017-09-15,182.73,184.93,181.43,182.1,5442089.0,0.0,1.0,182.73,184.93,181.43,182.1,5442089.0
-2017-09-14,183.25,185.2882,182.07,182.63,4469985.0,0.0,1.0,183.25,185.2882,182.07,182.63,4469985.0
-2017-09-13,184.07,184.4995,182.55,183.64,4303277.0,0.0,1.0,184.07,184.4995,182.55,183.64,4303277.0
-2017-09-12,182.55,185.33,180.6435,185.15,6606688.0,0.0,1.0,182.55,185.33,180.6435,185.15,6606688.0
-2017-09-11,178.1,182.47,178.03,181.74,5936476.0,0.0,1.0,178.1,182.47,178.03,181.74,5936476.0
-2017-09-08,178.45,180.39,176.25,176.42,4577777.0,0.0,1.0,178.45,180.39,176.25,176.42,4577777.0
-2017-09-07,178.8,180.35,177.1,179.0,5938152.0,0.0,1.0,178.8,180.35,177.1,179.0,5938152.0
-2017-09-06,175.25,179.46,173.73,179.25,8695383.0,0.0,1.0,175.25,179.46,173.73,179.25,8695383.0
-2017-09-05,173.4,175.88,172.44,174.52,4580903.0,0.0,1.0,173.4,175.88,172.44,174.52,4580903.0
-2017-09-01,175.55,176.48,173.92,174.74,3781453.0,0.0,1.0,175.55,176.48,173.92,174.74,3781453.0
-2017-08-31,175.45,176.24,173.86,174.71,6886143.0,0.0,1.0,175.45,176.24,173.86,174.71,6886143.0
-2017-08-30,169.5,174.85,169.37,174.69,7985196.0,0.0,1.0,169.5,174.85,169.37,174.69,7985196.0
-2017-08-29,165.0,169.68,164.73,168.81,4573282.0,0.0,1.0,165.0,169.68,164.73,168.81,4573282.0
-2017-08-28,166.43,168.67,165.6,167.12,3619575.0,0.0,1.0,166.43,168.67,165.6,167.12,3619575.0
-2017-08-25,168.58,168.75,165.5,165.95,4045626.0,0.0,1.0,168.58,168.75,165.5,165.95,4045626.0
-2017-08-24,169.86,171.2363,166.15,168.13,5270931.0,0.0,1.0,169.86,171.2363,166.15,168.13,5270931.0
-2017-08-23,168.35,169.64,166.7,169.06,4616656.0,0.0,1.0,168.35,169.64,166.7,169.06,4616656.0
-2017-08-22,167.76,169.93,167.04,169.34,4857816.0,0.0,1.0,167.76,169.93,167.04,169.34,4857816.0
-2017-08-21,166.91,168.99,164.23,166.76,6303314.0,0.0,1.0,166.91,168.99,164.23,166.76,6303314.0
-2017-08-18,165.95,169.97,165.8,166.54,7363750.0,0.0,1.0,165.95,169.97,165.8,166.54,7363750.0
-2017-08-17,169.23,170.58,165.72,166.09,5161920.0,0.0,1.0,169.23,170.58,165.72,166.09,5161920.0
-2017-08-16,167.5,170.5,166.25,169.98,6916579.0,0.0,1.0,167.5,170.5,166.25,169.98,6916579.0
-2017-08-15,171.53,171.88,168.25,168.5,5470271.0,0.0,1.0,171.53,171.88,168.25,168.5,5470271.0
-2017-08-14,169.8,172.45,168.8,171.0,7377962.0,0.0,1.0,169.8,172.45,168.8,171.0,7377962.0
-2017-08-11,169.86,172.58,169.0,171.4,4972045.0,0.0,1.0,169.86,172.58,169.0,171.4,4972045.0
-2017-08-10,174.03,174.45,167.6,169.14,9539473.0,0.0,1.0,174.03,174.45,167.6,169.14,9539473.0
-2017-08-09,171.43,175.96,170.01,175.78,9573608.0,0.0,1.0,171.43,175.96,170.01,175.78,9573608.0
-2017-08-08,181.37,181.91,177.45,178.36,4806525.0,0.0,1.0,181.37,181.91,177.45,178.36,4806525.0
-2017-08-07,181.0,182.27,179.1,181.33,4470746.0,0.0,1.0,181.0,182.27,179.1,181.33,4470746.0
-2017-08-04,179.6,181.0,178.5,180.27,4446148.0,0.0,1.0,179.6,181.0,178.5,180.27,4446148.0
-2017-08-03,180.53,181.2248,178.02,179.23,4596187.0,0.0,1.0,180.53,181.2248,178.02,179.23,4596187.0
-2017-08-02,182.22,182.57,177.8149,180.74,5713517.0,0.0,1.0,182.22,182.57,177.8149,180.74,5713517.0
-2017-08-01,182.49,184.62,181.43,182.03,5003248.0,0.0,1.0,182.49,184.62,181.43,182.03,5003248.0
-2017-07-31,184.26,184.9738,180.65,181.66,4776740.0,0.0,1.0,184.26,184.9738,180.65,181.66,4776740.0
-2017-07-28,182.0,185.03,181.18,184.04,6166404.0,0.0,1.0,182.0,185.03,181.18,184.04,6166404.0
-2017-07-27,189.89,190.0,179.38,182.68,11013995.0,0.0,1.0,189.89,190.0,179.38,182.68,11013995.0
-2017-07-26,187.7,189.7043,187.51,189.08,4354866.0,0.0,1.0,187.7,189.7043,187.51,189.08,4354866.0
-2017-07-25,187.79,188.66,185.81,186.97,5357533.0,0.0,1.0,187.79,188.66,185.81,186.97,5357533.0
-2017-07-24,188.685,190.25,187.01,187.91,8646192.0,0.0,1.0,188.685,190.25,187.01,187.91,8646192.0
-2017-07-21,182.72,191.5,182.71,188.54,9215232.0,0.0,1.0,182.72,191.5,182.71,188.54,9215232.0
-2017-07-20,183.84,185.92,182.7,183.6,7688768.0,0.0,1.0,183.84,185.92,182.7,183.6,7688768.0
-2017-07-19,182.97,187.17,181.75,183.86,17149580.0,0.0,1.0,182.97,187.17,181.75,183.86,17149580.0
-2017-07-18,176.12,185.0,174.24,183.6,40126110.0,0.0,1.0,176.12,185.0,174.24,183.6,40126110.0
-2017-07-17,162.91,163.55,160.0201,161.7,12299024.0,0.0,1.0,162.91,163.55,160.0201,161.7,12299024.0
-2017-07-14,159.3,161.35,157.97,161.12,5412128.0,0.0,1.0,159.3,161.35,157.97,161.12,5412128.0
-2017-07-13,158.51,160.13,156.98,158.17,6666000.0,0.0,1.0,158.51,160.13,156.98,158.17,6666000.0
-2017-07-12,155.77,158.8,155.77,158.75,8095303.0,0.0,1.0,155.77,158.8,155.77,158.75,8095303.0
-2017-07-11,152.37,155.23,151.55,154.33,4824579.0,0.0,1.0,152.37,155.23,151.55,154.33,4824579.0
-2017-07-10,150.34,153.23,149.65,152.67,5113353.0,0.0,1.0,150.34,153.23,149.65,152.67,5113353.0
-2017-07-07,146.65,150.75,146.65,150.18,5490809.0,0.0,1.0,146.65,150.75,146.65,150.18,5490809.0
-2017-07-06,146.13,147.27,144.25,146.25,5253871.0,0.0,1.0,146.13,147.27,144.25,146.25,5253871.0
-2017-07-05,146.58,148.26,145.58,147.61,4469163.0,0.0,1.0,146.58,148.26,145.58,147.61,4469163.0
-2017-07-03,149.8,150.45,145.8,146.17,3907790.0,0.0,1.0,149.8,150.45,145.8,146.17,3907790.0
-2017-06-30,149.76,150.71,148.42,149.41,5164844.0,0.0,1.0,149.76,150.71,148.42,149.41,5164844.0
-2017-06-29,152.82,152.82,148.0,150.09,7106930.0,0.0,1.0,152.82,152.82,148.0,150.09,7106930.0
-2017-06-28,151.64,154.2,150.12,153.41,5522740.0,0.0,1.0,151.64,154.2,150.12,153.41,5522740.0
-2017-06-27,156.62,156.9775,150.7197,151.03,7386827.0,0.0,1.0,156.62,156.9775,150.7197,151.03,7386827.0
-2017-06-26,158.78,159.97,156.56,157.5,5951060.0,0.0,1.0,158.78,159.97,156.56,157.5,5951060.0
-2017-06-23,155.01,158.19,153.76,158.03,6086644.0,0.0,1.0,155.01,158.19,153.76,158.03,6086644.0
-2017-06-22,155.13,155.2,153.7,154.89,3735995.0,0.0,1.0,155.13,155.2,153.7,154.89,3735995.0
-2017-06-21,152.5,155.38,152.26,155.03,5783436.0,0.0,1.0,152.5,155.38,152.26,155.03,5783436.0
-2017-06-20,153.68,154.5,151.4,152.05,4850911.0,0.0,1.0,153.68,154.5,151.4,152.05,4850911.0
-2017-06-19,154.29,155.58,152.41,153.4,6461866.0,0.0,1.0,154.29,155.58,152.41,153.4,6461866.0
-2017-06-16,151.45,153.53,150.39,152.38,6751799.0,0.0,1.0,151.45,153.53,150.39,152.38,6751799.0
-2017-06-15,149.44,152.56,147.3,151.76,6976720.0,0.0,1.0,149.44,152.56,147.3,151.76,6976720.0
-2017-06-14,154.34,155.615,150.28,152.2,6364572.0,0.0,1.0,154.34,155.615,150.28,152.2,6364572.0
-2017-06-13,154.38,155.68,150.13,152.72,8379437.0,0.0,1.0,154.38,155.68,150.13,152.72,8379437.0
-2017-06-12,155.3,155.53,148.31,151.44,14045559.0,0.0,1.0,155.3,155.53,148.31,151.44,14045559.0
-2017-06-09,166.27,166.27,154.5,158.03,10255110.0,0.0,1.0,166.27,166.27,154.5,158.03,10255110.0
-2017-06-08,166.12,166.87,164.84,165.88,3666393.0,0.0,1.0,166.12,166.87,164.84,165.88,3666393.0
-2017-06-07,165.6,166.4,164.4086,165.61,3285592.0,0.0,1.0,165.6,166.4,164.4086,165.61,3285592.0
-2017-06-06,164.95,166.82,164.51,165.17,4325459.0,0.0,1.0,164.95,166.82,164.51,165.17,4325459.0
-2017-06-05,165.49,165.5,163.43,165.06,3830296.0,0.0,1.0,165.49,165.5,163.43,165.06,3830296.0
-2017-06-02,163.42,165.36,162.8,165.18,4217679.0,0.0,1.0,163.42,165.36,162.8,165.18,4217679.0
-2017-06-01,163.52,163.9316,161.7,162.99,3869808.0,0.0,1.0,163.52,163.9316,161.7,162.99,3869808.0
diff --git a/examples/quick/demos/stocqt/content/data/NTAP.csv b/examples/quick/demos/stocqt/content/data/NTAP.csv
deleted file mode 100644
index dcceae9ac7..0000000000
--- a/examples/quick/demos/stocqt/content/data/NTAP.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,55.8,55.94,55.26,55.32,1287431.0,0.0,1.0,55.8,55.94,55.26,55.32,1287431.0
-2017-12-28,56.25,56.45,55.39,55.8,904513.0,0.0,1.0,56.25,56.45,55.39,55.8,904513.0
-2017-12-27,55.9,56.19,55.76,56.15,961107.0,0.0,1.0,55.9,56.19,55.76,56.15,961107.0
-2017-12-26,56.2,56.3,55.64,55.86,875796.0,0.0,1.0,56.2,56.3,55.64,55.86,875796.0
-2017-12-22,56.19,56.49,56.16,56.3,1019859.0,0.0,1.0,56.19,56.49,56.16,56.3,1019859.0
-2017-12-21,57.09,57.17,56.13,56.21,2342109.0,0.0,1.0,57.09,57.17,56.13,56.21,2342109.0
-2017-12-20,58.42,58.44,56.88,57.04,1872565.0,0.0,1.0,58.42,58.44,56.88,57.04,1872565.0
-2017-12-19,57.71,58.125,57.47,57.91,3065092.0,0.0,1.0,57.71,58.125,57.47,57.91,3065092.0
-2017-12-18,57.76,58.13,57.43,57.73,2009903.0,0.0,1.0,57.76,58.13,57.43,57.73,2009903.0
-2017-12-15,57.29,57.88,57.26,57.27,4421855.0,0.0,1.0,57.29,57.88,57.26,57.27,4421855.0
-2017-12-14,57.89,58.16,57.25,57.37,2368380.0,0.0,1.0,57.89,58.16,57.25,57.37,2368380.0
-2017-12-13,57.95,58.32,57.71,57.78,2930515.0,0.0,1.0,57.95,58.32,57.71,57.78,2930515.0
-2017-12-12,58.67,58.82,57.76,57.8,2540225.0,0.0,1.0,58.67,58.82,57.76,57.8,2540225.0
-2017-12-11,58.09,58.99,58.0,58.58,2795677.0,0.0,1.0,58.09,58.99,58.0,58.58,2795677.0
-2017-12-08,57.9,58.63,57.475,58.26,3376794.0,0.0,1.0,57.9,58.63,57.475,58.26,3376794.0
-2017-12-07,57.21,57.82,56.72,57.53,2822878.0,0.0,1.0,57.21,57.82,56.72,57.53,2822878.0
-2017-12-06,56.14,57.275,55.92,57.21,3139341.0,0.0,1.0,56.14,57.275,55.92,57.21,3139341.0
-2017-12-05,55.97,56.56,55.62,56.14,2585323.0,0.0,1.0,55.97,56.56,55.62,56.14,2585323.0
-2017-12-04,56.72,58.11,55.92,55.93,4249052.0,0.0,1.0,56.72,58.11,55.92,55.93,4249052.0
-2017-12-01,55.59,56.51,54.93,56.41,4054006.0,0.0,1.0,55.59,56.51,54.93,56.41,4054006.0
-2017-11-30,56.79,57.75,56.5,56.51,4294760.0,0.0,1.0,56.79,57.75,56.5,56.51,4294760.0
-2017-11-29,56.67,57.18,56.08,56.23,2628942.0,0.0,1.0,56.67,57.18,56.08,56.23,2628942.0
-2017-11-28,56.15,56.91,56.08,56.8,2472780.0,0.0,1.0,56.15,56.91,56.08,56.8,2472780.0
-2017-11-27,56.0,56.32,55.205,56.23,2818463.0,0.0,1.0,56.0,56.32,55.205,56.23,2818463.0
-2017-11-24,56.1,56.55,56.0,56.41,1533554.0,0.0,1.0,56.1,56.55,56.0,56.41,1533554.0
-2017-11-22,55.0,56.1,54.69,56.05,2732890.0,0.0,1.0,55.0,56.1,54.69,56.05,2732890.0
-2017-11-21,54.55,55.5,54.44,55.08,3438391.0,0.0,1.0,54.55,55.5,54.44,55.08,3438391.0
-2017-11-20,52.5,54.81,52.46,54.73,4364375.0,0.0,1.0,52.5,54.81,52.46,54.73,4364375.0
-2017-11-17,53.03,54.72,52.5,52.95,5601447.0,0.0,1.0,53.03,54.72,52.5,52.95,5601447.0
-2017-11-16,51.41,53.89,51.31,53.11,12798497.0,0.0,1.0,51.41,53.89,51.31,53.11,12798497.0
-2017-11-15,45.45,46.09,45.24,45.82,3834732.0,0.0,1.0,45.45,46.09,45.24,45.82,3834732.0
-2017-11-14,45.95,46.14,45.59,45.62,2122392.0,0.0,1.0,45.95,46.14,45.59,45.62,2122392.0
-2017-11-13,46.21,46.62,45.93,46.0,2314390.0,0.0,1.0,46.21,46.62,45.93,46.0,2314390.0
-2017-11-10,46.19,46.7,46.1,46.34,1641852.0,0.0,1.0,46.19,46.7,46.1,46.34,1641852.0
-2017-11-09,46.15,47.2,45.93,46.3,3559622.0,0.0,1.0,46.15,47.2,45.93,46.3,3559622.0
-2017-11-07,45.0,45.07,44.41,44.65,1904133.0,0.0,1.0,45.0,45.07,44.41,44.65,1904133.0
-2017-11-06,44.07,45.12,44.02,45.005,2541032.0,0.0,1.0,44.07,45.12,44.02,45.005,2541032.0
-2017-11-03,44.39,44.485,43.91,44.24,2055137.0,0.0,1.0,44.39,44.485,43.91,44.24,2055137.0
-2017-11-02,44.55,44.605,43.94,44.25,2109252.0,0.0,1.0,44.55,44.605,43.94,44.25,2109252.0
-2017-11-01,44.74,44.9,44.4,44.53,1937032.0,0.0,1.0,44.74,44.9,44.4,44.53,1937032.0
-2017-10-31,43.71,44.57,43.56,44.42,2462916.0,0.0,1.0,43.71,44.57,43.56,44.42,2462916.0
-2017-10-30,43.74,43.95,43.24,43.52,2050846.0,0.0,1.0,43.74,43.95,43.24,43.52,2050846.0
-2017-10-27,44.52,44.52,43.86,44.01,1818983.0,0.0,1.0,44.52,44.52,43.86,44.01,1818983.0
-2017-10-26,43.92,44.675,43.82,44.42,1567088.0,0.0,1.0,43.92,44.675,43.82,44.42,1567088.0
-2017-10-25,44.66,44.66,43.665,43.71,3428810.0,0.0,1.0,44.66,44.66,43.665,43.71,3428810.0
-2017-10-24,44.7,45.03,44.65,44.82,2477689.0,0.0,1.0,44.7,45.03,44.65,44.82,2477689.0
-2017-10-23,44.92,45.14,44.66,44.74,2719135.0,0.0,1.0,44.92,45.14,44.66,44.74,2719135.0
-2017-10-20,44.57,45.03,44.39,44.56,2540716.0,0.0,1.0,44.57,45.03,44.39,44.56,2540716.0
-2017-10-19,44.37,44.505,43.91,44.26,2253612.0,0.0,1.0,44.37,44.505,43.91,44.26,2253612.0
-2017-10-18,44.32,44.64,44.08,44.62,2523179.0,0.0,1.0,44.32,44.64,44.08,44.62,2523179.0
-2017-10-17,43.29,44.11,43.29,44.08,1760179.0,0.0,1.0,43.29,44.11,43.29,44.08,1760179.0
-2017-10-16,43.83,43.939,43.65,43.72,1433772.0,0.0,1.0,43.83,43.939,43.65,43.72,1433772.0
-2017-10-13,43.65,44.22,43.615,43.63,1840650.0,0.0,1.0,43.65,44.22,43.615,43.63,1840650.0
-2017-10-12,43.38,43.59,42.99,43.42,3223379.0,0.0,1.0,43.38,43.59,42.99,43.42,3223379.0
-2017-10-11,43.54,43.9399,43.29,43.51,1654470.0,0.0,1.0,43.54,43.9399,43.29,43.51,1654470.0
-2017-10-10,44.36,44.52,43.57,43.66,3930121.0,0.0,1.0,44.36,44.52,43.57,43.66,3930121.0
-2017-10-09,44.42,44.815,44.25,44.37,2039538.0,0.0,1.0,44.42,44.815,44.25,44.37,2039538.0
-2017-10-06,44.34,44.63,44.05,44.43,1778991.0,0.0,1.0,44.34,44.63,44.05,44.43,1778991.0
-2017-10-05,44.28,44.565,44.17,44.55,2957479.0,0.2,1.0,44.28,44.565,44.17,44.55,2957479.0
-2017-10-04,44.19,44.54,44.17,44.46,2875404.0,0.0,1.0,43.992502793296,44.340938547486,43.972592178771,44.261296089385,2875404.0
-2017-10-03,44.07,44.52,43.75,44.39,2905694.0,0.0,1.0,43.873039106145,44.321027932961,43.554469273743,44.191608938547,2905694.0
-2017-10-02,43.89,44.1,43.71,44.0,3186168.0,0.0,1.0,43.693843575419,43.902905027933,43.514648044693,43.803351955307,3186168.0
-2017-09-29,43.7,43.975,43.39,43.76,1866218.0,0.0,1.0,43.50469273743,43.778463687151,43.196078212291,43.564424581006,1866218.0
-2017-09-28,43.95,44.045,43.52,43.84,2195811.0,0.0,1.0,43.753575418994,43.848150837989,43.325497206704,43.644067039106,2195811.0
-2017-09-27,43.98,44.47,43.56,44.17,2566121.0,0.0,1.0,43.783441340782,44.271251396648,43.365318435754,43.972592178771,2566121.0
-2017-09-26,43.0,43.82,42.875,43.76,3262283.0,0.0,1.0,42.80782122905,43.624156424581,42.683379888268,43.564424581006,3262283.0
-2017-09-25,42.17,43.085,42.11,42.7,2486787.0,0.0,1.0,41.981530726257,42.892441340782,41.921798882682,42.509162011173,2486787.0
-2017-09-22,41.77,42.6,41.7,42.55,1820422.0,0.0,1.0,41.583318435754,42.409608938547,41.513631284916,42.359832402235,1820422.0
-2017-09-21,41.75,42.04,41.64,41.86,2621389.0,0.0,1.0,41.563407821229,41.852111731844,41.453899441341,41.672916201117,2621389.0
-2017-09-20,41.72,41.91,41.22,41.7,2878107.0,0.0,1.0,41.533541899441,41.72269273743,41.035776536313,41.513631284916,2878107.0
-2017-09-19,41.79,42.32,41.3,41.71,5252863.0,0.0,1.0,41.603229050279,42.130860335196,41.115418994413,41.523586592179,5252863.0
-2017-09-18,41.04,41.16,40.51,40.63,2686167.0,0.0,1.0,40.856581005587,40.976044692737,40.32894972067,40.448413407821,2686167.0
-2017-09-15,40.72,41.06,40.33,41.03,3537425.0,0.0,1.0,40.538011173184,40.876491620112,40.149754189944,40.846625698324,3537425.0
-2017-09-14,40.17,40.69,39.95,40.65,2799617.0,0.0,1.0,39.990469273743,40.508145251397,39.771452513966,40.468324022346,2799617.0
-2017-09-13,39.82,40.54,39.55,40.28,3019737.0,0.0,1.0,39.642033519553,40.358815642458,39.373240223464,40.099977653631,3019737.0
-2017-09-12,39.62,40.24,39.16,39.93,4031681.0,0.0,1.0,39.442927374302,40.060156424581,38.984983240223,39.751541899441,4031681.0
-2017-09-11,38.91,39.56,38.8,39.46,2798378.0,0.0,1.0,38.736100558659,39.383195530726,38.626592178771,39.283642458101,2798378.0
-2017-09-08,38.61,38.835,38.3799,38.63,2715485.0,0.0,1.0,38.437441340782,38.66143575419,38.20836972067,38.457351955307,2715485.0
-2017-09-07,38.9,38.9,38.12,38.69,2541004.0,0.0,1.0,38.726145251397,38.726145251397,37.949631284916,38.517083798883,2541004.0
-2017-09-06,38.09,38.97,37.855,38.85,3720730.0,0.0,1.0,37.919765363128,38.795832402235,37.685815642458,38.676368715084,3720730.0
-2017-09-05,38.49,38.74,37.55,37.98,2318304.0,0.0,1.0,38.317977653631,38.566860335196,37.38217877095,37.81025698324,2318304.0
-2017-09-01,38.82,38.9,38.56,38.65,1784904.0,0.0,1.0,38.646502793296,38.726145251397,38.387664804469,38.477262569832,1784904.0
-2017-08-31,38.46,38.6975,38.07,38.66,2576968.0,0.0,1.0,38.288111731844,38.52455027933,37.899854748603,38.487217877095,2576968.0
-2017-08-30,37.98,38.26,37.84,38.22,1625130.0,0.0,1.0,37.81025698324,38.089005586592,37.670882681564,38.049184357542,1625130.0
-2017-08-29,37.92,38.315,37.89,38.03,1437800.0,0.0,1.0,37.750525139665,38.143759776536,37.720659217877,37.860033519553,1437800.0
-2017-08-28,38.73,38.81,38.18,38.34,1448478.0,0.0,1.0,38.556905027933,38.636547486034,38.009363128492,38.168648044693,1448478.0
-2017-08-25,38.97,38.99,38.52,38.54,1868152.0,0.0,1.0,38.795832402235,38.81574301676,38.347843575419,38.367754189944,1868152.0
-2017-08-24,38.76,38.93,38.51,38.81,2128753.0,0.0,1.0,38.586770949721,38.756011173184,38.337888268156,38.636547486034,2128753.0
-2017-08-23,38.49,38.95,38.35,38.6792,2625700.0,0.0,1.0,38.317977653631,38.775921787709,38.178603351955,38.506332067039,2625700.0
-2017-08-22,39.17,39.21,38.59,38.7,3834442.0,0.0,1.0,38.994938547486,39.034759776536,38.417530726257,38.527039106145,3834442.0
-2017-08-21,39.76,39.87,38.51,38.95,4371303.0,0.0,1.0,39.582301675978,39.691810055866,38.337888268156,38.775921787709,4371303.0
-2017-08-18,39.62,39.87,39.26,39.35,4934878.0,0.0,1.0,39.442927374302,39.691810055866,39.084536312849,39.174134078212,4934878.0
-2017-08-17,40.37,41.49,39.475,39.56,11599368.0,0.0,1.0,40.189575418994,41.304569832402,39.298575418994,39.383195530726,11599368.0
-2017-08-16,42.0,42.549,42.0,42.41,3481046.0,0.0,1.0,41.812290502793,42.358836871508,41.812290502793,42.220458100559,3481046.0
-2017-08-15,42.96,43.05,41.97,41.97,3781136.0,0.0,1.0,42.768,42.857597765363,41.782424581006,41.782424581006,3781136.0
-2017-08-14,42.37,42.53,41.75,42.03,3763330.0,0.0,1.0,42.180636871508,42.339921787709,41.563407821229,41.842156424581,3763330.0
-2017-08-11,41.44,41.85,41.23,41.49,1407483.0,0.0,1.0,41.254793296089,41.662960893855,41.045731843575,41.304569832402,1407483.0
-2017-08-10,42.01,42.23,41.23,41.29,2117207.0,0.0,1.0,41.822245810056,42.041262569832,41.045731843575,41.105463687151,2117207.0
-2017-08-09,42.49,42.61,42.18,42.24,1538691.0,0.0,1.0,42.300100558659,42.41956424581,41.99148603352,42.051217877095,1538691.0
-2017-08-08,42.66,43.16,42.52,42.69,1901300.0,0.0,1.0,42.469340782123,42.967106145251,42.329966480447,42.499206703911,1901300.0
-2017-08-07,42.83,42.8843,42.44,42.74,1611901.0,0.0,1.0,42.638581005587,42.692638324022,42.250324022346,42.548983240223,1611901.0
-2017-08-04,43.07,43.11,42.61,42.74,1871097.0,0.0,1.0,42.877508379888,42.917329608939,42.41956424581,42.548983240223,1871097.0
-2017-08-03,43.34,43.34,42.74,42.91,2350321.0,0.0,1.0,43.146301675978,43.146301675978,42.548983240223,42.718223463687,2350321.0
-2017-08-02,43.65,43.79,43.04,43.41,1460145.0,0.0,1.0,43.454916201117,43.594290502793,42.847642458101,43.215988826816,1460145.0
-2017-08-01,43.72,43.83,43.16,43.55,2576291.0,0.0,1.0,43.524603351955,43.634111731844,42.967106145251,43.355363128492,2576291.0
-2017-07-31,43.67,43.82,43.11,43.42,2360992.0,0.0,1.0,43.474826815642,43.624156424581,42.917329608939,43.225944134078,2360992.0
-2017-07-28,43.66,43.86,43.09,43.49,2581751.0,0.0,1.0,43.46487150838,43.663977653631,42.897418994413,43.295631284916,2581751.0
-2017-07-27,44.32,44.97,43.65,44.0197,4149229.0,0.0,1.0,44.121921787709,44.769016759777,43.454916201117,43.822963910615,4149229.0
-2017-07-26,44.87,44.87,44.025,44.36,3272594.0,0.0,1.0,44.669463687151,44.669463687151,43.828240223464,44.16174301676,3272594.0
-2017-07-25,44.58,44.94,44.21,44.76,3495184.0,0.0,1.0,44.380759776536,44.739150837989,44.012413407821,44.559955307263,3495184.0
-2017-07-24,44.4,45.23,44.4,44.86,2877601.0,0.0,1.0,44.20156424581,45.027854748603,44.20156424581,44.659508379888,2877601.0
-2017-07-21,44.56,45.24,44.18,44.76,4496318.0,0.0,1.0,44.360849162011,45.037810055866,43.982547486034,44.559955307263,4496318.0
-2017-07-20,44.18,44.69,44.09,44.6,3563323.0,0.0,1.0,43.982547486034,44.490268156425,43.89294972067,44.400670391061,3563323.0
-2017-07-19,43.88,44.5299,43.83,44.16,3618018.0,0.0,1.0,43.683888268156,44.330883687151,43.634111731844,43.962636871508,3618018.0
-2017-07-18,43.25,43.88,43.18,43.77,3030714.0,0.0,1.0,43.056703910615,43.683888268156,42.987016759777,43.574379888268,3030714.0
-2017-07-17,43.2,43.76,43.0,43.62,5253442.0,0.0,1.0,43.006927374302,43.564424581006,42.80782122905,43.42505027933,5253442.0
-2017-07-14,42.04,43.9,42.0,43.64,8405233.0,0.0,1.0,41.852111731844,43.703798882682,41.812290502793,43.444960893855,8405233.0
-2017-07-13,40.17,41.5,40.04,41.38,3940472.0,0.0,1.0,39.990469273743,41.314525139665,39.86105027933,41.195061452514,3940472.0
-2017-07-12,39.45,40.19,39.1701,40.17,2597317.0,0.0,1.0,39.273687150838,40.010379888268,38.995038100559,39.990469273743,2597317.0
-2017-07-11,38.55,39.11,38.51,39.07,2155200.0,0.0,1.0,38.377709497207,38.935206703911,38.337888268156,38.89538547486,2155200.0
-2017-07-10,38.5,38.91,38.35,38.57,2273543.0,0.0,1.0,38.327932960894,38.736100558659,38.178603351955,38.397620111732,2273543.0
-2017-07-07,38.44,38.83,38.32,38.64,1883863.0,0.0,1.0,38.268201117318,38.656458100559,38.148737430168,38.46730726257,1883863.0
-2017-07-06,39.33,39.39,38.2,38.3,2510853.0,0.0,1.0,39.154223463687,39.213955307263,38.029273743017,38.128826815642,2510853.0
-2017-07-05,39.55,40.25,39.475,39.66,2484571.0,0.2,1.0,39.373240223464,40.070111731844,39.298575418994,39.482748603352,2484571.0
-2017-07-03,40.44,40.5,39.53,39.57,1568751.0,0.0,1.0,40.057259245348,40.116691380726,39.155871858768,39.195493282354,1568751.0
-2017-06-30,40.18,40.38,39.73,40.05,3859273.0,0.0,1.0,39.799719992039,39.997827109969,39.353978976698,39.670950365385,3859273.0
-2017-06-29,40.28,40.38,39.55,40.1,3177050.0,0.0,1.0,39.898773551004,39.997827109969,39.175682570561,39.720477144867,3177050.0
-2017-06-28,39.8,40.59,39.6,40.41,2635603.0,0.0,1.0,39.423316467973,40.205839583795,39.225209350044,40.027543177658,2635603.0
-2017-06-27,40.14,40.35,39.62,39.63,2705421.0,0.0,1.0,39.760098568453,39.968111042279,39.245020061837,39.254925417733,2705421.0
-2017-06-26,39.87,40.515,39.87,40.29,3251780.0,0.0,1.0,39.492653959248,40.131549414571,39.492653959248,39.9086789069,3251780.0
-2017-06-23,39.13,40.07,39.01,39.87,4505252.0,0.0,1.0,38.759657622909,39.690761077178,38.640793352152,39.492653959248,4505252.0
-2017-06-22,38.59,39.36,38.58,39.11,3042690.0,0.0,1.0,38.2247684045,38.987480808528,38.214863048603,38.739846911116,3042690.0
-2017-06-21,38.36,38.86,38.3501,38.61,2462900.0,0.0,1.0,37.996945218881,38.492213013704,37.987138916543,38.244579116292,2462900.0
-2017-06-20,38.27,38.65,38.25,38.26,2206944.0,0.0,1.0,37.907797015812,38.284200539878,37.887986304019,37.897891659916,2206944.0
-2017-06-19,38.17,38.495,38.04,38.42,2487716.0,0.0,1.0,37.808743456848,38.130667523483,37.679973830193,38.056377354259,2487716.0
-2017-06-16,37.94,38.11,37.78,37.98,2238387.0,0.0,1.0,37.580920271229,37.749311321469,37.422434576885,37.620541694815,2238387.0
-2017-06-15,37.72,38.1,37.43,37.97,2208659.0,0.0,1.0,37.363002441506,37.739405965572,37.075747120508,37.610636338918,2208659.0
-2017-06-14,38.94,39.01,37.78,38.1,2849570.0,0.0,1.0,38.571455860876,38.640793352152,37.422434576885,37.739405965572,2849570.0
-2017-06-13,38.95,39.37,38.7,38.93,2827824.0,0.0,1.0,38.581361216773,38.997386164425,38.333727319361,38.56155050498,2827824.0
-2017-06-12,39.14,39.66,38.65,38.86,4222954.0,0.0,1.0,38.769562978806,39.284641485422,38.284200539878,38.492213013704,4222954.0
-2017-06-09,39.87,40.395,39.13,39.52,2961902.0,0.0,1.0,39.492653959248,40.012685143813,38.759657622909,39.145966502872,2961902.0
-2017-06-08,39.21,40.12,39.09,40.01,3552505.0,0.0,1.0,38.838900470081,39.74028785666,38.720036199323,39.631328941799,3552505.0
-2017-06-07,38.86,39.57,38.71,39.27,2414656.0,0.0,1.0,38.492213013704,39.195493282354,38.343632675257,38.89833260546,2414656.0
-2017-06-06,38.7,39.23,38.67,38.7,2459220.0,0.0,1.0,38.333727319361,38.858711181874,38.304011251671,38.333727319361,2459220.0
-2017-06-05,39.19,39.7,38.95,38.98,2387428.0,0.0,1.0,38.819089758288,39.324262909008,38.581361216773,38.611077284462,2387428.0
-2017-06-02,39.51,39.75,39.24,39.41,3121583.0,0.0,1.0,39.136061146975,39.373789688491,38.86861653777,39.037007588011,3121583.0
-2017-06-01,39.85,40.25,39.54,39.61,3933108.0,0.0,1.0,39.472843247455,39.869057483314,39.165777214665,39.23511470594,3933108.0
diff --git a/examples/quick/demos/stocqt/content/data/NVDA.csv b/examples/quick/demos/stocqt/content/data/NVDA.csv
deleted file mode 100644
index c37a25ae5b..0000000000
--- a/examples/quick/demos/stocqt/content/data/NVDA.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,198.46,198.46,193.5,193.5,6896330.0,0.0,1.0,198.46,198.46,193.5,193.5,6896330.0
-2017-12-28,198.13,199.38,197.1514,197.4,5978211.0,0.0,1.0,198.13,199.38,197.1514,197.4,5978211.0
-2017-12-27,196.9,199.97,196.31,197.17,8097374.0,0.0,1.0,196.9,199.97,196.31,197.17,8097374.0
-2017-12-26,193.03,197.75,191.82,197.44,8821296.0,0.0,1.0,193.03,197.75,191.82,197.44,8821296.0
-2017-12-22,194.4,195.65,191.25,195.27,11613423.0,0.0,1.0,194.4,195.65,191.25,195.27,11613423.0
-2017-12-21,196.94,197.95,195.55,195.89,7458634.0,0.0,1.0,196.94,197.95,195.55,195.89,7458634.0
-2017-12-20,197.7,198.07,194.55,196.8,7185318.0,0.0,1.0,197.7,198.07,194.55,196.8,7185318.0
-2017-12-19,197.52,197.73,194.96,196.11,9217358.0,0.0,1.0,197.52,197.73,194.96,196.11,9217358.0
-2017-12-18,193.2,198.02,192.0,197.9,11730697.0,0.0,1.0,193.2,198.02,192.0,197.9,11730697.0
-2017-12-15,188.251,192.38,185.62,191.56,16090200.0,0.0,1.0,188.251,192.38,185.62,191.56,16090200.0
-2017-12-14,185.92,189.34,184.6,186.47,10871746.0,0.0,1.0,185.92,189.34,184.6,186.47,10871746.0
-2017-12-13,192.5,192.55,185.88,186.18,13744496.0,0.0,1.0,192.5,192.55,185.88,186.18,13744496.0
-2017-12-12,192.9,193.84,189.89,190.84,11296559.0,0.0,1.0,192.9,193.84,189.89,190.84,11296559.0
-2017-12-11,192.06,194.78,191.42,194.66,9106693.0,0.0,1.0,192.06,194.78,191.42,194.66,9106693.0
-2017-12-08,194.01,194.78,191.15,191.49,11483868.0,0.0,1.0,194.01,194.78,191.15,191.49,11483868.0
-2017-12-07,191.96,193.6,190.12,191.99,13190983.0,0.0,1.0,191.96,193.6,190.12,191.99,13190983.0
-2017-12-06,185.7,190.14,184.84,189.26,11464458.0,0.0,1.0,185.7,190.14,184.84,189.26,11464458.0
-2017-12-05,182.4,192.7,180.58,187.74,24480558.0,0.0,1.0,182.4,192.7,180.58,187.74,24480558.0
-2017-12-04,200.05,200.3,184.5,186.66,27080405.0,0.0,1.0,200.05,200.3,184.5,186.66,27080405.0
-2017-12-01,199.31,200.13,192.47,197.68,16352946.0,0.0,1.0,199.31,200.13,192.47,197.68,16352946.0
-2017-11-30,199.2,202.68,196.65,200.71,20144301.0,0.0,1.0,199.2,202.68,196.65,200.71,20144301.0
-2017-11-29,210.01,210.1226,191.23,196.42,34731979.0,0.0,1.0,210.01,210.1226,191.23,196.42,34731979.0
-2017-11-28,214.35,214.73,208.24,210.71,12677148.0,0.0,1.0,214.35,214.73,208.24,210.71,12677148.0
-2017-11-27,217.31,217.36,214.01,214.14,10477983.0,0.0,1.0,217.31,217.36,214.01,214.14,10477983.0
-2017-11-24,215.59,217.0,214.6,216.96,4517982.0,0.0,1.0,215.59,217.0,214.6,216.96,4517982.0
-2017-11-22,217.0,217.0,213.61,214.93,8766814.0,0.0,1.0,217.0,217.0,213.61,214.93,8766814.0
-2017-11-21,215.69,216.52,214.4,216.05,9858634.0,0.0,1.0,215.69,216.52,214.4,216.05,9858634.0
-2017-11-20,211.99,214.57,210.5,214.08,9828414.0,0.0,1.0,211.99,214.57,210.5,214.08,9828414.0
-2017-11-17,213.92,215.35,210.75,211.36,12702474.0,0.0,1.0,213.92,215.35,210.75,211.36,12702474.0
-2017-11-16,212.98,214.2,211.25,211.61,9947915.0,0.0,1.0,212.98,214.2,211.25,211.61,9947915.0
-2017-11-15,211.95,212.0,207.8,209.98,12427082.0,0.0,1.0,211.95,212.0,207.8,209.98,12427082.0
-2017-11-14,213.0,214.8,211.23,214.18,13101484.0,0.0,1.0,213.0,214.8,211.23,214.18,13101484.0
-2017-11-13,216.14,217.17,212.01,212.63,14398431.0,0.0,1.0,216.14,217.17,212.01,212.63,14398431.0
-2017-11-10,213.08,218.67,211.63,216.14,31197127.0,0.0,1.0,213.08,218.67,211.63,216.14,31197127.0
-2017-11-09,205.27,206.33,200.37,205.32,20123846.0,0.0,1.0,205.27,206.33,200.37,205.32,20123846.0
-2017-11-07,210.55,212.9,210.0556,212.03,10580672.0,0.0,1.0,210.55,212.9,210.0556,212.03,10580672.0
-2017-11-06,207.2,209.98,206.7,209.63,9693716.0,0.0,1.0,207.2,209.98,206.7,209.63,9693716.0
-2017-11-03,207.2,208.69,205.341,208.69,8777981.0,0.0,1.0,207.2,208.69,205.341,208.69,8777981.0
-2017-11-02,206.0,207.81,203.65,205.94,8480413.0,0.0,1.0,206.0,207.81,203.65,205.94,8480413.0
-2017-11-01,209.35,209.97,204.6,207.2,12385654.0,0.0,1.0,209.35,209.97,204.6,207.2,12385654.0
-2017-10-31,205.13,207.89,204.9,206.81,10179802.0,0.0,1.0,205.13,207.89,204.9,206.81,10179802.0
-2017-10-30,201.86,206.0899,201.22,203.84,12522329.0,0.0,1.0,201.86,206.0899,201.22,203.84,12522329.0
-2017-10-27,197.8,201.87,196.75,201.86,14174171.0,0.0,1.0,197.8,201.87,196.75,201.86,14174171.0
-2017-10-26,194.78,196.16,193.81,195.69,7892651.0,0.0,1.0,194.78,196.16,193.81,195.69,7892651.0
-2017-10-25,197.08,199.22,191.17,193.66,20588601.0,0.0,1.0,197.08,199.22,191.17,193.66,20588601.0
-2017-10-24,196.99,198.75,195.94,198.68,9820462.0,0.0,1.0,196.99,198.75,195.94,198.68,9820462.0
-2017-10-23,197.78,198.85,195.8,196.62,10592416.0,0.0,1.0,197.78,198.85,195.8,196.62,10592416.0
-2017-10-20,198.49,199.59,196.54,196.9,11006029.0,0.0,1.0,198.49,199.59,196.54,196.9,11006029.0
-2017-10-19,194.44,198.0,192.4501,197.8,14156573.0,0.0,1.0,194.44,198.0,192.4501,197.8,14156573.0
-2017-10-18,198.11,198.14,193.32,197.58,14066925.0,0.0,1.0,198.11,198.14,193.32,197.58,14066925.0
-2017-10-17,197.09,198.9,196.35,197.75,11482547.0,0.0,1.0,197.09,198.9,196.35,197.75,11482547.0
-2017-10-16,195.8,198.048,193.24,197.93,14279032.0,0.0,1.0,195.8,198.048,193.24,197.93,14279032.0
-2017-10-13,193.55,195.0,191.65,194.59,15626525.0,0.0,1.0,193.55,195.0,191.65,194.59,15626525.0
-2017-10-12,191.08,193.09,189.9301,191.03,13036890.0,0.0,1.0,191.08,193.09,189.9301,191.03,13036890.0
-2017-10-11,189.6,191.0,187.74,190.94,13051762.0,0.0,1.0,189.6,191.0,187.74,190.94,13051762.0
-2017-10-10,191.43,192.95,187.26,188.88,24261445.0,0.0,1.0,191.43,192.95,187.26,188.88,24261445.0
-2017-10-09,182.79,186.73,182.03,185.39,13986610.0,0.0,1.0,182.79,186.73,182.03,185.39,13986610.0
-2017-10-06,179.65,181.84,179.0,181.3,7911087.0,0.0,1.0,179.65,181.84,179.0,181.3,7911087.0
-2017-10-05,181.86,182.0,179.56,180.77,10830438.0,0.0,1.0,181.86,182.0,179.56,180.77,10830438.0
-2017-10-04,179.62,181.77,178.14,180.87,10621386.0,0.0,1.0,179.62,181.77,178.14,180.87,10621386.0
-2017-10-03,179.25,180.58,177.58,179.37,9678430.0,0.0,1.0,179.25,180.58,177.58,179.37,9678430.0
-2017-10-02,180.8,181.98,177.0,179.0,12475560.0,0.0,1.0,180.8,181.98,177.0,179.0,12475560.0
-2017-09-29,179.08,179.73,177.25,178.77,14936876.0,0.0,1.0,179.08,179.73,177.25,178.77,14936876.0
-2017-09-28,176.02,176.18,173.76,175.68,10801464.0,0.0,1.0,176.02,176.18,173.76,175.68,10801464.0
-2017-09-27,175.62,176.27,172.75,175.73,17602299.0,0.0,1.0,175.62,176.27,172.75,175.73,17602299.0
-2017-09-26,176.45,178.68,170.35,171.96,27542805.0,0.0,1.0,176.45,178.68,170.35,171.96,27542805.0
-2017-09-25,177.75,177.8,170.16,171.0,21628235.0,0.0,1.0,177.75,177.8,170.16,171.0,21628235.0
-2017-09-22,180.3,182.31,178.6,179.0,12196947.0,0.0,1.0,180.3,182.31,178.6,179.0,12196947.0
-2017-09-21,181.64,182.7,177.61,180.7799,26631321.0,0.0,1.0,181.64,182.7,177.61,180.7799,26631321.0
-2017-09-20,187.5,189.42,184.21,185.84,16435216.0,0.0,1.0,187.5,189.42,184.21,185.84,16435216.0
-2017-09-19,185.51,189.85,184.615,187.35,21631434.0,0.0,1.0,185.51,189.85,184.615,187.35,21631434.0
-2017-09-18,185.14,191.2,184.86,187.55,41601951.0,0.0,1.0,185.14,191.2,184.86,187.55,41601951.0
-2017-09-15,172.86,180.11,172.65,180.11,33338633.0,0.0,1.0,172.86,180.11,172.65,180.11,33338633.0
-2017-09-14,168.79,172.56,167.8,169.4,12728431.0,0.0,1.0,168.79,172.56,167.8,169.4,12728431.0
-2017-09-13,168.59,171.54,167.28,170.37,14340105.0,0.0,1.0,168.59,171.54,167.28,170.37,14340105.0
-2017-09-12,170.0,170.0,166.97,169.61,10155905.0,0.0,1.0,170.0,170.0,166.97,169.61,10155905.0
-2017-09-11,165.54,169.4325,165.32,169.0,13934287.0,0.0,1.0,165.54,169.4325,165.32,169.0,13934287.0
-2017-09-08,166.11,166.71,162.71,163.69,12365074.0,0.0,1.0,166.11,166.71,162.71,163.69,12365074.0
-2017-09-07,166.49,167.89,164.95,166.58,8731886.0,0.0,1.0,166.49,167.89,164.95,166.58,8731886.0
-2017-09-06,167.24,167.8,164.4,165.81,9800559.0,0.0,1.0,167.24,167.8,164.4,165.81,9800559.0
-2017-09-05,168.38,168.5843,163.5625,165.91,17358768.0,0.0,1.0,168.38,168.5843,163.5625,165.91,17358768.0
-2017-09-01,169.95,171.9,169.6,170.46,11017001.0,0.0,1.0,169.95,171.9,169.6,170.46,11017001.0
-2017-08-31,166.5,169.6,166.2,169.44,15022660.0,0.0,1.0,166.5,169.6,166.2,169.44,15022660.0
-2017-08-30,165.5,166.13,164.27,165.68,9469680.0,0.0,1.0,165.5,166.13,164.27,165.68,9469680.0
-2017-08-29,162.59,165.58,162.261,164.7,7992338.0,0.0,1.0,162.59,165.58,162.261,164.7,7992338.0
-2017-08-28,164.58,165.1,162.33,164.97,9568908.0,0.0,1.0,164.58,165.1,162.33,164.97,9568908.0
-2017-08-25,166.17,166.58,163.55,163.81,8753208.0,0.0,1.0,166.17,166.58,163.55,163.81,8753208.0
-2017-08-24,167.1,167.28,164.12,165.19,11592997.0,0.0,1.0,167.1,167.28,164.12,165.19,11592997.0
-2017-08-23,161.2,166.25,160.85,165.8,14421053.0,0.0,1.0,161.2,166.25,160.85,165.8,14421053.0
-2017-08-22,160.49,162.79,159.71,162.51,11084658.0,0.14,1.0,160.49,162.79,159.71,162.51,11084658.0
-2017-08-21,162.49,162.95,157.37,159.12,15203637.0,0.0,1.0,162.35013771903,162.80974177682,157.23454472794,158.98303842607,15203637.0
-2017-08-18,163.67,164.36,159.64,161.5,14883408.0,0.0,1.0,163.52912204119,164.21852812788,159.50259083923,161.36098985552,14883408.0
-2017-08-17,164.81,165.5,161.38,161.47,12937916.0,0.0,1.0,164.66814079311,165.3575468798,161.24109314479,161.33101567784,12937916.0
-2017-08-16,167.59,168.54,163.84,165.15,14788247.0,0.0,1.0,167.44574792499,168.39493021826,163.69897571472,165.00784814018,14788247.0
-2017-08-15,168.61,169.67,165.59,166.98,18980198.0,0.0,1.0,168.46486996619,169.52395757762,165.44746941285,166.83627297879,18980198.0
-2017-08-14,159.67,168.55,159.2,168.4,31674266.0,0.0,1.0,159.53256501691,168.40492161082,159.06296956655,168.25505072241,31674266.0
-2017-08-11,157.14,159.0,152.91,155.95,37272782.0,0.0,1.0,157.00474269905,158.86314171534,152.77838364587,155.81576698432,37272782.0
-2017-08-10,172.16,172.66,164.33,164.74,26065538.0,0.0,1.0,172.01181432524,172.51138395327,164.1885539502,164.59820104519,26065538.0
-2017-08-09,168.43,172.21,167.67,172.11,13060514.0,0.0,1.0,168.28502490009,172.06177128804,167.52567906548,171.96185736243,13060514.0
-2017-08-08,173.89,174.56,168.71,170.3,18632853.0,0.0,1.0,173.74032523824,174.40974853981,168.56478389179,170.15341530895,18632853.0
-2017-08-07,168.39,172.37,168.0,172.25,17743004.0,0.0,1.0,168.24505932985,172.22163356901,167.85539501998,172.10173685828,17743004.0
-2017-08-04,167.4,170.07,166.48,167.21,14653397.0,0.0,1.0,167.25591146634,169.92361328005,166.33670335075,167.06607500769,14653397.0
-2017-08-03,164.37,166.63,163.68,166.48,10926536.0,0.0,1.0,164.22851952044,166.48657423916,163.53911343375,166.33670335075,10926536.0
-2017-08-02,165.75,165.91,161.27,164.39,11565556.0,0.0,1.0,165.60733169382,165.76719397479,161.13118782662,164.24850230556,11565556.0
-2017-08-01,162.125,164.56,161.0,164.49,10606575.0,0.0,1.0,161.98545189056,164.4183559791,160.86142022748,164.34841623117,10606575.0
-2017-07-31,164.94,166.4,160.62,162.51,13800261.0,0.0,1.0,164.7980288964,166.25677221027,160.48174731018,162.37012050415,13800261.0
-2017-07-28,160.29,165.38,159.28,164.39,12776296.0,0.0,1.0,160.15203135567,165.23765016907,159.14290070704,164.24850230556,12776296.0
-2017-07-27,168.27,168.74,157.56,161.74,18888931.0,0.0,1.0,168.12516261912,168.59475806947,157.4243811866,161.60078327698,18888931.0
-2017-07-26,167.68,169.927,165.85,167.26,15755026.0,0.0,1.0,167.53567045804,169.78073636643,165.70724561943,167.11603197049,15755026.0
-2017-07-25,165.22,165.93,163.581,165.35,12002860.0,0.0,1.0,165.0777878881,165.78717675991,163.4401986474,165.20767599139,12002860.0
-2017-07-24,168.39,168.78,165.72,166.15,15868676.0,0.0,1.0,168.24505932985,168.63472363972,165.57735751614,166.00698739625,15868676.0
-2017-07-21,166.67,169.3,166.09,168.1,15886110.0,0.0,1.0,166.52653980941,169.15427605287,165.94703904089,167.95530894559,15886110.0
-2017-07-20,165.93,167.51,163.9121,167.48,17258237.0,0.0,1.0,165.78717675991,167.36581678451,163.77101365509,167.33584260682,17258237.0
-2017-07-19,166.33,167.4,164.61,165.1,17014089.0,0.0,1.0,166.18683246234,167.25591146634,164.4683129419,164.95789117737,17014089.0
-2017-07-18,161.78,166.55,161.3,165.96,19123179.0,0.0,1.0,161.64074884722,166.40664309868,161.1611620043,165.8171509376,19123179.0
-2017-07-17,166.33,167.5,161.75,164.25,22936328.0,0.0,1.0,166.18683246234,167.35582539195,161.61077466954,164.10862280971,22936328.0
-2017-07-14,161.29,165.01,161.01,164.95,23349534.0,0.0,1.0,161.15117061174,164.86796864433,160.87141162004,164.80802028896,23349534.0
-2017-07-13,163.0,166.3,158.75,160.63,34123997.0,0.0,1.0,162.85969873962,166.15685828466,158.61335690132,160.49173870274,34123997.0
-2017-07-12,158.3,163.0,156.56,162.51,28283476.0,0.0,1.0,158.16374423609,162.85969873962,156.42524193053,162.37012050415,28283476.0
-2017-07-11,153.85,156.19,152.15,155.88,18744156.0,0.0,1.0,153.71757454657,156.05556040578,152.01903781125,155.7458272364,18744156.0
-2017-07-10,149.74,154.0,148.6842,153.7,23720137.0,0.0,1.0,149.61111220412,153.86744543498,148.55622097756,153.56770365816,23720137.0
-2017-07-07,145.78,147.5,144.85,146.76,16258515.0,0.0,1.0,145.65452075008,147.37304027052,144.72532124193,146.63367722103,16258515.0
-2017-07-06,141.87,145.3799,139.76,143.48,18383056.0,0.0,1.0,141.74788625884,145.25476513372,139.63970242853,143.35650046111,18383056.0
-2017-07-05,141.9,144.22,141.13,143.05,20226442.0,0.0,1.0,141.77786043652,144.09586351061,141.00852320935,142.926870581,20226442.0
-2017-07-03,145.05,145.6537,138.58,139.33,17722284.0,0.0,1.0,144.92514909314,145.52832946204,138.46071810636,139.21007254842,17722284.0
-2017-06-30,147.38,147.93,143.5,144.56,17992137.0,0.0,1.0,147.25314355979,147.80267015063,143.37648324623,144.43557085767,17992137.0
-2017-06-29,150.6,150.72,144.08,146.68,26334702.0,0.0,1.0,150.47037196434,150.59026867507,143.95598401476,146.55374608054,26334702.0
-2017-06-28,149.32,151.94,145.75,151.75,24660291.0,0.0,1.0,149.19147371657,151.80921856748,145.62454657239,151.61938210882,24660291.0
-2017-06-27,151.44,151.79,146.35,146.58,24850612.0,0.0,1.0,151.30964893944,151.65934767907,146.22403012604,146.45383215493,24850612.0
-2017-06-26,155.16,156.6,148.33,152.15,26418557.0,0.0,1.0,155.02644697203,156.46520750077,148.20232585306,152.01903781125,26418557.0
-2017-06-23,158.68,159.32,153.22,154.11,24565502.0,0.0,1.0,158.5434171534,159.18286627728,153.08811681525,153.97735075315,24565502.0
-2017-06-22,159.8,160.34,157.4,158.37,11596308.0,0.0,1.0,159.6624531202,160.20198831848,157.26451890563,158.23368398401,11596308.0
-2017-06-21,158.21,159.62,155.7,159.47,16945632.0,0.0,1.0,158.07382170304,159.4826080541,155.5659821703,159.33273716569,16945632.0
-2017-06-20,159.03,161.74,156.92,157.09,27169647.0,0.0,1.0,158.89311589302,161.60078327698,156.78493206271,156.95478573624,27169647.0
-2017-06-19,153.41,157.53,153.26,157.32,19260255.0,0.0,1.0,153.2779532739,157.39440700891,153.12808238549,157.18458776514,19260255.0
-2017-06-16,152.76,154.7,150.24,151.62,22554327.0,0.0,1.0,152.62851275745,154.56684291423,150.11068183215,151.48949400553,22554327.0
-2017-06-15,146.96,153.6,146.5,152.37,23883179.0,0.0,1.0,146.83350507224,153.46778973255,146.37390101445,152.23884844759,23883179.0
-2017-06-14,151.52,154.06,148.5,151.72,29431459.0,0.0,1.0,151.38958007993,153.92739379035,148.37217952659,151.58940793114,29431459.0
-2017-06-13,154.4,154.77,145.65,151.4,41488612.0,0.0,1.0,154.26710113741,154.63678266216,145.52463264679,151.2696833692,41488612.0
-2017-06-12,145.88,151.7,142.11,149.97,41793262.0,0.0,1.0,145.75443467568,151.56942514602,141.9876796803,149.84091423302,41793262.0
-2017-06-09,164.74,168.5,142.75,149.6,91979374.0,0.0,1.0,164.59820104519,168.35496464802,142.62712880418,149.47123270827,91979374.0
-2017-06-08,153.46,160.0,151.79,159.952,28475455.0,0.0,1.0,153.3279102367,159.86228097141,151.65934767907,159.81432228712,28475455.0
-2017-06-07,148.33,149.88,147.7,149.12,15057318.0,0.0,1.0,148.20232585306,149.75099169997,147.57286812173,148.99164586536,15057318.0
-2017-06-06,147.82,149.69,146.8,147.34,18743334.0,0.0,1.0,147.69276483246,149.56115524132,146.67364279127,147.21317798955,18743334.0
-2017-06-05,142.98,148.53,142.51,148.01,20311623.0,0.0,1.0,142.85693083308,148.40215370427,142.38733538272,147.88260129112,20311623.0
-2017-06-02,144.24,145.3,143.4,143.64,12140804.0,0.0,1.0,144.11584629573,145.17493390716,143.27656932063,143.51636274208,12140804.0
-2017-06-01,144.99,145.03,142.52,144.2499,12462061.0,0.0,1.0,144.86520073778,144.90516630802,142.39732677528,144.12573777436,12462061.0
diff --git a/examples/quick/demos/stocqt/content/data/PYPL.csv b/examples/quick/demos/stocqt/content/data/PYPL.csv
deleted file mode 100644
index 53034c65d2..0000000000
--- a/examples/quick/demos/stocqt/content/data/PYPL.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,73.92,74.53,73.58,73.62,4396182.0,0.0,1.0,73.92,74.53,73.58,73.62,4396182.0
-2017-12-28,74.96,75.0,73.86,74.17,3363964.0,0.0,1.0,74.96,75.0,73.86,74.17,3363964.0
-2017-12-27,74.25,74.93,74.0,74.59,4226467.0,0.0,1.0,74.25,74.93,74.0,74.59,4226467.0
-2017-12-26,73.29,74.34,72.63,74.27,4683371.0,0.0,1.0,73.29,74.34,72.63,74.27,4683371.0
-2017-12-22,73.8,74.04,72.9,73.89,3570969.0,0.0,1.0,73.8,74.04,72.9,73.89,3570969.0
-2017-12-21,74.19,74.47,73.8,74.02,4556474.0,0.0,1.0,74.19,74.47,73.8,74.02,4556474.0
-2017-12-20,74.64,74.9,73.76,74.0,5964055.0,0.0,1.0,74.64,74.9,73.76,74.0,5964055.0
-2017-12-19,75.39,75.39,73.91,74.5,7430435.0,0.0,1.0,75.39,75.39,73.91,74.5,7430435.0
-2017-12-18,76.3,76.35,75.2,75.32,8034166.0,0.0,1.0,76.3,76.35,75.2,75.32,8034166.0
-2017-12-15,74.82,75.87,73.51,75.65,10935788.0,0.0,1.0,74.82,75.87,73.51,75.65,10935788.0
-2017-12-14,74.5,75.53,74.2,74.26,7453419.0,0.0,1.0,74.5,75.53,74.2,74.26,7453419.0
-2017-12-13,74.08,75.42,73.77,74.09,7037486.0,0.0,1.0,74.08,75.42,73.77,74.09,7037486.0
-2017-12-12,73.45,74.31,73.0,73.62,5947690.0,0.0,1.0,73.45,74.31,73.0,73.62,5947690.0
-2017-12-11,72.96,73.68,72.56,73.29,5786918.0,0.0,1.0,72.96,73.68,72.56,73.29,5786918.0
-2017-12-08,74.71,74.71,72.6,72.91,8130594.0,0.0,1.0,74.71,74.71,72.6,72.91,8130594.0
-2017-12-07,73.25,74.069,73.25,73.69,7547591.0,0.0,1.0,73.25,74.069,73.25,73.69,7547591.0
-2017-12-06,70.89,73.2,70.83,73.14,9188317.0,0.0,1.0,70.89,73.2,70.83,73.14,9188317.0
-2017-12-05,69.81,72.75,69.61,71.2,15818651.0,0.0,1.0,69.81,72.75,69.61,71.2,15818651.0
-2017-12-04,75.59,75.7439,68.61,70.97,26157704.0,0.0,1.0,75.59,75.7439,68.61,70.97,26157704.0
-2017-12-01,75.22,76.44,74.26,75.2999,13310272.0,0.0,1.0,75.22,76.44,74.26,75.2999,13310272.0
-2017-11-30,73.77,75.87,73.54,75.73,15737916.0,0.0,1.0,73.77,75.87,73.54,75.73,15737916.0
-2017-11-29,77.95,77.98,71.67,73.25,24981118.0,0.0,1.0,77.95,77.98,71.67,73.25,24981118.0
-2017-11-28,77.95,78.23,77.2435,77.79,8570920.0,0.0,1.0,77.95,78.23,77.2435,77.79,8570920.0
-2017-11-27,78.63,79.385,77.71,77.84,6745449.0,0.0,1.0,78.63,79.385,77.71,77.84,6745449.0
-2017-11-24,77.81,78.9,77.7,78.57,4305618.0,0.0,1.0,77.81,78.9,77.7,78.57,4305618.0
-2017-11-22,77.9,77.99,76.62,77.57,7975445.0,0.0,1.0,77.9,77.99,76.62,77.57,7975445.0
-2017-11-21,77.09,78.43,76.85,77.77,10283504.0,0.0,1.0,77.09,78.43,76.85,77.77,10283504.0
-2017-11-20,76.6,77.32,75.88,76.01,6799610.0,0.0,1.0,76.6,77.32,75.88,76.01,6799610.0
-2017-11-17,78.01,78.01,75.8,76.38,11771514.0,0.0,1.0,78.01,78.01,75.8,76.38,11771514.0
-2017-11-16,75.5,77.94,75.28,77.7,12154083.0,0.0,1.0,75.5,77.94,75.28,77.7,12154083.0
-2017-11-15,74.3,74.4,73.1853,73.43,5780290.0,0.0,1.0,74.3,74.4,73.1853,73.43,5780290.0
-2017-11-14,74.1,74.82,73.62,74.49,5426087.0,0.0,1.0,74.1,74.82,73.62,74.49,5426087.0
-2017-11-13,73.61,74.29,73.34,74.03,5821794.0,0.0,1.0,73.61,74.29,73.34,74.03,5821794.0
-2017-11-10,73.77,74.14,73.56,73.99,5703206.0,0.0,1.0,73.77,74.14,73.56,73.99,5703206.0
-2017-11-09,74.02,74.2,72.41,74.1,8526645.0,0.0,1.0,74.02,74.2,72.41,74.1,8526645.0
-2017-11-07,75.17,75.45,74.19,74.41,6855004.0,0.0,1.0,75.17,75.45,74.19,74.41,6855004.0
-2017-11-06,73.72,74.76,73.42,74.74,10052359.0,0.0,1.0,73.72,74.76,73.42,74.74,10052359.0
-2017-11-03,72.37,73.41,71.94,73.39,6714105.0,0.0,1.0,72.37,73.41,71.94,73.39,6714105.0
-2017-11-02,72.46,72.7755,72.01,72.25,4518557.0,0.0,1.0,72.46,72.7755,72.01,72.25,4518557.0
-2017-11-01,72.78,72.99,71.69,72.38,6576235.0,0.0,1.0,72.78,72.99,71.69,72.38,6576235.0
-2017-10-31,71.34,72.74,71.11,72.56,7478157.0,0.0,1.0,71.34,72.74,71.11,72.56,7478157.0
-2017-10-30,71.45,71.54,70.53,71.15,6911407.0,0.0,1.0,71.45,71.54,70.53,71.15,6911407.0
-2017-10-27,71.72,71.79,70.58,71.06,9192172.0,0.0,1.0,71.72,71.79,70.58,71.06,9192172.0
-2017-10-26,71.46,72.07,71.04,71.34,7967791.0,0.0,1.0,71.46,72.07,71.04,71.34,7967791.0
-2017-10-25,69.94,71.42,69.85,71.02,11908785.0,0.0,1.0,69.94,71.42,69.85,71.02,11908785.0
-2017-10-24,69.73,70.565,69.67,70.21,12057648.0,0.0,1.0,69.73,70.565,69.67,70.21,12057648.0
-2017-10-23,71.02,71.33,69.55,69.8,12004583.0,0.0,1.0,71.02,71.33,69.55,69.8,12004583.0
-2017-10-20,71.33,71.73,69.69,70.97,33976887.0,0.0,1.0,71.33,71.73,69.69,70.97,33976887.0
-2017-10-19,67.3,67.45,66.16,67.25,11645310.0,0.0,1.0,67.3,67.45,66.16,67.25,11645310.0
-2017-10-18,67.4,67.5,67.0,67.26,7866118.0,0.0,1.0,67.4,67.5,67.0,67.26,7866118.0
-2017-10-17,67.65,67.67,66.35,66.67,10630805.0,0.0,1.0,67.65,67.67,66.35,66.67,10630805.0
-2017-10-16,69.04,69.2,67.28,67.31,9449837.0,0.0,1.0,69.04,69.2,67.28,67.31,9449837.0
-2017-10-13,69.49,69.61,68.0,68.66,8596855.0,0.0,1.0,69.49,69.61,68.0,68.66,8596855.0
-2017-10-12,68.02,68.98,67.8048,68.86,8607233.0,0.0,1.0,68.02,68.98,67.8048,68.86,8607233.0
-2017-10-11,67.25,68.42,66.98,67.78,11918941.0,0.0,1.0,67.25,68.42,66.98,67.78,11918941.0
-2017-10-10,66.6,66.67,65.79,66.04,5795772.0,0.0,1.0,66.6,66.67,65.79,66.04,5795772.0
-2017-10-09,66.2,66.55,65.9,66.23,5511409.0,0.0,1.0,66.2,66.55,65.9,66.23,5511409.0
-2017-10-06,66.0,66.41,65.79,66.05,6102894.0,0.0,1.0,66.0,66.41,65.79,66.05,6102894.0
-2017-10-05,64.38,66.0,64.22,65.82,6918222.0,0.0,1.0,64.38,66.0,64.22,65.82,6918222.0
-2017-10-04,64.3,64.3,63.69,64.01,4399565.0,0.0,1.0,64.3,64.3,63.69,64.01,4399565.0
-2017-10-03,64.51,64.51,63.7607,64.22,5614020.0,0.0,1.0,64.51,64.51,63.7607,64.22,5614020.0
-2017-10-02,64.5,65.12,64.1,64.18,5141673.0,0.0,1.0,64.5,65.12,64.1,64.18,5141673.0
-2017-09-29,63.86,64.17,63.5,64.03,6706995.0,0.0,1.0,63.86,64.17,63.5,64.03,6706995.0
-2017-09-28,63.62,64.055,63.11,63.93,3982117.0,0.0,1.0,63.62,64.055,63.11,63.93,3982117.0
-2017-09-27,63.41,63.75,63.1601,63.33,6807674.0,0.0,1.0,63.41,63.75,63.1601,63.33,6807674.0
-2017-09-26,63.71,63.7623,62.84,62.94,8084916.0,0.0,1.0,63.71,63.7623,62.84,62.94,8084916.0
-2017-09-25,65.0,65.0,62.365,63.5,13088161.0,0.0,1.0,65.0,65.0,62.365,63.5,13088161.0
-2017-09-22,64.33,65.24,64.11,65.08,6539011.0,0.0,1.0,64.33,65.24,64.11,65.08,6539011.0
-2017-09-21,64.67,64.95,63.905,64.63,6539750.0,0.0,1.0,64.67,64.95,63.905,64.63,6539750.0
-2017-09-20,63.99,64.87,63.83,64.74,11704012.0,0.0,1.0,63.99,64.87,63.83,64.74,11704012.0
-2017-09-19,63.01,63.925,62.96,63.83,7646245.0,0.0,1.0,63.01,63.925,62.96,63.83,7646245.0
-2017-09-18,62.62,63.5299,62.52,62.92,7561354.0,0.0,1.0,62.62,63.5299,62.52,62.92,7561354.0
-2017-09-15,62.27,62.8,61.96,62.5,9561717.0,0.0,1.0,62.27,62.8,61.96,62.5,9561717.0
-2017-09-14,62.04,62.37,61.71,62.24,5657030.0,0.0,1.0,62.04,62.37,61.71,62.24,5657030.0
-2017-09-13,62.47,62.75,61.58,62.04,6113877.0,0.0,1.0,62.47,62.75,61.58,62.04,6113877.0
-2017-09-12,62.95,63.12,62.15,62.56,6199885.0,0.0,1.0,62.95,63.12,62.15,62.56,6199885.0
-2017-09-11,61.73,63.26,61.62,62.64,8162604.0,0.0,1.0,61.73,63.26,61.62,62.64,8162604.0
-2017-09-08,61.94,62.0,61.1,61.13,4876488.0,0.0,1.0,61.94,62.0,61.1,61.13,4876488.0
-2017-09-07,61.33,62.13,61.28,62.0,4962951.0,0.0,1.0,61.33,62.13,61.28,62.0,4962951.0
-2017-09-06,61.74,61.99,60.9,61.24,5217668.0,0.0,1.0,61.74,61.99,60.9,61.24,5217668.0
-2017-09-05,61.26,61.75,60.58,61.27,5696603.0,0.0,1.0,61.26,61.75,60.58,61.27,5696603.0
-2017-09-01,61.98,62.23,61.3831,61.46,3389772.0,0.0,1.0,61.98,62.23,61.3831,61.46,3389772.0
-2017-08-31,62.0,62.029,61.17,61.68,6088973.0,0.0,1.0,62.0,62.029,61.17,61.68,6088973.0
-2017-08-30,61.05,61.86,60.89,61.77,5613393.0,0.0,1.0,61.05,61.86,60.89,61.77,5613393.0
-2017-08-29,59.82,61.16,59.63,61.01,4330268.0,0.0,1.0,59.82,61.16,59.63,61.01,4330268.0
-2017-08-28,60.31,60.53,59.81,60.53,4616049.0,0.0,1.0,60.31,60.53,59.81,60.53,4616049.0
-2017-08-25,60.33,60.58,59.61,59.97,4006421.0,0.0,1.0,60.33,60.58,59.61,59.97,4006421.0
-2017-08-24,60.22,60.43,59.11,60.0,3787878.0,0.0,1.0,60.22,60.43,59.11,60.0,3787878.0
-2017-08-23,60.3,60.51,59.82,60.04,4511679.0,0.0,1.0,60.3,60.51,59.82,60.04,4511679.0
-2017-08-22,59.72,61.0,59.44,60.84,5782471.0,0.0,1.0,59.72,61.0,59.44,60.84,5782471.0
-2017-08-21,59.33,59.65,58.755,59.4,4206531.0,0.0,1.0,59.33,59.65,58.755,59.4,4206531.0
-2017-08-18,59.36,59.82,58.94,59.44,4594653.0,0.0,1.0,59.36,59.82,58.94,59.44,4594653.0
-2017-08-17,60.15,60.28,59.29,59.29,6537123.0,0.0,1.0,60.15,60.28,59.29,59.29,6537123.0
-2017-08-16,59.95,60.7,59.6,60.29,5679048.0,0.0,1.0,59.95,60.7,59.6,60.29,5679048.0
-2017-08-15,59.3,59.98,59.23,59.69,6419599.0,0.0,1.0,59.3,59.98,59.23,59.69,6419599.0
-2017-08-14,58.61,59.2763,58.271,59.06,7127903.0,0.0,1.0,58.61,59.2763,58.271,59.06,7127903.0
-2017-08-11,57.85,58.25,57.58,58.04,6891359.0,0.0,1.0,57.85,58.25,57.58,58.04,6891359.0
-2017-08-10,59.24,59.37,57.81,58.02,9341375.0,0.0,1.0,59.24,59.37,57.81,58.02,9341375.0
-2017-08-09,58.97,59.73,58.59,59.67,5991127.0,0.0,1.0,58.97,59.73,58.59,59.67,5991127.0
-2017-08-08,59.61,59.88,59.25,59.48,5960460.0,0.0,1.0,59.61,59.88,59.25,59.48,5960460.0
-2017-08-07,59.18,59.64,58.84,59.62,5875028.0,0.0,1.0,59.18,59.64,58.84,59.62,5875028.0
-2017-08-04,58.62,58.93,58.32,58.86,6118655.0,0.0,1.0,58.62,58.93,58.32,58.86,6118655.0
-2017-08-03,59.16,59.28,58.36,58.42,6104372.0,0.0,1.0,59.16,59.28,58.36,58.42,6104372.0
-2017-08-02,59.67,59.71,58.44,59.12,6486312.0,0.0,1.0,59.67,59.71,58.44,59.12,6486312.0
-2017-08-01,59.0,59.39,58.79,59.34,8950112.0,0.0,1.0,59.0,59.39,58.79,59.34,8950112.0
-2017-07-31,59.37,59.64,58.52,58.55,7307044.0,0.0,1.0,59.37,59.64,58.52,58.55,7307044.0
-2017-07-28,59.8,60.71,59.04,59.2,10684806.0,0.0,1.0,59.8,60.71,59.04,59.2,10684806.0
-2017-07-27,61.0,61.3,57.6921,60.15,22678000.0,0.0,1.0,61.0,61.3,57.6921,60.15,22678000.0
-2017-07-26,58.48,58.94,57.9,58.79,12794748.0,0.0,1.0,58.48,58.94,57.9,58.79,12794748.0
-2017-07-25,58.73,58.83,58.19,58.26,7859354.0,0.0,1.0,58.73,58.83,58.19,58.26,7859354.0
-2017-07-24,58.9,59.07,58.34,58.58,6373567.0,0.0,1.0,58.9,59.07,58.34,58.58,6373567.0
-2017-07-21,59.0,59.33,58.59,58.67,7486133.0,0.0,1.0,59.0,59.33,58.59,58.67,7486133.0
-2017-07-20,58.75,59.38,58.43,59.09,7990391.0,0.0,1.0,58.75,59.38,58.43,59.09,7990391.0
-2017-07-19,58.31,58.62,57.55,58.35,9624663.0,0.0,1.0,58.31,58.62,57.55,58.35,9624663.0
-2017-07-18,57.5,58.96,57.31,58.96,9436755.0,0.0,1.0,57.5,58.96,57.31,58.96,9436755.0
-2017-07-17,57.53,57.6,57.02,57.58,5604480.0,0.0,1.0,57.53,57.6,57.02,57.58,5604480.0
-2017-07-14,58.14,58.63,56.915,57.16,11651935.0,0.0,1.0,58.14,58.63,56.915,57.16,11651935.0
-2017-07-13,57.3,57.91,56.8,57.9,14687917.0,0.0,1.0,57.3,57.91,56.8,57.9,14687917.0
-2017-07-12,56.6,57.445,55.55,56.55,17345098.0,0.0,1.0,56.6,57.445,55.55,56.55,17345098.0
-2017-07-11,54.92,55.2,54.33,54.76,8865099.0,0.0,1.0,54.92,55.2,54.33,54.76,8865099.0
-2017-07-10,54.91,55.42,54.7,54.96,9916785.0,0.0,1.0,54.91,55.42,54.7,54.96,9916785.0
-2017-07-07,53.7,54.48,53.52,53.97,4805962.0,0.0,1.0,53.7,54.48,53.52,53.97,4805962.0
-2017-07-06,54.22,54.3506,53.15,53.47,7289275.0,0.0,1.0,54.22,54.3506,53.15,53.47,7289275.0
-2017-07-05,53.0,54.75,52.94,54.61,9638570.0,0.0,1.0,53.0,54.75,52.94,54.61,9638570.0
-2017-07-03,54.14,54.33,52.83,52.87,4831590.0,0.0,1.0,54.14,54.33,52.83,52.87,4831590.0
-2017-06-30,53.6,54.25,53.29,53.67,7611077.0,0.0,1.0,53.6,54.25,53.29,53.67,7611077.0
-2017-06-29,53.81,54.1,52.52,53.42,11162726.0,0.0,1.0,53.81,54.1,52.52,53.42,11162726.0
-2017-06-28,52.75,54.44,52.65,54.39,7894816.0,0.0,1.0,52.75,54.44,52.65,54.39,7894816.0
-2017-06-27,53.6,53.79,52.64,52.73,7680978.0,0.0,1.0,53.6,53.79,52.64,52.73,7680978.0
-2017-06-26,54.44,55.1,53.65,53.74,4728731.0,0.0,1.0,54.44,55.1,53.65,53.74,4728731.0
-2017-06-23,53.82,54.53,53.69,54.34,5954697.0,0.0,1.0,53.82,54.53,53.69,54.34,5954697.0
-2017-06-22,53.71,53.951,52.86,53.87,9631525.0,0.0,1.0,53.71,53.951,52.86,53.87,9631525.0
-2017-06-21,52.99,53.58,52.61,53.54,7992648.0,0.0,1.0,52.99,53.58,52.61,53.54,7992648.0
-2017-06-20,52.84,53.23,52.43,52.52,4522851.0,0.0,1.0,52.84,53.23,52.43,52.52,4522851.0
-2017-06-19,52.28,53.0,52.1101,52.93,5276661.0,0.0,1.0,52.28,53.0,52.1101,52.93,5276661.0
-2017-06-16,52.04,52.16,51.58,51.84,10792581.0,0.0,1.0,52.04,52.16,51.58,51.84,10792581.0
-2017-06-15,51.44,52.38,50.83,52.29,9945649.0,0.0,1.0,51.44,52.38,50.83,52.29,9945649.0
-2017-06-14,52.0,52.505,51.535,51.9,7114891.0,0.0,1.0,52.0,52.505,51.535,51.9,7114891.0
-2017-06-13,52.29,52.485,51.7,52.04,10119801.0,0.0,1.0,52.29,52.485,51.7,52.04,10119801.0
-2017-06-12,52.81,52.9,51.43,52.16,15724406.0,0.0,1.0,52.81,52.9,51.43,52.16,15724406.0
-2017-06-09,54.65,55.14,52.85,53.4,10524856.0,0.0,1.0,54.65,55.14,52.85,53.4,10524856.0
-2017-06-08,54.03,54.43,53.45,54.39,6251592.0,0.0,1.0,54.03,54.43,53.45,54.39,6251592.0
-2017-06-07,53.3,53.94,53.26,53.85,6282623.0,0.0,1.0,53.3,53.94,53.26,53.85,6282623.0
-2017-06-06,53.75,53.8,53.16,53.4,6212080.0,0.0,1.0,53.75,53.8,53.16,53.4,6212080.0
-2017-06-05,53.77,54.07,53.59,53.8,9119908.0,0.0,1.0,53.77,54.07,53.59,53.8,9119908.0
-2017-06-02,53.44,53.64,53.08,53.52,9019731.0,0.0,1.0,53.44,53.64,53.08,53.52,9019731.0
-2017-06-01,52.48,53.39,52.475,53.16,13878328.0,0.0,1.0,52.48,53.39,52.475,53.16,13878328.0
diff --git a/examples/quick/demos/stocqt/content/data/QCOM.csv b/examples/quick/demos/stocqt/content/data/QCOM.csv
deleted file mode 100644
index 0067fe307b..0000000000
--- a/examples/quick/demos/stocqt/content/data/QCOM.csv
+++ /dev/null
@@ -1,147 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,64.36,64.65,64.0,64.02,4553732.0,0.0,1.0,64.36,64.65,64.0,64.02,4553732.0
-2017-12-28,64.69,64.73,64.35,64.38,2371094.0,0.0,1.0,64.69,64.73,64.35,64.38,2371094.0
-2017-12-27,64.32,64.64,64.18,64.54,4821727.0,0.0,1.0,64.32,64.64,64.18,64.54,4821727.0
-2017-12-26,64.49,64.94,64.2,64.3,4185772.0,0.0,1.0,64.49,64.94,64.2,64.3,4185772.0
-2017-12-22,64.31,64.98,64.3,64.73,4386678.0,0.0,1.0,64.31,64.98,64.3,64.73,4386678.0
-2017-12-21,64.75,64.9604,64.34,64.39,5349137.0,0.0,1.0,64.75,64.9604,64.34,64.39,5349137.0
-2017-12-20,64.56,65.17,64.33,64.6,6919901.0,0.0,1.0,64.56,65.17,64.33,64.6,6919901.0
-2017-12-19,65.11,65.48,64.43,64.5,6906151.0,0.0,1.0,65.11,65.48,64.43,64.5,6906151.0
-2017-12-18,64.93,65.46,64.8,65.38,7092422.0,0.0,1.0,64.93,65.46,64.8,65.38,7092422.0
-2017-12-15,65.33,65.42,64.5,64.76,14158271.0,0.0,1.0,65.33,65.42,64.5,64.76,14158271.0
-2017-12-14,64.86,65.17,64.545,64.7,7012732.0,0.0,1.0,64.86,65.17,64.545,64.7,7012732.0
-2017-12-13,64.98,65.425,64.83,64.9,6431073.0,0.0,1.0,64.98,65.425,64.83,64.9,6431073.0
-2017-12-12,64.88,65.11,64.55,64.86,5559918.0,0.0,1.0,64.88,65.11,64.55,64.86,5559918.0
-2017-12-11,64.06,65.2631,64.0,65.18,11846177.0,0.0,1.0,64.06,65.2631,64.0,65.18,11846177.0
-2017-12-08,65.6,65.6,63.88,64.24,9170240.0,0.0,1.0,65.6,65.6,63.88,64.24,9170240.0
-2017-12-07,65.21,65.55,64.77,65.23,6068240.0,0.0,1.0,65.21,65.55,64.77,65.23,6068240.0
-2017-12-06,64.64,65.68,64.36,64.98,6907606.0,0.0,1.0,64.64,65.68,64.36,64.98,6907606.0
-2017-12-05,64.85,65.03,64.4,64.69,9492637.0,0.0,1.0,64.85,65.03,64.4,64.69,9492637.0
-2017-12-04,65.6,65.7,63.8,64.56,17057274.0,0.0,1.0,65.6,65.7,63.8,64.56,17057274.0
-2017-12-01,65.2,66.12,64.6,65.49,15286995.0,0.0,1.0,65.2,66.12,64.6,65.49,15286995.0
-2017-11-30,66.51,67.1,65.72,66.34,14675004.0,0.0,1.0,66.51,67.1,65.72,66.34,14675004.0
-2017-11-29,68.1,68.2,66.03,66.52,16841361.0,0.0,1.0,68.1,68.2,66.03,66.52,16841361.0
-2017-11-28,67.59,68.41,67.22,68.38,12641308.0,0.57,1.0,67.59,68.41,67.22,68.38,12641308.0
-2017-11-27,68.6,68.92,68.04,68.14,20112979.0,0.0,1.0,68.032893401015,68.350248005801,67.47752284264,67.576696156635,20112979.0
-2017-11-24,68.51,69.28,68.45,68.91,9233010.0,0.0,1.0,67.943637418419,68.707271936186,67.884133430022,68.340330674402,9233010.0
-2017-11-22,66.37,68.26,66.24,68.13,15165652.0,0.0,1.0,65.821328498912,67.69570413343,65.692403190718,67.566778825236,15165652.0
-2017-11-21,65.35,66.93,65.27,66.67,11062010.0,0.0,1.0,64.809760696157,66.376699057288,64.73042204496,66.118848440899,11062010.0
-2017-11-20,66.18,66.85,65.95,66.47,9677801.0,0.0,1.0,65.632899202321,66.297360406091,65.404800580131,65.920501812908,9677801.0
-2017-11-17,66.37,66.95,66.0,66.72,12134512.0,0.0,1.0,65.821328498912,66.396533720087,65.454387237128,66.168435097897,12134512.0
-2017-11-16,65.77,66.54,65.43,66.11,12142331.0,0.0,1.0,65.226288614938,65.989923132705,64.889099347353,65.563477882524,12142331.0
-2017-11-15,65.55,66.4838,65.24,65.61,10531408.0,0.0,1.0,65.008107324148,65.934187730239,64.700670050761,65.067611312545,10531408.0
-2017-11-14,66.16,66.8,65.55,66.0,13970519.0,0.0,1.0,65.613064539521,66.247773749094,65.008107324148,65.454387237128,13970519.0
-2017-11-13,64.96,66.82,64.75,66.49,24327595.0,0.0,1.0,64.422984771574,66.267608411893,64.214720812183,65.940336475707,24327595.0
-2017-11-10,64.36,65.1,63.92,64.57,9597929.0,0.0,1.0,63.8279448876,64.561827411168,63.391582306019,64.036208846991,9597929.0
-2017-11-09,64.91,65.33,63.93,64.6,15600914.0,0.0,1.0,64.373398114576,64.789926033358,63.401499637418,64.065960841189,15600914.0
-2017-11-07,62.52,64.16,62.45,64.1,23249338.0,0.0,1.0,62.00315591008,63.629598259608,61.933734590283,63.570094271211,23249338.0
-2017-11-06,64.54,65.33,62.15,62.52,58620899.0,0.0,1.0,64.006456852792,64.789926033358,61.636214648296,62.00315591008,58620899.0
-2017-11-03,54.76,64.99,54.21,61.81,78515925.0,0.0,1.0,54.307306744017,64.452736765772,53.761853517041,61.299025380711,78515925.0
-2017-11-02,53.6,55.68,53.6,54.84,17115009.0,0.0,1.0,53.156896301668,55.219701232777,53.156896301668,54.386645395214,17115009.0
-2017-11-01,51.47,53.49,50.51,53.46,14923803.0,0.0,1.0,51.044504713561,53.047805656273,50.092440899202,53.018053662074,14923803.0
-2017-10-31,52.26,52.49,50.02,51.01,28432806.0,0.0,1.0,51.827973894126,52.056072516316,49.606491660624,50.588307469181,28432806.0
-2017-10-30,54.16,54.77,54.08,54.66,6986348.0,0.0,1.0,53.712266860044,54.317224075417,53.632928208847,54.208133430022,6986348.0
-2017-10-27,53.7,54.7,53.36,54.57,8637328.0,0.0,1.0,53.256069615664,54.24780275562,52.918880348078,54.118877447426,8637328.0
-2017-10-26,54.1,54.39,53.665,53.8,5227877.0,0.0,1.0,53.652762871646,53.940365482234,53.221358955765,53.355242929659,5227877.0
-2017-10-25,53.98,54.43,53.475,53.84,7352176.0,0.0,1.0,53.533754894851,53.980034807832,53.032929659173,53.394912255257,7352176.0
-2017-10-24,53.44,54.44,53.4,54.25,10450810.0,0.0,1.0,52.998218999275,53.989952139231,52.958549673677,53.80152284264,10450810.0
-2017-10-23,52.3,53.78,52.13,53.39,9698032.0,0.0,1.0,51.867643219724,53.33540826686,51.699048585932,52.948632342277,9698032.0
-2017-10-20,52.51,52.59,51.94,52.02,8405771.0,0.0,1.0,52.075907179115,52.155245830312,51.51061928934,51.589957940537,8405771.0
-2017-10-19,52.03,52.4,52.01,52.29,6657536.0,0.0,1.0,51.599875271936,51.96681653372,51.580040609137,51.857725888325,6657536.0
-2017-10-18,52.54,52.67,52.02,52.21,5928735.0,0.0,1.0,52.105659173314,52.234584481508,51.589957940537,51.778387237128,5928735.0
-2017-10-17,52.32,52.44,51.8501,52.41,7456659.0,0.0,1.0,51.887477882524,52.006485859318,51.421462480058,51.97673386512,7456659.0
-2017-10-16,52.98,53.0,52.3101,52.38,5749880.0,0.0,1.0,52.542021754895,52.561856417694,51.877659724438,51.946981870921,5749880.0
-2017-10-13,53.38,53.38,52.74,52.82,6293816.0,0.0,1.0,52.938715010877,52.938715010877,52.304005801305,52.383344452502,6293816.0
-2017-10-12,53.88,54.175,52.96,53.0,7000530.0,0.0,1.0,53.434581580856,53.727142857143,52.522187092096,52.561856417694,7000530.0
-2017-10-11,53.79,54.38,53.66,54.12,8679167.0,0.0,1.0,53.34532559826,53.930448150834,53.216400290065,53.672597534445,8679167.0
-2017-10-10,52.95,53.9,52.9,53.87,8701455.0,0.0,1.0,52.512269760696,53.454416243655,52.462683103698,53.424664249456,8701455.0
-2017-10-09,52.68,52.9799,52.38,52.88,5803730.0,0.0,1.0,52.244501812908,52.541922581581,51.946981870921,52.442848440899,5803730.0
-2017-10-06,52.16,52.63,52.16,52.49,4780961.0,0.0,1.0,51.728800580131,52.19491515591,51.728800580131,52.056072516316,4780961.0
-2017-10-05,52.17,52.43,51.96,52.35,5144244.0,0.0,1.0,51.73871791153,51.996568527919,51.530453952139,51.917229876722,5144244.0
-2017-10-04,51.93,52.12,51.67,51.96,4521452.0,0.0,1.0,51.500701957941,51.689131254532,51.242851341552,51.530453952139,4521452.0
-2017-10-03,51.99,52.22,51.65,52.02,4176210.0,0.0,1.0,51.560205946338,51.788304568528,51.223016678753,51.589957940537,4176210.0
-2017-10-02,52.09,52.16,51.7,51.88,4363679.0,0.0,1.0,51.659379260334,51.728800580131,51.272603335751,51.451115300943,4363679.0
-2017-09-29,51.91,52.0447,51.62,51.84,5159612.0,0.0,1.0,51.480867295141,51.614453749094,51.193264684554,51.411445975344,5159612.0
-2017-09-28,51.38,52.04,51.31,51.75,5671994.0,0.0,1.0,50.955248730964,51.609792603336,50.885827411168,51.322189992748,5671994.0
-2017-09-27,51.43,51.61,51.1526,51.55,8122353.0,0.0,1.0,51.004835387962,51.183347353154,50.729728614938,51.123843364757,8122353.0
-2017-09-26,51.75,51.87,50.85,51.13,9148913.0,0.0,1.0,51.322189992748,51.441197969543,50.429630166788,50.707315445975,9148913.0
-2017-09-25,51.9,52.285,51.61,51.63,7931316.0,0.0,1.0,51.470949963742,51.852767222625,51.183347353154,51.203182015954,7931316.0
-2017-09-22,51.82,52.23,51.78,52.09,4077699.0,0.0,1.0,51.391611312545,51.798221899927,51.351941986947,51.659379260334,4077699.0
-2017-09-21,51.86,52.2,51.71,52.03,5192113.0,0.0,1.0,51.431280638144,51.768469905729,51.28252066715,51.599875271936,5192113.0
-2017-09-20,52.43,52.52,51.48,51.98,8273935.0,0.0,1.0,51.996568527919,52.085824510515,51.05442204496,51.550288614938,8273935.0
-2017-09-19,52.4,52.5,52.06,52.3,4897549.0,0.0,1.0,51.96681653372,52.065989847716,51.629627266135,51.867643219724,4897549.0
-2017-09-18,52.24,52.37,51.955,52.25,5951635.0,0.0,1.0,51.808139231327,51.937064539521,51.525495286439,51.818056562727,5951635.0
-2017-09-15,51.95,52.29,51.44,52.19,12717688.0,0.0,1.0,51.52053662074,51.857725888325,51.014752719362,51.758552574329,12717688.0
-2017-09-14,50.97,51.59,50.67,51.48,7677860.0,0.0,1.0,50.548638143582,51.163512690355,50.251118201595,51.05442204496,7677860.0
-2017-09-13,50.8,51.1054,50.72,51.01,6147412.0,0.0,1.0,50.38004350979,50.682918810732,50.300704858593,50.588307469181,6147412.0
-2017-09-12,50.6,51.07,50.52,50.9,4444021.0,0.0,1.0,50.181696881798,50.647811457578,50.102358230602,50.479216823785,4444021.0
-2017-09-11,49.94,50.67,49.91,50.57,7137370.0,0.0,1.0,49.527153009427,50.251118201595,49.497401015228,50.1519448876,7137370.0
-2017-09-08,50.35,50.45,48.92,49.64,12445202.0,0.0,1.0,49.933763596809,50.032936910805,48.515585206672,49.22963306744,12445202.0
-2017-09-07,50.56,50.69,50.25,50.38,8214389.0,0.0,1.0,50.1420275562,50.270952864394,49.834590282814,49.963515591008,8214389.0
-2017-09-06,50.19,50.77,49.83,50.45,16009190.0,0.0,1.0,49.775086294416,50.350291515591,49.418062364032,50.032936910805,16009190.0
-2017-09-05,51.86,51.9,49.83,50.03,17850640.0,0.0,1.0,51.431280638144,51.470949963742,49.418062364032,49.616408992023,17850640.0
-2017-09-01,52.53,52.77,51.925,52.05,5250026.0,0.0,1.0,52.095741841914,52.333757795504,51.495743292241,51.619709934735,5250026.0
-2017-08-31,52.26,52.59,52.12,52.27,7907278.0,0.0,1.0,51.827973894126,52.155245830312,51.689131254532,51.837891225526,7907278.0
-2017-08-30,51.75,52.286,51.56,52.12,4806103.0,0.0,1.0,51.322189992748,51.853758955765,51.133760696157,51.689131254532,4806103.0
-2017-08-29,51.31,51.86,51.28,51.81,4896218.0,0.0,1.0,50.885827411168,51.431280638144,50.856075416969,51.381693981146,4896218.0
-2017-08-28,51.77,51.81,51.46,51.81,4441742.0,0.57,1.0,51.342024655548,51.381693981146,51.034587382161,51.381693981146,4441742.0
-2017-08-25,52.78,52.8545,52.02,52.03,8502179.0,0.0,1.0,51.774070414755,51.847150525515,51.028555190897,51.038364601738,8502179.0
-2017-08-24,52.37,52.71,52.26,52.49,5972821.0,0.0,1.0,51.371884570306,51.705404538873,51.263981051063,51.489597500388,5972821.0
-2017-08-23,52.3,52.405,51.78,52.23,5046782.0,0.0,1.0,51.303218694424,51.406217508246,50.793129330732,51.234552818542,5046782.0
-2017-08-22,52.21,52.62,52.21,52.35,4350136.0,0.0,1.0,51.214933996862,51.617119841311,51.214933996862,51.352265748625,4350136.0
-2017-08-21,52.0,52.08,51.5,51.98,5185851.0,0.0,1.0,51.008936369217,51.087411655939,50.518465827205,50.989317547536,5185851.0
-2017-08-18,52.26,52.415,51.9,51.92,6642109.0,0.0,1.0,51.263981051063,51.416026919087,50.910842260815,50.930461082495,6642109.0
-2017-08-17,53.19,53.41,52.27,52.27,6087867.0,0.0,1.0,52.176256259205,52.39206329769,51.273790461903,51.273790461903,6087867.0
-2017-08-16,54.06,54.1,53.255,53.31,7034292.0,0.0,1.0,53.029675002305,53.068912645666,52.240017429666,52.293969189288,7034292.0
-2017-08-15,53.66,54.08,53.35,53.87,7562385.0,0.0,1.0,52.637298568696,53.049293823986,52.333206832648,52.843296196341,7562385.0
-2017-08-14,53.04,53.64,52.91,53.55,7558235.0,0.0,1.0,52.029115096601,52.617679747015,51.901592755678,52.529395049453,7558235.0
-2017-08-11,52.39,53.13,52.29,52.72,5835863.0,0.0,1.0,51.391503391986,52.117399794163,51.293409283584,51.715213949714,5835863.0
-2017-08-10,52.54,52.75,52.11,52.34,9578948.0,0.0,1.0,51.53864455459,51.744642182234,51.116839888459,51.342456337785,9578948.0
-2017-08-09,52.05,52.8,52.0,52.77,7039352.0,0.0,1.0,51.057983423418,51.793689236436,51.008936369217,51.764261003915,7039352.0
-2017-08-08,52.55,53.33,52.21,52.29,8779415.0,0.0,1.0,51.54845396543,52.313588010968,51.214933996862,51.293409283584,8779415.0
-2017-08-04,53.0,53.0,52.51,52.62,8645879.0,0.0,1.0,51.98987745324,51.98987745324,51.509216322069,51.617119841311,8645879.0
-2017-08-03,53.16,53.3399,52.75,52.95,8481098.0,0.0,1.0,52.146828026684,52.3232993277,51.744642182234,51.940830399039,8481098.0
-2017-08-02,53.295,53.3885,52.78,53.17,19324507.0,0.0,1.0,52.279255073027,52.370973064383,51.774070414755,52.156637437524,19324507.0
-2017-08-01,53.3,53.43,52.91,53.41,7480549.0,0.0,1.0,52.284159778447,52.41168211937,51.901592755678,52.39206329769,7480549.0
-2017-07-31,53.1,53.295,52.75,53.19,10641489.0,0.0,1.0,52.087971561643,52.279255073027,51.744642182234,52.176256259205,10641489.0
-2017-07-28,52.27,52.9865,52.27,52.88,6534345.0,0.0,1.0,51.273790461903,51.976634748606,51.273790461903,51.872164523157,6534345.0
-2017-07-27,53.08,53.37,52.23,52.49,13964311.0,0.0,1.0,52.068352739962,52.352825654329,51.234552818542,51.489597500388,13964311.0
-2017-07-26,53.29,53.35,52.74,53.14,7492633.0,0.0,1.0,52.274350367607,52.333206832648,51.734832771394,52.127209205004,7492633.0
-2017-07-25,53.2,53.65,53.07,53.27,7060158.0,0.0,1.0,52.186065670045,52.627489157855,52.058543329122,52.254731545927,7060158.0
-2017-07-24,53.75,53.88,53.09,53.22,8739769.0,0.0,1.0,52.725583266258,52.853105607181,52.078162150802,52.205684491725,8739769.0
-2017-07-21,53.66,54.0,53.37,53.84,11963407.0,0.0,1.0,52.637298568696,52.970818537264,52.352825654329,52.81386796382,11963407.0
-2017-07-20,55.11,55.43,53.46,53.97,35647961.0,0.0,1.0,54.05966314053,54.373564287417,52.441110351891,52.941390304743,35647961.0
-2017-07-19,56.46,56.9399,56.01,56.78,7437353.0,0.0,1.0,55.383933603961,55.854687230184,54.942510116151,55.697834750849,7437353.0
-2017-07-18,56.34,56.38,56.0,56.29,7329551.0,0.0,1.0,55.266220673878,55.305458317239,54.93270070531,55.217173619677,7329551.0
-2017-07-17,56.73,56.92,56.39,56.45,5067322.0,0.0,1.0,55.648787696648,55.835166502612,55.31526772808,55.374124193121,5067322.0
-2017-07-14,56.5,56.93,56.15,56.81,4365609.0,0.0,1.0,55.423171247322,55.844975913452,55.079841867914,55.727262983369,4365609.0
-2017-07-13,56.38,56.52,56.17,56.23,5884064.0,0.0,1.0,55.305458317239,55.442790069003,55.099460689594,55.158317154636,5884064.0
-2017-07-12,55.79,56.31,55.72,56.2,6082481.0,0.0,1.0,54.726703077666,55.236792441358,54.658037201784,55.128888922115,6082481.0
-2017-07-11,55.63,55.63,55.02,55.33,6009448.0,0.0,1.0,54.569752504222,54.569752504222,53.971378442968,54.275470179015,6009448.0
-2017-07-10,55.37,55.885,55.19,55.64,4973557.0,0.0,1.0,54.314707822376,54.819892480648,54.138138427252,54.579561915062,4973557.0
-2017-07-07,55.04,55.73,54.87,55.35,5156330.0,0.0,1.0,53.990997264648,54.667846612624,53.824237280364,54.295089000695,5156330.0
-2017-07-06,55.02,55.23,54.735,54.79,5557013.0,0.0,1.0,53.971378442968,54.177376070612,53.691810234021,53.745761993642,5557013.0
-2017-07-05,55.01,55.56,54.78,55.45,6624023.0,0.0,1.0,53.961569032127,54.50108662834,53.735952582802,54.393183109098,6624023.0
-2017-07-03,55.53,56.02,54.92,54.95,4379566.0,0.0,1.0,54.471658395819,54.952319526991,53.873284334565,53.902712567086,4379566.0
-2017-06-30,55.6,55.63,55.03,55.22,8596198.0,0.0,1.0,54.540324271701,54.569752504222,53.981187853808,54.167566659772,8596198.0
-2017-06-29,55.93,55.93,54.55,55.08,8333137.0,0.0,1.0,54.864034829429,54.864034829429,53.510336133477,54.030234908009,8333137.0
-2017-06-28,55.4,56.32,55.18,56.16,7231216.0,0.0,1.0,54.344136054896,55.246601852198,54.128329016411,55.089651278754,7231216.0
-2017-06-27,56.29,56.33,55.41,55.43,6734074.0,0.0,1.0,55.217173619677,55.256411263038,54.353945465737,54.373564287417,6734074.0
-2017-06-26,57.09,57.6892,56.21,56.56,7255489.0,0.0,1.0,56.001926486896,56.589706384443,55.138698332955,55.482027712364,7255489.0
-2017-06-23,56.64,57.4365,56.57,56.91,8660612.0,0.0,1.0,55.560502999085,56.34182257251,55.491837123204,55.825357091772,8660612.0
-2017-06-22,56.24,56.745,56.06,56.47,5512097.0,0.0,1.0,55.168126565476,55.663501812908,54.991557170352,55.393743014801,5512097.0
-2017-06-21,56.79,56.84,56.12,56.33,8189893.0,0.0,1.0,55.707644161689,55.75669121589,55.050413635393,55.256411263038,8189893.0
-2017-06-20,57.46,57.61,56.51,56.79,8087133.0,0.0,1.0,56.364874687985,56.512015850588,55.432980658162,55.707644161689,8087133.0
-2017-06-19,56.96,57.66,56.91,57.61,6909034.0,0.0,1.0,55.874404145973,56.561062904789,55.825357091772,56.512015850588,6909034.0
-2017-06-16,56.98,57.01,56.35,56.82,13536039.0,0.0,1.0,55.894022967653,55.923451200174,55.276030084719,55.73707239421,13536039.0
-2017-06-15,56.42,57.17,56.4,56.93,5371464.0,0.0,1.0,55.3446959606,56.080401773618,55.32507713892,55.844975913452,5371464.0
-2017-06-14,57.7,57.97,56.67,57.01,6702810.0,0.0,1.0,56.60030054815,56.865154640837,55.589931231606,55.923451200174,6702810.0
-2017-06-13,57.95,58.065,57.5,57.54,6971106.0,0.0,1.0,56.845535819156,56.958344043819,56.404112331346,56.443349974707,6971106.0
-2017-06-12,56.52,57.675,56.48,57.49,9871291.0,0.0,1.0,55.442790069003,56.57577702105,55.403552425642,56.394302920505,9871291.0
-2017-06-09,58.37,58.49,56.74,57.05,13572264.0,0.0,1.0,57.257531074446,57.375244004529,55.658597107488,55.962688843535,13572264.0
-2017-06-08,57.77,58.15,57.61,58.12,10134415.0,0.0,1.0,56.668966424032,57.041724035961,56.512015850588,57.01229580344,10134415.0
-2017-06-07,58.3,58.49,57.13,57.53,9967746.0,0.0,1.0,57.188865198564,57.375244004529,56.041164130257,56.433540563866,9967746.0
-2017-06-06,58.6,58.91,58.18,58.2,7808482.0,0.0,1.0,57.483147523771,57.787239259819,57.071152268481,57.090771090162,7808482.0
-2017-06-05,58.5,59.05,58.48,58.85,7655063.0,0.0,1.0,57.385053415369,57.924571011582,57.365434593689,57.728382794777,7655063.0
-2017-06-02,58.89,58.96,58.35,58.58,9461824.0,0.0,1.0,57.767620438138,57.83628631402,57.237912252765,57.463528702091,9461824.0
-2017-06-01,57.45,58.65,57.35,58.62,11116224.0,0.0,1.0,56.355065277144,57.532194577972,56.256971168742,57.502766345452,11116224.0
diff --git a/examples/quick/demos/stocqt/content/data/TSLA.csv b/examples/quick/demos/stocqt/content/data/TSLA.csv
deleted file mode 100644
index c1343441d8..0000000000
--- a/examples/quick/demos/stocqt/content/data/TSLA.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,316.18,316.41,310.0,311.35,3727621.0,0.0,1.0,316.18,316.41,310.0,311.35,3727621.0
-2017-12-28,311.75,315.82,309.54,315.36,4294689.0,0.0,1.0,311.75,315.82,309.54,315.36,4294689.0
-2017-12-27,316.0,317.68,310.75,311.64,4645441.0,0.0,1.0,316.0,317.68,310.75,311.64,4645441.0
-2017-12-26,323.83,323.94,316.58,317.29,4321909.0,0.0,1.0,323.83,323.94,316.58,317.29,4321909.0
-2017-12-22,329.51,330.9214,324.82,325.2,4186131.0,0.0,1.0,329.51,330.9214,324.82,325.2,4186131.0
-2017-12-21,329.59,333.74,327.21,331.66,4344701.0,0.0,1.0,329.59,333.74,327.21,331.66,4344701.0
-2017-12-20,332.69,333.1,325.04,328.98,5937684.0,0.0,1.0,332.69,333.1,325.04,328.98,5937684.0
-2017-12-19,340.26,341.4925,330.3,331.1,6792009.0,0.0,1.0,340.26,341.4925,330.3,331.1,6792009.0
-2017-12-18,344.9,346.73,337.58,338.87,5441450.0,0.0,1.0,344.9,346.73,337.58,338.87,5441450.0
-2017-12-15,342.04,343.9,335.76,343.45,6832071.0,0.0,1.0,342.04,343.9,335.76,343.45,6832071.0
-2017-12-14,341.01,347.44,336.9,337.89,5744750.0,0.0,1.0,341.01,347.44,336.9,337.89,5744750.0
-2017-12-13,340.93,344.22,336.5,339.03,6189204.0,0.0,1.0,340.93,344.22,336.5,339.03,6189204.0
-2017-12-12,330.45,341.44,330.03,341.03,8648534.0,0.0,1.0,330.45,341.44,330.03,341.03,8648534.0
-2017-12-11,314.63,329.01,313.75,328.91,7867288.0,0.0,1.0,314.63,329.01,313.75,328.91,7867288.0
-2017-12-08,314.6,316.98,311.26,315.13,3442898.0,0.0,1.0,314.6,316.98,311.26,315.13,3442898.0
-2017-12-07,312.0,318.6341,311.05,311.24,4705140.0,0.0,1.0,312.0,318.6341,311.05,311.24,4705140.0
-2017-12-06,300.1,313.39,300.0,313.26,7160938.0,0.0,1.0,300.1,313.39,300.0,313.26,7160938.0
-2017-12-05,302.0,308.0,301.0,303.7,4628462.0,0.0,1.0,302.0,308.0,301.0,303.7,4628462.0
-2017-12-04,306.5,308.265,300.61,305.2,5811205.0,0.0,1.0,306.5,308.265,300.61,305.2,5811205.0
-2017-12-01,305.44,310.32,305.05,306.53,4256030.0,0.0,1.0,305.44,310.32,305.05,306.53,4256030.0
-2017-11-30,308.56,310.7,304.54,308.85,4288221.0,0.0,1.0,308.56,310.7,304.54,308.85,4288221.0
-2017-11-29,317.3,318.0,301.23,307.54,8732941.0,0.0,1.0,317.3,318.0,301.23,307.54,8732941.0
-2017-11-28,316.36,320.0,313.92,317.55,4916555.0,0.0,1.0,316.36,320.0,313.92,317.55,4916555.0
-2017-11-27,313.25,317.34,309.51,316.81,4524921.0,0.0,1.0,313.25,317.34,309.51,316.81,4524921.0
-2017-11-24,313.79,316.41,311.0,315.55,3242220.0,0.0,1.0,313.79,316.41,311.0,315.55,3242220.0
-2017-11-22,316.77,317.42,311.84,312.6,4890091.0,0.0,1.0,316.77,317.42,311.84,312.6,4890091.0
-2017-11-21,310.86,318.23,308.71,317.81,7230570.0,0.0,1.0,310.86,318.23,308.71,317.81,7230570.0
-2017-11-20,313.79,315.5,304.75,308.74,8220759.0,0.0,1.0,313.79,315.5,304.75,308.74,8220759.0
-2017-11-17,325.67,326.67,313.15,315.05,13682753.0,0.0,1.0,325.67,326.67,313.15,315.05,13682753.0
-2017-11-16,313.99,318.14,311.3,312.5,5757709.0,0.0,1.0,313.99,318.14,311.3,312.5,5757709.0
-2017-11-15,306.01,312.49,301.5,311.3,5909055.0,0.0,1.0,306.01,312.49,301.5,311.3,5909055.0
-2017-11-14,315.0,316.35,306.9,308.7,5641615.0,0.0,1.0,315.0,316.35,306.9,308.7,5641615.0
-2017-11-13,300.13,316.8,299.11,315.4,7536669.0,0.0,1.0,300.13,316.8,299.11,315.4,7536669.0
-2017-11-10,302.5,308.36,301.85,302.99,4600097.0,0.0,1.0,302.5,308.36,301.85,302.99,4600097.0
-2017-11-09,302.5,304.46,296.3,302.99,5419497.0,0.0,1.0,302.5,304.46,296.3,302.99,5419497.0
-2017-11-07,301.02,306.5,300.03,306.05,5209573.0,0.0,1.0,301.02,306.5,300.03,306.05,5209573.0
-2017-11-06,307.0,307.5,299.01,302.78,6463227.0,0.0,1.0,307.0,307.5,299.01,302.78,6463227.0
-2017-11-03,299.5,306.25,295.13,306.09,8835157.0,0.0,1.0,299.5,306.25,295.13,306.09,8835157.0
-2017-11-02,300.13,308.69,292.63,299.26,19731322.0,0.0,1.0,300.13,308.69,292.63,299.26,19731322.0
-2017-11-01,332.25,332.6089,320.26,321.08,7028856.0,0.0,1.0,332.25,332.6089,320.26,321.08,7028856.0
-2017-10-31,320.23,331.95,320.18,331.53,5532647.0,0.0,1.0,320.23,331.95,320.18,331.53,5532647.0
-2017-10-30,319.18,323.78,317.25,320.08,4236029.0,0.0,1.0,319.18,323.78,317.25,320.08,4236029.0
-2017-10-27,319.75,324.59,316.66,320.87,6942493.0,0.0,1.0,319.75,324.59,316.66,320.87,6942493.0
-2017-10-26,327.78,330.23,323.2,326.17,4980316.0,0.0,1.0,327.78,330.23,323.2,326.17,4980316.0
-2017-10-25,336.7,337.5,323.56,325.84,8547764.0,0.0,1.0,336.7,337.5,323.56,325.84,8547764.0
-2017-10-24,338.8,342.8,336.16,337.34,4463807.0,0.0,1.0,338.8,342.8,336.16,337.34,4463807.0
-2017-10-23,349.88,349.95,336.25,337.02,5715817.0,0.0,1.0,349.88,349.95,336.25,337.02,5715817.0
-2017-10-20,352.69,354.55,344.34,345.1,4888221.0,0.0,1.0,352.69,354.55,344.34,345.1,4888221.0
-2017-10-19,355.56,357.1465,348.2,351.81,5032884.0,0.0,1.0,355.56,357.1465,348.2,351.81,5032884.0
-2017-10-18,355.97,363.0,354.13,359.65,4898808.0,0.0,1.0,355.97,363.0,354.13,359.65,4898808.0
-2017-10-17,350.91,356.22,350.07,355.75,3280670.0,0.0,1.0,350.91,356.22,350.07,355.75,3280670.0
-2017-10-16,353.76,354.48,347.16,350.6,5353262.0,0.0,1.0,353.76,354.48,347.16,350.6,5353262.0
-2017-10-13,356.98,358.49,353.68,355.57,3528413.0,0.0,1.0,356.98,358.49,353.68,355.57,3528413.0
-2017-10-12,352.95,359.78,352.64,355.68,4047318.0,0.0,1.0,352.95,359.78,352.64,355.68,4047318.0
-2017-10-11,353.89,357.6,351.15,354.6,4476769.0,0.0,1.0,353.89,357.6,351.15,354.6,4476769.0
-2017-10-10,346.8,355.63,345.5305,355.59,6914972.0,0.0,1.0,346.8,355.63,345.5305,355.59,6914972.0
-2017-10-09,349.65,351.75,342.67,342.94,7406324.0,0.0,1.0,349.65,351.75,342.67,342.94,7406324.0
-2017-10-06,353.1,360.0992,352.25,356.88,4171789.0,0.0,1.0,353.1,360.0992,352.25,356.88,4171789.0
-2017-10-05,356.0,357.435,351.35,355.33,4102286.0,0.0,1.0,356.0,357.435,351.35,355.33,4102286.0
-2017-10-04,351.25,358.62,349.6,355.01,8120353.0,0.0,1.0,351.25,358.62,349.6,355.01,8120353.0
-2017-10-03,335.9,348.55,331.28,348.14,9981885.0,0.0,1.0,335.9,348.55,331.28,348.14,9981885.0
-2017-10-02,342.52,343.7,335.51,341.53,4901453.0,0.0,1.0,342.52,343.7,335.51,341.53,4901453.0
-2017-09-29,341.86,344.68,338.601,341.1,5062297.0,0.0,1.0,341.86,344.68,338.601,341.1,5062297.0
-2017-09-28,339.88,342.75,335.4,339.6,5279310.0,0.0,1.0,339.88,342.75,335.4,339.6,5279310.0
-2017-09-27,349.9,351.489,340.5,340.97,6010631.0,0.0,1.0,349.9,351.489,340.5,340.97,6010631.0
-2017-09-26,350.93,351.24,340.9,345.25,7126550.0,0.0,1.0,350.93,351.24,340.9,345.25,7126550.0
-2017-09-25,353.15,357.469,342.88,344.99,7542161.0,0.0,1.0,353.15,357.469,342.88,344.99,7542161.0
-2017-09-22,366.49,369.8999,350.88,351.09,8105653.0,0.0,1.0,366.49,369.8999,350.88,351.09,8105653.0
-2017-09-21,374.9,376.83,364.51,366.48,4605428.0,0.0,1.0,374.9,376.83,364.51,366.48,4605428.0
-2017-09-20,373.0,378.249,371.07,373.91,4892872.0,0.0,1.0,373.0,378.249,371.07,373.91,4892872.0
-2017-09-19,380.0,382.39,373.57,375.1,6256035.0,0.0,1.0,380.0,382.39,373.57,375.1,6256035.0
-2017-09-18,380.25,389.61,377.68,385.0,7149295.0,0.0,1.0,380.25,389.61,377.68,385.0,7149295.0
-2017-09-15,374.51,380.0,372.7,379.81,5338678.0,0.0,1.0,374.51,380.0,372.7,379.81,5338678.0
-2017-09-14,364.33,377.96,362.63,377.64,7141663.0,0.0,1.0,364.33,377.96,362.63,377.64,7141663.0
-2017-09-13,363.82,368.07,359.59,366.23,4161382.0,0.0,1.0,363.82,368.07,359.59,366.23,4161382.0
-2017-09-12,364.49,368.76,360.4,362.75,5929289.0,0.0,1.0,364.49,368.76,360.4,362.75,5929289.0
-2017-09-11,351.35,363.71,350.0,363.69,7610309.0,0.0,1.0,351.35,363.71,350.0,363.69,7610309.0
-2017-09-08,348.99,349.78,342.3,343.4,3248803.0,0.0,1.0,348.99,349.78,342.3,343.4,3248803.0
-2017-09-07,345.98,352.48,343.45,350.61,4219997.0,0.0,1.0,345.98,352.48,343.45,350.61,4219997.0
-2017-09-06,349.5,350.979,341.56,344.53,4058983.0,0.0,1.0,349.5,350.979,341.56,344.53,4058983.0
-2017-09-05,353.8,355.49,345.89,349.59,3813862.0,0.0,1.0,353.8,355.49,345.89,349.59,3813862.0
-2017-09-01,356.12,357.59,353.6902,355.4,3028578.0,0.0,1.0,356.12,357.59,353.6902,355.4,3028578.0
-2017-08-31,353.55,358.44,352.82,355.9,4019065.0,0.0,1.0,353.55,358.44,352.82,355.9,4019065.0
-2017-08-30,349.67,353.47,347.0,353.18,3390055.0,0.0,1.0,349.67,353.47,347.0,353.18,3390055.0
-2017-08-29,339.48,349.05,338.75,347.36,4032825.0,0.0,1.0,339.48,349.05,338.75,347.36,4032825.0
-2017-08-28,347.28,347.35,339.72,345.66,3718108.0,0.0,1.0,347.28,347.35,339.72,345.66,3718108.0
-2017-08-25,354.24,355.69,347.3,348.05,3461744.0,0.0,1.0,354.24,355.69,347.3,348.05,3461744.0
-2017-08-24,352.52,356.66,349.74,352.93,4540652.0,0.0,1.0,352.52,356.66,349.74,352.93,4540652.0
-2017-08-23,338.99,353.49,338.3041,352.77,4914201.0,0.0,1.0,338.99,353.49,338.3041,352.77,4914201.0
-2017-08-22,341.13,342.24,337.3725,341.35,4288367.0,0.0,1.0,341.13,342.24,337.3725,341.35,4288367.0
-2017-08-21,345.82,345.82,331.85,337.86,6458812.0,0.0,1.0,345.82,345.82,331.85,337.86,6458812.0
-2017-08-18,352.91,354.0,345.8,347.46,5335793.0,0.0,1.0,352.91,354.0,345.8,347.46,5335793.0
-2017-08-17,361.21,363.3,351.59,351.92,4969222.0,0.0,1.0,361.21,363.3,351.59,351.92,4969222.0
-2017-08-16,363.0,366.5,362.52,362.91,3328576.0,0.0,1.0,363.0,366.5,362.52,362.91,3328576.0
-2017-08-15,365.2,365.49,359.37,362.33,3048074.0,0.0,1.0,365.2,365.49,359.37,362.33,3048074.0
-2017-08-14,364.63,367.66,362.6,363.8,4461215.0,0.0,1.0,364.63,367.66,362.6,363.8,4461215.0
-2017-08-11,356.97,361.26,353.62,357.715,4318835.0,0.0,1.0,356.97,361.26,353.62,357.715,4318835.0
-2017-08-10,361.6,366.6504,354.66,355.13,7035192.0,0.0,1.0,361.6,366.6504,354.66,355.13,7035192.0
-2017-08-09,361.0,370.0,358.95,363.525,6847245.0,0.0,1.0,361.0,370.0,358.95,363.525,6847245.0
-2017-08-08,357.53,368.58,357.4,365.22,7363033.0,0.0,1.0,357.53,368.58,357.4,365.22,7363033.0
-2017-08-07,357.35,359.48,352.75,355.17,6265570.0,0.0,1.0,357.35,359.48,352.75,355.17,6265570.0
-2017-08-04,347.0,357.27,343.3,356.91,9151520.0,0.0,1.0,347.0,357.27,343.3,356.91,9151520.0
-2017-08-03,345.33,350.0,343.15,347.09,13448583.0,0.0,1.0,345.33,350.0,343.15,347.09,13448583.0
-2017-08-02,318.94,327.12,311.22,325.89,9911432.0,0.0,1.0,318.94,327.12,311.22,325.89,9911432.0
-2017-08-01,323.0,324.45,316.13,319.57,8247544.0,0.0,1.0,323.0,324.45,316.13,319.57,8247544.0
-2017-07-31,335.5,341.49,321.04,323.47,8499335.0,0.0,1.0,335.5,341.49,321.04,323.47,8499335.0
-2017-07-28,336.89,339.6,332.51,335.07,4841257.0,0.0,1.0,336.89,339.6,332.51,335.07,4841257.0
-2017-07-27,346.0,347.5,326.29,334.46,8259202.0,0.0,1.0,346.0,347.5,326.29,334.46,8259202.0
-2017-07-26,340.36,345.5,338.12,343.85,4750198.0,0.0,1.0,340.36,345.5,338.12,343.85,4750198.0
-2017-07-25,345.0,345.6,334.15,339.6,6958889.0,0.0,1.0,345.0,345.6,334.15,339.6,6958889.0
-2017-07-24,330.24,343.399,330.01,342.52,8552012.0,0.0,1.0,330.24,343.399,330.01,342.52,8552012.0
-2017-07-21,329.46,331.2575,325.8,328.4,4826383.0,0.0,1.0,329.46,331.2575,325.8,328.4,4826383.0
-2017-07-20,326.9,330.22,324.2,329.92,5098707.0,0.0,1.0,326.9,330.22,324.2,329.92,5098707.0
-2017-07-19,328.23,331.65,323.2193,325.26,6300735.0,0.0,1.0,328.23,331.65,323.2193,325.26,6300735.0
-2017-07-18,317.5,329.13,315.66,328.24,6326961.0,0.0,1.0,317.5,329.13,315.66,328.24,6326961.0
-2017-07-17,325.54,327.1,313.45,319.57,9784200.0,0.0,1.0,325.54,327.1,313.45,319.57,9784200.0
-2017-07-14,323.19,328.42,321.22,327.78,5590393.0,0.0,1.0,323.19,328.42,321.22,327.78,5590393.0
-2017-07-13,330.11,331.6,319.97,323.41,8540442.0,0.0,1.0,330.11,331.6,319.97,323.41,8540442.0
-2017-07-12,330.4,333.1,324.5,329.52,10297839.0,0.0,1.0,330.4,333.1,324.5,329.52,10297839.0
-2017-07-11,316.0,327.28,314.3,327.22,11400054.0,0.0,1.0,316.0,327.28,314.3,327.22,11400054.0
-2017-07-10,312.9,317.94,303.13,316.05,13702080.0,0.0,1.0,312.9,317.94,303.13,316.05,13702080.0
-2017-07-07,313.5,317.0,307.38,313.22,14053750.0,0.0,1.0,313.5,317.0,307.38,313.22,14053750.0
-2017-07-06,317.26,320.7899,306.3,308.89,19189195.0,0.0,1.0,317.26,320.7899,306.3,308.89,19189195.0
-2017-07-05,347.2,347.24,326.33,327.09,16883496.0,0.0,1.0,347.2,347.24,326.33,327.09,16883496.0
-2017-07-03,370.24,371.35,351.5,352.62,6297330.0,0.0,1.0,370.24,371.35,351.5,352.62,6297330.0
-2017-06-30,363.71,366.7674,359.6187,361.61,5759458.0,0.0,1.0,363.71,366.7674,359.6187,361.61,5759458.0
-2017-06-29,370.61,371.0,354.1,360.75,8180408.0,0.0,1.0,370.61,371.0,354.1,360.75,8180408.0
-2017-06-28,366.68,371.74,362.52,371.24,6245040.0,0.0,1.0,366.68,371.74,362.52,371.24,6245040.0
-2017-06-27,376.4,376.4,362.02,362.37,6884529.0,0.0,1.0,376.4,376.4,362.02,362.37,6884529.0
-2017-06-26,386.69,386.95,373.1,377.49,6575285.0,0.0,1.0,386.69,386.95,373.1,377.49,6575285.0
-2017-06-23,382.45,386.99,379.345,383.45,6176578.0,0.0,1.0,382.45,386.99,379.345,383.45,6176578.0
-2017-06-22,377.99,385.0,373.57,382.61,7485677.0,0.0,1.0,377.99,385.0,373.57,382.61,7485677.0
-2017-06-21,374.35,376.99,368.02,376.4,4900356.0,0.0,1.0,374.35,376.99,368.02,376.4,4900356.0
-2017-06-20,376.67,378.88,369.73,372.24,7396357.0,0.0,1.0,376.67,378.88,369.73,372.24,7396357.0
-2017-06-19,375.0,376.7,367.8,369.8,6392331.0,0.0,1.0,375.0,376.7,367.8,369.8,6392331.0
-2017-06-16,377.975,378.01,370.1,371.4,6259666.0,0.0,1.0,377.975,378.01,370.1,371.4,6259666.0
-2017-06-15,372.5,375.46,366.49,375.34,10371559.0,0.0,1.0,372.5,375.46,366.49,375.34,10371559.0
-2017-06-14,381.085,384.25,376.31,380.66,12731997.0,0.0,1.0,381.085,384.25,376.31,380.66,12731997.0
-2017-06-13,367.62,376.0,366.61,375.95,11693404.0,0.0,1.0,367.62,376.0,366.61,375.95,11693404.0
-2017-06-12,357.99,364.5,350.62,359.01,10476833.0,0.0,1.0,357.99,364.5,350.62,359.01,10476833.0
-2017-06-09,374.42,376.87,354.8,357.32,17160231.0,0.0,1.0,374.42,376.87,354.8,357.32,17160231.0
-2017-06-08,363.75,371.9,360.22,370.0,8975028.0,0.0,1.0,363.75,371.9,360.22,370.0,8975028.0
-2017-06-07,356.34,360.5,355.14,359.65,9287888.0,0.0,1.0,356.34,360.5,355.14,359.65,9287888.0
-2017-06-06,344.7,359.4929,339.97,352.85,10951473.0,0.0,1.0,344.7,359.4929,339.97,352.85,10951473.0
-2017-06-05,338.5,348.44,334.21,347.32,6737855.0,0.0,1.0,338.5,348.44,334.21,347.32,6737855.0
-2017-06-02,339.77,342.88,335.93,339.85,5570256.0,0.0,1.0,339.77,342.88,335.93,339.85,5570256.0
-2017-06-01,344.0,344.88,337.29,340.37,7580447.0,0.0,1.0,344.0,344.88,337.29,340.37,7580447.0
diff --git a/examples/quick/demos/stocqt/content/data/TXN.csv b/examples/quick/demos/stocqt/content/data/TXN.csv
deleted file mode 100644
index d42c304e8f..0000000000
--- a/examples/quick/demos/stocqt/content/data/TXN.csv
+++ /dev/null
@@ -1,148 +0,0 @@
-Date,Open,High,Low,Close,Volume,Ex-Dividend,Split Ratio,Adj. Open,Adj. High,Adj. Low,Adj. Close,Adj. Volume
-2017-12-29,104.58,105.08,104.42,104.44,2767863.0,0.0,1.0,104.58,105.08,104.42,104.44,2767863.0
-2017-12-28,104.92,104.92,104.2194,104.82,1632350.0,0.0,1.0,104.92,104.92,104.2194,104.82,1632350.0
-2017-12-27,104.42,104.9,103.98,104.53,1699287.0,0.0,1.0,104.42,104.9,103.98,104.53,1699287.0
-2017-12-26,103.58,104.19,103.06,104.15,1468127.0,0.0,1.0,103.58,104.19,103.06,104.15,1468127.0
-2017-12-22,104.0,104.34,103.64,104.13,3022033.0,0.0,1.0,104.0,104.34,103.64,104.13,3022033.0
-2017-12-21,105.16,105.33,104.0055,104.07,4505720.0,0.0,1.0,105.16,105.33,104.0055,104.07,4505720.0
-2017-12-20,104.9,105.15,103.48,104.8,5433234.0,0.0,1.0,104.9,105.15,103.48,104.8,5433234.0
-2017-12-19,103.19,104.3,103.08,104.1,5133128.0,0.0,1.0,103.19,104.3,103.08,104.1,5133128.0
-2017-12-18,102.1,103.37,101.65,103.27,5494703.0,0.0,1.0,102.1,103.37,101.65,103.27,5494703.0
-2017-12-15,101.28,101.6,100.07,101.22,7773336.0,0.0,1.0,101.28,101.6,100.07,101.22,7773336.0
-2017-12-14,98.96,100.537,98.78,100.25,6802423.0,0.0,1.0,98.96,100.537,98.78,100.25,6802423.0
-2017-12-13,98.97,99.18,98.21,98.86,5151351.0,0.0,1.0,98.97,99.18,98.21,98.86,5151351.0
-2017-12-12,98.7,99.19,98.23,98.43,5766972.0,0.0,1.0,98.7,99.19,98.23,98.43,5766972.0
-2017-12-11,98.07,98.88,97.77,98.83,5137163.0,0.0,1.0,98.07,98.88,97.77,98.83,5137163.0
-2017-12-08,98.92,99.31,97.78,98.02,5282589.0,0.0,1.0,98.92,99.31,97.78,98.02,5282589.0
-2017-12-07,97.32,98.14,96.94,97.78,4195838.0,0.0,1.0,97.32,98.14,96.94,97.78,4195838.0
-2017-12-06,96.25,97.45,95.87,97.02,4438627.0,0.0,1.0,96.25,97.45,95.87,97.02,4438627.0
-2017-12-05,95.98,98.72,95.36,96.9,4759253.0,0.0,1.0,95.98,98.72,95.36,96.9,4759253.0
-2017-12-04,97.54,97.88,95.27,95.97,4891987.0,0.0,1.0,97.54,97.88,95.27,95.97,4891987.0
-2017-12-01,96.54,97.41,94.72,97.18,4925917.0,0.0,1.0,96.54,97.41,94.72,97.18,4925917.0
-2017-11-30,97.38,98.47,96.7,97.29,7195996.0,0.0,1.0,97.38,98.47,96.7,97.29,7195996.0
-2017-11-29,99.73,99.79,96.45,96.88,5408821.0,0.0,1.0,99.73,99.79,96.45,96.88,5408821.0
-2017-11-28,99.09,99.73,98.62,99.48,3010642.0,0.0,1.0,99.09,99.73,98.62,99.48,3010642.0
-2017-11-27,98.95,99.25,98.61,98.63,2900573.0,0.0,1.0,98.95,99.25,98.61,98.63,2900573.0
-2017-11-24,98.2,99.33,98.19,99.3,1288450.0,0.0,1.0,98.2,99.33,98.19,99.3,1288450.0
-2017-11-22,99.15,99.35,98.07,98.08,2109870.0,0.0,1.0,99.15,99.35,98.07,98.08,2109870.0
-2017-11-21,98.75,99.65,98.65,99.19,3668182.0,0.0,1.0,98.75,99.65,98.65,99.19,3668182.0
-2017-11-20,97.81,98.92,97.8,98.28,2912436.0,0.0,1.0,97.81,98.92,97.8,98.28,2912436.0
-2017-11-17,98.56,98.56,97.61,97.74,3694813.0,0.0,1.0,98.56,98.56,97.61,97.74,3694813.0
-2017-11-16,97.07,98.63,97.05,98.32,3531463.0,0.0,1.0,97.07,98.63,97.05,98.32,3531463.0
-2017-11-15,96.62,98.03,96.28,96.77,3332930.0,0.0,1.0,96.62,98.03,96.28,96.77,3332930.0
-2017-11-14,96.7,97.23,96.35,96.96,2727637.0,0.0,1.0,96.7,97.23,96.35,96.96,2727637.0
-2017-11-13,96.4,97.29,96.35,97.03,2158456.0,0.0,1.0,96.4,97.29,96.35,97.03,2158456.0
-2017-11-10,96.67,97.05,96.4,96.94,3093870.0,0.0,1.0,96.67,97.05,96.4,96.94,3093870.0
-2017-11-09,97.6,98.03,95.63,97.05,4180900.0,0.0,1.0,97.6,98.03,95.63,97.05,4180900.0
-2017-11-07,98.55,99.05,98.28,98.4,3883582.0,0.0,1.0,98.55,99.05,98.28,98.4,3883582.0
-2017-11-06,97.82,98.67,97.67,98.54,4261980.0,0.0,1.0,97.82,98.67,97.67,98.54,4261980.0
-2017-11-03,97.0,98.0,96.34,97.98,3329584.0,0.0,1.0,97.0,98.0,96.34,97.98,3329584.0
-2017-11-02,96.25,96.88,95.6,96.79,3274438.0,0.0,1.0,96.25,96.88,95.6,96.79,3274438.0
-2017-11-01,96.97,97.25,95.77,96.35,3826516.0,0.0,1.0,96.97,97.25,95.77,96.35,3826516.0
-2017-10-31,96.28,97.04,96.18,96.69,3747495.0,0.0,1.0,96.28,97.04,96.18,96.69,3747495.0
-2017-10-30,96.68,97.13,95.92,96.06,4914536.0,0.62,1.0,96.68,97.13,95.92,96.06,4914536.0
-2017-10-27,95.94,97.56,95.71,97.5,5534015.0,0.0,1.0,95.324745552338,96.934356640463,95.096220521307,96.874741414977,5534015.0
-2017-10-26,96.44,96.9399,95.84,96.17,5481993.0,0.0,1.0,95.821539098055,96.318233285064,95.225386843194,95.553270583368,5481993.0
-2017-10-25,95.0,96.7,94.16,95.82,6805958.0,0.0,1.0,94.390773686388,96.079871741829,93.556160529582,95.205515101365,6805958.0
-2017-10-24,96.3,96.62,95.46,96.44,7521218.0,0.0,1.0,95.682436905254,96.000384774514,94.847823748448,95.821539098055,7521218.0
-2017-10-23,96.0,96.7399,95.44,96.21,7248578.0,0.0,1.0,95.384360777824,96.119515866777,94.82795200662,95.593014067025,7248578.0
-2017-10-20,94.05,95.4,94.0,95.18,4775490.0,0.0,1.0,93.446865949524,94.788208522962,93.397186594952,94.569619362847,4775490.0
-2017-10-19,92.97,93.64,92.57,93.45,3890390.0,0.0,1.0,92.373791890774,93.039495242036,91.976357054199,92.850713694663,3890390.0
-2017-10-18,94.26,94.29,93.2,93.43,3528482.0,0.0,1.0,93.655519238726,93.685326851469,92.602316921804,92.830841952834,3528482.0
-2017-10-17,94.17,94.31,93.54,94.27,3136049.0,0.0,1.0,93.566096400496,93.705198593297,92.940136532892,93.66545510964,3136049.0
-2017-10-16,94.21,94.41,93.67,94.23,3109004.0,0.0,1.0,93.605839884154,93.804557302441,93.069302854779,93.625711625983,3109004.0
-2017-10-13,93.09,93.73,92.8,93.59,2666130.0,0.0,1.0,92.493022341746,93.128918080265,92.20488208523,92.989815887464,2666130.0
-2017-10-12,92.88,93.31,92.59,92.62,3415763.0,0.0,1.0,92.284369052544,92.711611501862,91.996228796028,92.026036408771,3415763.0
-2017-10-11,91.99,92.92,91.72,92.87,2996950.0,0.0,1.0,91.400076541167,92.324112536202,91.131808026479,92.27443318163,2996950.0
-2017-10-10,91.97,92.41,91.465,92.38,2805769.0,0.0,1.0,91.380204799338,91.81738311957,90.878443318163,91.787575506827,2805769.0
-2017-10-09,91.61,91.86,91.31,91.57,1636340.0,0.0,1.0,91.022513446421,91.27091021928,90.72443731899,90.982769962764,1636340.0
-2017-10-06,90.74,91.54,90.74,91.35,2300990.0,0.0,1.0,90.158092676872,90.952962350021,90.158092676872,90.764180802648,2300990.0
-2017-10-05,90.55,91.3,90.11,91.14,3105380.0,0.0,1.0,89.969311129499,90.714501448076,89.532132809268,90.555527513446,3105380.0
-2017-10-04,89.9,90.56,89.58,90.49,3781466.0,0.0,1.0,89.323479520066,89.979247000414,89.005531650807,89.909695904013,3781466.0
-2017-10-03,89.65,90.24,89.5,89.94,2330174.0,0.0,1.0,89.075082747207,89.661299131154,88.926044683492,89.363223003724,2330174.0
-2017-10-02,89.88,90.24,89.31,89.65,3134142.0,0.0,1.0,89.303607778237,89.661299131154,88.737263136119,89.075082747207,3134142.0
-2017-09-29,89.77,89.89,89.09,89.64,3144262.0,0.0,1.0,89.19431319818,89.313543649152,88.518673976003,89.065146876293,3144262.0
-2017-09-28,88.44,89.66,88.35,89.65,5054134.0,0.0,1.0,87.87284236657,89.085018618122,87.783419528341,89.075082747207,5054134.0
-2017-09-27,88.48,89.15,87.85,88.81,3611592.0,0.0,1.0,87.912585850228,88.578289201489,87.286625982623,88.240469590401,3611592.0
-2017-09-26,87.99,88.29,87.45,87.7,2961476.0,0.0,1.0,87.425728175424,87.723804302855,86.889191146049,87.137587918908,2961476.0
-2017-09-25,87.65,88.08,86.9188,87.5,5475113.0,0.0,1.0,87.087908564336,87.515151013653,86.361397683078,86.938870500621,5475113.0
-2017-09-22,86.59,88.45,86.5,88.27,6374309.0,0.0,1.0,86.034706247414,87.882778237484,85.945283409185,87.703932561026,6374309.0
-2017-09-21,86.02,86.59,85.67,86.05,3979462.0,0.0,1.0,85.468361605296,86.034706247414,85.120606123293,85.498169218039,3979462.0
-2017-09-20,87.0,87.0,84.48,85.83,4829104.0,0.0,1.0,86.442076954903,86.442076954903,83.938237484485,85.279580057923,4829104.0
-2017-09-19,86.37,87.24,85.64,86.81,3924755.0,0.0,1.0,85.816117087298,86.680537856847,85.09079851055,86.25329540753,3924755.0
-2017-09-18,85.0,86.47,84.89,86.14,5296505.0,0.0,1.0,84.454902772031,85.915475796442,84.345608191974,85.587592056268,5296505.0
-2017-09-15,83.14,85.03,82.87,84.84,9419782.0,0.0,1.0,82.606830781961,84.484710384775,82.338562267273,84.295928837402,9419782.0
-2017-09-14,82.4,83.67,82.4,83.29,3482781.0,0.0,1.0,81.871576334299,83.133431940422,81.871576334299,82.755868845676,3482781.0
-2017-09-13,82.84,82.94,82.28,82.7,2531515.0,0.0,1.0,82.30875465453,82.408113363674,81.752345883326,82.169652461729,2531515.0
-2017-09-12,82.34,82.95,82.155,82.89,4559914.0,0.0,1.0,81.811961108813,82.418049234588,81.628147496897,82.358434009102,4559914.0
-2017-09-11,81.9,82.73,81.81,82.22,3810169.0,0.0,1.0,81.374782788581,82.199460074472,81.285359950352,81.69273065784,3810169.0
-2017-09-08,81.98,82.035,81.25,81.38,2423569.0,0.0,1.0,81.454269755896,81.508917045925,80.728951179148,80.858117501034,2423569.0
-2017-09-07,82.45,83.99,81.79,82.0,3568251.0,0.0,1.0,81.921255688871,83.451379809681,81.265488208523,81.474141497724,3568251.0
-2017-09-06,82.24,82.37,81.59,82.07,3627993.0,0.0,1.0,81.712602399669,81.841768721556,81.066770790236,81.543692594125,3627993.0
-2017-09-05,82.32,82.49,81.27,81.85,3665925.0,0.0,1.0,81.792089366984,81.960999172528,80.748822920976,81.325103434009,3665925.0
-2017-09-01,82.74,83.1137,82.38,82.54,2644706.0,0.0,1.0,82.209395945387,82.580699441456,81.85170459247,82.0106785271,2644706.0
-2017-08-31,82.44,82.95,82.13,82.82,4301382.0,0.0,1.0,81.911319817956,82.418049234588,81.603307819611,82.288882912702,4301382.0
-2017-08-30,81.21,82.41,81.1,82.31,4353457.0,0.0,1.0,80.68920769549,81.881512205213,80.579913115432,81.78215349607,4353457.0
-2017-08-29,80.08,81.25,80.03,81.03,3677615.0,0.0,1.0,79.566454282168,80.728951179148,79.516774927596,80.510362019032,3677615.0
-2017-08-28,81.44,81.66,80.58,80.76,3042730.0,0.0,1.0,80.91773272652,81.136321886636,80.063247827886,80.242093504344,3042730.0
-2017-08-25,81.58,81.9,80.94,80.98,2560280.0,0.0,1.0,81.056834919321,81.374782788581,80.420939180803,80.46068266446,2560280.0
-2017-08-24,81.16,81.495,80.82,81.25,3312832.0,0.0,1.0,80.639528340918,80.972380016549,80.30170872983,80.728951179148,3312832.0
-2017-08-23,80.24,81.12,80.07,80.89,4039288.0,0.0,1.0,79.725428216798,80.599784857261,79.556518411254,80.371259826231,4039288.0
-2017-08-22,80.34,81.13,80.06,80.75,4302975.0,0.0,1.0,79.824786925941,80.609720728175,79.546582540339,80.23215763343,4302975.0
-2017-08-21,80.14,80.24,79.6,79.89,3167966.0,0.0,1.0,79.626069507654,79.725428216798,79.089532478279,79.377672734795,3167966.0
-2017-08-18,80.09,80.69,79.94,79.97,3605319.0,0.0,1.0,79.576390153082,80.172542407944,79.427352089367,79.45715970211,3605319.0
-2017-08-17,81.95,82.16,80.09,80.15,4036391.0,0.0,1.0,81.424462143153,81.633115432354,79.576390153082,79.636005378568,4036391.0
-2017-08-16,82.42,82.66,81.95,82.46,3171387.0,0.0,1.0,81.891448076127,82.129908978072,81.424462143153,81.931191559785,3171387.0
-2017-08-15,82.07,82.31,81.69,81.95,3597596.0,0.0,1.0,81.543692594125,81.78215349607,81.166129499379,81.424462143153,3597596.0
-2017-08-14,81.48,82.21,81.2031,82.05,3449064.0,0.0,1.0,80.957476210178,81.682794786926,80.682351944559,81.523820852296,3449064.0
-2017-08-11,80.58,81.34,80.43,80.89,3348656.0,0.0,1.0,80.063247827886,80.818374017377,79.91420976417,80.371259826231,3348656.0
-2017-08-10,81.8,82.0,80.28,80.36,4260051.0,0.0,1.0,81.275424079437,81.474141497724,79.765171700455,79.84465866777,4260051.0
-2017-08-09,81.97,82.31,81.38,82.28,4083335.0,0.0,1.0,81.444333884981,81.78215349607,80.858117501034,81.752345883326,4083335.0
-2017-08-08,81.99,83.69,81.89,82.45,6995231.0,0.0,1.0,81.46420562681,83.153303682251,81.364846917667,81.921255688871,6995231.0
-2017-08-07,81.44,82.2,81.44,82.17,2808616.0,0.0,1.0,80.91773272652,81.672858916012,80.91773272652,81.643051303269,2808616.0
-2017-08-04,81.63,81.96,81.25,81.43,2293905.0,0.0,1.0,81.106514273893,81.434398014067,80.728951179148,80.907796855606,2293905.0
-2017-08-03,81.3,81.73,80.965,81.36,2704547.0,0.0,1.0,80.778630533719,81.205872983037,80.445778858089,80.838245759206,2704547.0
-2017-08-02,82.01,82.01,80.64,81.31,3121636.0,0.0,1.0,81.484077368639,81.484077368639,80.122863053372,80.788566404634,3121636.0
-2017-08-01,81.6,81.84,81.02,81.71,3243303.0,0.0,1.0,81.07670666115,81.315167563095,80.500426148117,81.186001241208,3243303.0
-2017-07-31,80.83,81.66,80.78,81.38,5780471.0,0.0,1.0,80.311644600745,81.136321886636,80.261965246173,80.858117501034,5780471.0
-2017-07-28,80.42,81.04,80.05,80.71,5188380.0,0.0,1.0,79.904273893256,80.520297889946,79.536646669425,80.192414149772,5188380.0
-2017-07-27,82.125,82.53,80.09,80.97,6842762.0,0.5,1.0,81.598339884154,82.000742656185,79.576390153082,80.450746793546,6842762.0
-2017-07-26,83.0,84.24,81.96,82.55,6633813.0,0.0,1.0,81.9616053009,83.186091934311,80.934616511587,81.517235151678,6633813.0
-2017-07-25,81.05,81.93,80.58,81.39,6302456.0,0.0,1.0,80.036001320939,80.904991834972,79.571881387307,80.371747655906,6302456.0
-2017-07-24,81.86,81.8673,80.6,80.92,4333751.0,0.0,1.0,80.835867589538,80.843076260847,79.591631171717,79.907627722275,4333751.0
-2017-07-21,81.46,82.0,81.0,81.7,4396691.0,0.0,1.0,80.440871901341,80.974116080407,79.986626859914,80.677869314259,4396691.0
-2017-07-20,82.2,82.81,81.8621,82.69,3719865.0,0.0,1.0,81.171613924505,81.773982349006,80.837941316901,81.655483642547,3719865.0
-2017-07-19,82.49,82.7,81.86,82.16,3065398.0,0.0,1.0,81.457985798448,81.665358534752,80.835867589538,81.132114355686,3065398.0
-2017-07-18,81.5,82.205,81.15,82.16,2713549.0,0.0,1.0,80.480371470161,81.176551370608,80.134750242988,81.132114355686,2713549.0
-2017-07-17,81.82,82.0,81.48,81.66,2955424.0,0.0,1.0,80.796368020718,80.974116080407,80.460621685751,80.638369745439,2955424.0
-2017-07-14,80.95,82.11,80.8481,82.0,3597113.0,0.0,1.0,79.937252398889,81.082739894661,79.836627247321,80.974116080407,3597113.0
-2017-07-13,80.41,80.98,80.265,80.54,3323859.0,0.0,1.0,79.404008219823,79.966877075504,79.260822282852,79.532381818487,3323859.0
-2017-07-12,79.46,80.54,79.46,80.52,3839369.0,0.0,1.0,78.465893460355,79.532381818487,78.465893460355,79.512632034078,3839369.0
-2017-07-11,78.78,79.145,78.28,79.04,2673057.0,0.0,1.0,77.79440079042,78.1548343559,77.300656180174,78.051147987748,2673057.0
-2017-07-10,78.43,79.09,77.925,78.78,3266394.0,0.0,1.0,77.448779563248,78.100522448773,76.950097506899,77.79440079042,3266394.0
-2017-07-07,77.31,78.66,77.31,78.48,5215579.0,0.0,1.0,76.342791636296,77.675902083961,76.342791636296,77.498154024272,5215579.0
-2017-07-06,76.19,77.69,76.19,76.86,4998196.0,0.0,1.0,75.236803709344,76.718037540083,75.236803709344,75.898421487074,4998196.0
-2017-07-05,76.63,77.51,76.24,76.91,6552479.0,0.0,1.0,75.671298966361,76.540289480394,75.286178170369,75.947795948099,6552479.0
-2017-07-03,77.45,77.635,76.4,76.41,3493669.0,0.0,1.0,76.481040127165,76.663725632956,75.444176445647,75.454051337852,3493669.0
-2017-06-30,77.69,77.69,76.61,76.93,4618555.0,0.0,1.0,76.718037540083,76.718037540083,75.651549181951,75.967545732509,4618555.0
-2017-06-29,77.5,77.93,75.9199,76.9,6526856.0,0.0,1.0,76.530414588189,76.955034953001,74.970082870889,75.937921055894,6526856.0
-2017-06-28,77.61,78.21,76.95,78.06,6338112.0,0.0,1.0,76.639038402444,77.231531934739,75.987295516918,77.083408551665,6338112.0
-2017-06-27,78.0,78.27,76.94,76.95,5697074.0,0.0,1.0,77.024159198436,77.290781287969,75.977420624713,75.987295516918,5697074.0
-2017-06-26,80.04,80.09,78.24,78.31,4881033.0,0.0,1.0,79.038637208241,79.088011669266,77.261156611354,77.330280856789,4881033.0
-2017-06-23,79.06,80.02,78.64,79.58,3608764.0,0.0,1.0,78.070897772158,79.018887423831,77.656152299551,78.584392166814,3608764.0
-2017-06-22,79.95,80.05,78.95,79.05,3306610.0,0.0,1.0,78.949763178397,79.048512100446,77.962273957904,78.061022879953,3306610.0
-2017-06-21,79.7,79.92,79.23,79.67,4256147.0,0.0,1.0,78.702890873274,78.920138501782,78.238770939642,78.673266196659,4256147.0
-2017-06-20,81.16,81.23,79.54,79.57,3789428.0,0.0,1.0,80.144625135193,80.213749380627,78.544892597995,78.574517274609,3789428.0
-2017-06-19,80.37,81.45,80.28,81.42,3479332.0,0.0,1.0,79.364508651004,80.430997009136,79.275634621159,80.401372332521,3479332.0
-2017-06-16,79.85,80.23,79.02,79.7,5945383.0,0.0,1.0,78.851014256347,79.226260160135,78.031398203338,78.702890873274,5945383.0
-2017-06-15,79.35,80.4,79.22,80.08,3024056.0,0.0,1.0,78.357269646101,79.394133327618,78.228896047437,79.078136777061,3024056.0
-2017-06-14,81.26,81.49,79.44,80.16,3919507.0,0.0,1.0,80.243374057242,80.470496577956,78.446143675945,79.1571359147,3919507.0
-2017-06-13,81.41,81.8,80.6,80.98,4274125.0,0.0,1.0,80.391497440316,80.776618236308,79.591631171717,79.966877075504,4274125.0
-2017-06-12,79.82,81.32,79.6678,81.05,6724786.0,0.0,1.0,78.821389579733,80.302623410472,78.671093720374,80.036001320939,6724786.0
-2017-06-09,84.23,84.65,79.94,80.9,6785300.0,0.0,1.0,83.176217042106,83.590962514713,78.939888286192,79.887877937865,6785300.0
-2017-06-08,83.2,84.36,82.62,84.34,4332428.0,0.0,1.0,82.159103144998,83.30459064077,81.586359397112,83.28484085636,4332428.0
-2017-06-07,82.8,83.43,82.29,82.89,3705908.0,0.0,1.0,81.764107456801,82.386225665712,81.26048795435,81.852981486645,3705908.0
-2017-06-06,81.65,82.875,81.51,82.22,3222387.0,0.0,1.0,80.628494853234,81.838169148338,80.490246362365,81.191363708915,3222387.0
-2017-06-05,81.66,82.38,81.66,81.885,2467546.0,0.0,1.0,80.638369745439,81.349361984194,80.638369745439,80.86055482005,2467546.0
-2017-06-02,81.96,81.97,80.86,81.63,4714171.0,0.0,1.0,80.934616511587,80.944491403792,79.848378369045,80.608745068825,4714171.0
-2017-06-01,82.61,82.8642,81.215,81.49,4292961.0,0.0,1.0,81.576484504907,81.827504264757,80.19893704232,80.470496577956,4292961.0
diff --git a/examples/quick/demos/stocqt/content/images/icon-left-arrow.png b/examples/quick/demos/stocqt/content/images/icon-left-arrow.png
deleted file mode 100644
index 926938cadd..0000000000
--- a/examples/quick/demos/stocqt/content/images/icon-left-arrow.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/stocqt/content/images/wheel-touch.png b/examples/quick/demos/stocqt/content/images/wheel-touch.png
deleted file mode 100644
index 11c8120ada..0000000000
--- a/examples/quick/demos/stocqt/content/images/wheel-touch.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/stocqt/content/images/wheel.png b/examples/quick/demos/stocqt/content/images/wheel.png
deleted file mode 100644
index 470a675b35..0000000000
--- a/examples/quick/demos/stocqt/content/images/wheel.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/stocqt/content/qmldir b/examples/quick/demos/stocqt/content/qmldir
deleted file mode 100644
index 77f5ed3c56..0000000000
--- a/examples/quick/demos/stocqt/content/qmldir
+++ /dev/null
@@ -1,12 +0,0 @@
-singleton Settings 1.0 Settings.qml
-Button 1.0 Button.qml
-CheckBox 1.0 CheckBox.qml
-StockChart 1.0 StockChart.qml
-StockInfo 1.0 StockInfo.qml
-StockListModel 1.0 StockListModel.qml
-StockListView 1.0 StockListView.qml
-StockModel 1.0 StockModel.qml
-StockSettingsPanel 1.0 StockSettingsPanel.qml
-StockView 1.0 StockView.qml
-StockListDelegate 1.0 StockListDelegate.qml
-Banner 1.0 Banner.qml
diff --git a/examples/quick/demos/stocqt/doc/images/qtquick-demo-stocqt.png b/examples/quick/demos/stocqt/doc/images/qtquick-demo-stocqt.png
deleted file mode 100644
index 38e279d60d..0000000000
--- a/examples/quick/demos/stocqt/doc/images/qtquick-demo-stocqt.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/stocqt/doc/src/stocqt.qdoc b/examples/quick/demos/stocqt/doc/src/stocqt.qdoc
deleted file mode 100644
index e324cf63b5..0000000000
--- a/examples/quick/demos/stocqt/doc/src/stocqt.qdoc
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - StocQt
- \ingroup qtquickdemos
- \example demos/stocqt
- \brief A configurable stock chart for the NASDAQ-100.
- \borderedimage qtquick-demo-stocqt.png
-
- The \e{StocQt} application presents a trend chart for the first stock in
- the list of NASDAQ-100 stocks. It allows the user to choose another stock
- from the list, and fetches the required data from the offline dataset
- using \c XMLHttpRequest.
-
- The application uses several custom types such as Button, CheckBox,
- StockChart, StockInfo, StockView, and so on. These types are used to
- present the stock data in a readable form and also let the user customize
- the trend chart. For example, the user can choose to view the weekly,
- monthly, quarterly, or half yearly trends in the stock price.
-
- The application uses the ObjectModel type to access the two visual data
- models that it depends on.
-
- \quotefromfile demos/stocqt/stocqt.qml
- \skipto ListView
- \printuntil id
- \dots 8
- \skipto model
- \printuntil StockView
- \printuntil }
- \printuntil }
- \printuntil }
-
- The StockListView model is a static data model listing the
- NASDAQ-100 stocks with basic information such as stockId, name, value,
- change, and so on. This data model is used by the application if the
- user wants to choose another stock from the list.
-
- StockView is a complex data model that presents a trend chart for the
- selected stock. It uses another custom type, StockChart, which presents
- the graphical trend of the stock price using a Canvas. This data model
- is used for most of the time during the lifetime of the application.
-
- \quotefromfile demos/stocqt/content/StockChart.qml
- \skipto Rectangle
- \printuntil id
- \dots
- \skipto Canvas
- \printuntil id
- \dots 8
- \skipto onPaint
- \printuntil /^\}$/
-
- To understand the application better, browse through its code using
- Qt Creator.
-
- \include examples-run.qdocinc
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/stocqt/main.cpp b/examples/quick/demos/stocqt/main.cpp
deleted file mode 100644
index 6031e28105..0000000000
--- a/examples/quick/demos/stocqt/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/stocqt/stocqt)
diff --git a/examples/quick/demos/stocqt/stocqt.pro b/examples/quick/demos/stocqt/stocqt.pro
deleted file mode 100644
index 0e89a30050..0000000000
--- a/examples/quick/demos/stocqt/stocqt.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-TEMPLATE = app
-
-QT += qml quick
-SOURCES += main.cpp
-RESOURCES += stocqt.qrc
-OTHER_FILES += *.qml content/*.qml content/images/*.png
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/stocqt
-INSTALLS += target
diff --git a/examples/quick/demos/stocqt/stocqt.qmlproject b/examples/quick/demos/stocqt/stocqt.qmlproject
deleted file mode 100644
index 11ab78418a..0000000000
--- a/examples/quick/demos/stocqt/stocqt.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "stocqt.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
-}
diff --git a/examples/quick/demos/stocqt/stocqt.qrc b/examples/quick/demos/stocqt/stocqt.qrc
deleted file mode 100644
index a1c3b25494..0000000000
--- a/examples/quick/demos/stocqt/stocqt.qrc
+++ /dev/null
@@ -1,42 +0,0 @@
-<RCC>
- <qresource prefix="/demos/stocqt">
- <file>stocqt.qml</file>
- <file>content/qmldir</file>
- <file>content/Button.qml</file>
- <file>content/CheckBox.qml</file>
- <file>content/StockChart.qml</file>
- <file>content/StockListModel.qml</file>
- <file>content/StockListView.qml</file>
- <file>content/StockModel.qml</file>
- <file>content/StockView.qml</file>
- <file>content/images/wheel-touch.png</file>
- <file>content/images/wheel.png</file>
- <file>content/images/icon-left-arrow.png</file>
- <file>content/StockSettingsPanel.qml</file>
- <file>content/StockInfo.qml</file>
- <file>content/Settings.qml</file>
- <file>content/+windows/Settings.qml</file>
- <file>content/StockListDelegate.qml</file>
- <file>content/Banner.qml</file>
- <file>content/data/AAPL.csv</file>
- <file>content/data/ADSK.csv</file>
- <file>content/data/AMZN.csv</file>
- <file>content/data/AMD.csv</file>
- <file>content/data/CSCO.csv</file>
- <file>content/data/FB.csv</file>
- <file>content/data/GOOG.csv</file>
- <file>content/data/GOOGL.csv</file>
- <file>content/data/MSFT.csv</file>
- <file>content/data/NCLH.csv</file>
- <file>content/data/NFLX.csv</file>
- <file>content/data/TXN.csv</file>
- <file>content/data/EA.csv</file>
- <file>content/data/EBAY.csv</file>
- <file>content/data/PYPL.csv</file>
- <file>content/data/INTC.csv</file>
- <file>content/data/NTAP.csv</file>
- <file>content/data/QCOM.csv</file>
- <file>content/data/NVDA.csv</file>
- <file>content/data/TSLA.csv</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/demos/tweetsearch/content/FlipBar.qml b/examples/quick/demos/tweetsearch/content/FlipBar.qml
deleted file mode 100644
index 608f5cc08b..0000000000
--- a/examples/quick/demos/tweetsearch/content/FlipBar.qml
+++ /dev/null
@@ -1,183 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: container
- property int animDuration: 300
- property Item front: Item {}
- property Item back: Item {}
- property real factor: 0.1 // amount the edges fold in for the 3D effect
- property alias delta: effect.delta
- property Item cur: frontShown ? front : back
- property Item noncur: frontShown ? back : front
-
- function swap() {
- var tmp = front;
- front = back;
- back = tmp;
- resync();
- }
-
- width: cur.width
- height: cur.height
- onFrontChanged: resync();
- onBackChanged: resync();
-
- function resync() {//TODO: Are the items ever actually visible?
- back.parent = container;
- front.parent = container;
- frontShown ? back.visible = false : front.visible = false;
- }
-
- property bool frontShown: true
-
- onFrontShownChanged: {
- back.visible = !frontShown
- front.visible = frontShown
- }
-
- function flipUp(start) {
- effect.visible = true;
- effect.sourceA = effect.source1
- effect.sourceB = effect.source2
- if (start == undefined)
- start = 1.0;
- deltaAnim.from = start;
- deltaAnim.to = 0.0
- dAnim.start();
- frontShown = false;
- }
-
- function flipDown(start) {
- effect.visible = true;
- effect.sourceA = effect.source1
- effect.sourceB = effect.source2
- if (start == undefined)
- start = 0.0;
- deltaAnim.from = start;
- deltaAnim.to = 1.0
- dAnim.start();
- frontShown = true;
- }
-
- ShaderEffect {
- id: effect
- width: cur.width
- height: cur.height
- property real factor: container.factor * width
- property real delta: 1.0
-
- mesh: GridMesh { resolution: Qt.size(8,2) }
-
- SequentialAnimation on delta {
- id: dAnim
- running: false
- NumberAnimation {
- id: deltaAnim
- duration: animDuration//expose anim
- }
- }
-
- property variant sourceA: source1
- property variant sourceB: source1
- property variant source1: ShaderEffectSource {
- sourceItem: front
- hideSource: effect.visible
- }
-
- property variant source2: ShaderEffectSource {
- sourceItem: back
- hideSource: effect.visible
- }
-
- fragmentShader: "
- uniform lowp float qt_Opacity;
- uniform sampler2D sourceA;
- uniform sampler2D sourceB;
- uniform highp float delta;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 tex = vec4(qt_TexCoord0.x, qt_TexCoord0.y * 2.0, qt_TexCoord0.x, (qt_TexCoord0.y-0.5) * 2.0);
- highp float shade = clamp(delta*2.0, 0.5, 1.0);
- highp vec4 col;
- if (qt_TexCoord0.y < 0.5) {
- col = texture2D(sourceA, tex.xy) * (shade);
- } else {
- col = texture2D(sourceB, tex.zw) * (1.5 - shade);
- col.w = 1.0;
- }
- gl_FragColor = col * qt_Opacity;
- }
- "
- property real h: height
- vertexShader: "
- uniform highp float delta;
- uniform highp float factor;
- uniform highp float h;
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- void main() {
- highp vec4 pos = qt_Vertex;
- if (qt_MultiTexCoord0.y == 0.0)
- pos.x += factor * (1. - delta) * (qt_MultiTexCoord0.x * -2.0 + 1.0);
- else if (qt_MultiTexCoord0.y == 1.0)
- pos.x += factor * (delta) * (qt_MultiTexCoord0.x * -2.0 + 1.0);
- else
- pos.y = delta * h;
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
-
- }
-}
diff --git a/examples/quick/demos/tweetsearch/content/LineInput.qml b/examples/quick/demos/tweetsearch/content/LineInput.qml
deleted file mode 100644
index 1ef8fd9f5c..0000000000
--- a/examples/quick/demos/tweetsearch/content/LineInput.qml
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-FocusScope {
- id: wrapper
-
- property alias text: input.text
- property alias hint: hint.text
- property alias prefix: prefix.text
-
- signal accepted
-
- Rectangle {
- anchors.fill: parent
- border.color: "#707070"
- color: "#c1c1c1"
- radius: 4
-
- Text {
- id: hint
- anchors { fill: parent; leftMargin: 14 }
- verticalAlignment: Text.AlignVCenter
- text: "Enter word"
- font.pixelSize: 18
- color: "#707070"
- opacity: input.displayText.length ? 0 : 1
- }
-
- Text {
- id: prefix
- anchors { left: parent.left; leftMargin: 14; verticalCenter: parent.verticalCenter }
- verticalAlignment: Text.AlignVCenter
- font.pixelSize: 18
- color: "#707070"
- opacity: !hint.opacity
- }
-
- TextInput {
- id: input
- focus: true
- anchors { left: prefix.right; right: parent.right; top: parent.top; bottom: parent.bottom }
- verticalAlignment: Text.AlignVCenter
- font.pixelSize: 18
- color: "#707070"
- onAccepted: wrapper.accepted()
- }
-
- Image {
- source: "resources/icon-search.png"
- anchors.right: parent.right
- anchors.rightMargin: 12
- anchors.verticalCenter: parent.verticalCenter
- MouseArea {
- anchors { fill: parent; margins: -10 }
- onClicked: wrapper.accepted()
- }
- }
- }
-}
diff --git a/examples/quick/demos/tweetsearch/content/ListFooter.qml b/examples/quick/demos/tweetsearch/content/ListFooter.qml
deleted file mode 100644
index b84496d4c1..0000000000
--- a/examples/quick/demos/tweetsearch/content/ListFooter.qml
+++ /dev/null
@@ -1,164 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Rectangle {
- color: "#d6d6d6"
- width: parent.width
- height: childrenRect.height
- z: 2
- Connections {
- target: mainListView
- onAutoSearch: {
- if (type == 'tag') {
- tagSearch.open()
- tagSearch.searchText = str
- } else if (type == 'user'){
- userSearch.open()
- userSearch.searchText = str
- } else {
- wordSearch.open()
- wordSearch.searchText = str
- }
- }
- }
-
- Column {
- width: parent.width
-
- SearchDelegate {
- id: wordSearch
- label: "Search word..."
- placeHolder: "Enter word"
- onHasOpened: {
- tagSearch.close()
- userSearch.close()
- }
- onOk: {
- mainListView.positionViewAtBeginning()
- mainListView.clear()
- tweetsModel.from = ""
- tweetsModel.phrase = searchText
- }
- }
-
- SearchDelegate {
- id: userSearch
- label: "From user..."
- placeHolder: "@username"
- prefix: "@"
- onHasOpened:{
- tagSearch.close()
- wordSearch.close()
- }
- onOk: {
- mainListView.positionViewAtBeginning()
- mainListView.clear()
- tweetsModel.phrase = ""
- tweetsModel.from = searchText
- }
- }
-
- SearchDelegate {
- id: tagSearch
- label: "Search hashtag..."
- placeHolder: "#hashtag"
- prefix: "#"
- onHasOpened:{
- userSearch.close()
- wordSearch.close()
- }
- onOk: {
- mainListView.positionViewAtBeginning()
- mainListView.clear()
- tweetsModel.from = ""
- tweetsModel.phrase = "#" + searchText
- }
- }
-
- SpriteSequence {
- id: sprite
- anchors.horizontalCenter: parent.horizontalCenter
- width: 320
- height: 300
- running: true
- interpolate: false
- Sprite {
- name: "bird"
- source: "resources/bird-anim-sprites.png"
- frameCount: 1
- frameRate: 1
- frameWidth: 320
- frameHeight: 300
- to: { "bird":10, "trill":1, "blink":1 }
- }
- Sprite {
- name: "trill"
- source: "resources/bird-anim-sprites.png"
- frameCount: 5
- frameRate: 3
- frameWidth: 320
- frameHeight: 300
- to: {"bird":1}
- }
- Sprite {
- name: "blink"
- source: "resources/bird-anim-sprites.png"
- frameCount: 1
- frameRate: 3
- frameWidth: 320
- frameHeight: 300
- frameX: 1600
- to: {"bird":1}
- }
- }
- }
-}
diff --git a/examples/quick/demos/tweetsearch/content/ListHeader.qml b/examples/quick/demos/tweetsearch/content/ListHeader.qml
deleted file mode 100644
index 8c4facf34b..0000000000
--- a/examples/quick/demos/tweetsearch/content/ListHeader.qml
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- height: 60
- width: parent.width
-
- property bool refresh: state == "pulled" ? true : false
-
- Row {
- spacing: 6
- height: childrenRect.height
- anchors.centerIn: parent
-
- Image {
- id: arrow
- source: "resources/icon-refresh.png"
- transformOrigin: Item.Center
- Behavior on rotation { NumberAnimation { duration: 200 } }
- }
-
- Text {
- id: label
- anchors.verticalCenter: arrow.verticalCenter
- text: "Pull to refresh... "
- font.pixelSize: 18
- color: "#999999"
- }
- }
-
- states: [
- State {
- name: "base"; when: mainListView.contentY >= -120
- PropertyChanges { target: arrow; rotation: 180 }
- },
- State {
- name: "pulled"; when: mainListView.contentY < -120
- PropertyChanges { target: label; text: "Release to refresh..." }
- PropertyChanges { target: arrow; rotation: 0 }
- }
- ]
-}
diff --git a/examples/quick/demos/tweetsearch/content/SearchDelegate.qml b/examples/quick/demos/tweetsearch/content/SearchDelegate.qml
deleted file mode 100644
index 082653657a..0000000000
--- a/examples/quick/demos/tweetsearch/content/SearchDelegate.qml
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-FlipBar {
- id: flipBar
- animDuration: 250
- property string label: ""
- property string placeHolder: ""
- property alias searchText: lineInput.text
- property alias prefix: lineInput.prefix
- property bool opened: false
- signal ok
- signal hasOpened
-
- height: 60
- width: parent.width
-
- function open() {
- flipBar.flipUp()
- flipBar.opened = true
- lineInput.forceActiveFocus()
- flipBar.hasOpened()
- }
-
- function close() {
- if (opened) {
- flipBar.flipDown()
- flipBar.opened = false
- }
- }
-
- front: Rectangle {
- height: 60
- width: parent.width
- color: "#999999"
-
- Rectangle { color: "#c1c1c1"; width: parent.width; height: 1 }
- Rectangle { color: "#707070"; width: parent.width; height: 1; anchors.bottom: parent.bottom }
-
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked: {
- if (!flipBar.opened)
- open()
- else if (!lineInput.activeFocus)
- lineInput.forceActiveFocus()
- else
- close()
- }
- }
-
- Text {
- text: flipBar.label
- anchors { left: parent.left; leftMargin: 20 }
- anchors.verticalCenter: parent.verticalCenter
- font.pixelSize: 18
- color: "#ffffff"
- }
- }
-
- back: FocusScope {
- height: 60
- width: parent.width
- Rectangle {
- anchors.fill: parent
- color: "#999999"
-
- Rectangle { color: "#c1c1c1"; width: parent.width; height: 1 }
- Rectangle { color: "#707070"; width: parent.width; height: 1; anchors.bottom: parent.bottom }
-
- LineInput {
- id: lineInput
- hint: flipBar.placeHolder
- focus: flipBar.opened
- anchors { fill: parent; margins: 6 }
- onAccepted: {
- if (Qt.inputMethod.visible)
- Qt.inputMethod.hide()
- flipBar.ok()
- }
- }
- }
- }
-
-}
diff --git a/examples/quick/demos/tweetsearch/content/TweetDelegate.qml b/examples/quick/demos/tweetsearch/content/TweetDelegate.qml
deleted file mode 100644
index b8953314f1..0000000000
--- a/examples/quick/demos/tweetsearch/content/TweetDelegate.qml
+++ /dev/null
@@ -1,199 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "tweetsearch.js" as Helper
-
-Item {
- id: container
- property real hm: 1.0
- property int appear: -1
- property real startRotation: 1
-
- onAppearChanged: {
- container.startRotation = 0.5
- flipBar.animDuration = appear;
- delayedAnim.start();
- }
-
- SequentialAnimation {
- id: delayedAnim
- PauseAnimation { duration: 50 }
- ScriptAction { script: flipBar.flipDown(startRotation); }
- }
-
- width: 320
- height: flipBar.height * hm
-
- FlipBar {
- id: flipBar
-
- property bool flipped: false
- delta: startRotation
-
- anchors.bottom: parent.bottom
- width: container.ListView.view ? container.ListView.view.width : 0
- height: Math.max(72, tweet.y + tweet.height + 10)
-
- front: Rectangle {
- width: container.ListView.view ? container.ListView.view.width : 0
- height: Math.max(72, tweet.y + tweet.height + 10)
- color: "#2699bf"
-
- Rectangle { color: "#33ccff"; width: parent.width; height: 1 }
- Rectangle { color: "#1a6680"; width: parent.width; height: 1; anchors.bottom: parent.bottom }
-
- Image {
- id: placeHolder
- source: "resources/anonymous.png"
- x: 10; y: 9
- visible: avatar.status != Image.Ready
- }
-
- Image {
- id: avatar
- source: model.userImage
- anchors.fill: placeHolder
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked: {
- flipBar.flipUp()
- flipBar.flipped = true
- }
- }
- }
-
- Text {
- id: name
- text: model.name
- anchors { left: avatar.right; leftMargin: 10; top: avatar.top; topMargin: -3 }
- font.pixelSize: 12
- font.bold: true
- color: "white"
- linkColor: "white"
- }
-
- Text {
- id: tweet
- text: model.statusText
- anchors { left: avatar.right; leftMargin: 10; top: name.bottom; topMargin: 0; right: parent.right; rightMargin: 10 }
- wrapMode: Text.WordWrap
- font.pixelSize: 12
- font.bold: false
- color: "#adebff"
- linkColor: "white"
- onLinkActivated: {
- var tag = link.split("https://twitter.com/search?q=%23")
- var user = link.split("https://twitter.com/")
- if (tag[1] != undefined) {
- mainListView.positionViewAtBeginning()
- mainListView.clear()
- mainListView.autoSearch('tag', tag[1])
- tweetsModel.from = ""
- tweetsModel.phrase = "#" + tag[1]
- } else if (user[1] != undefined) {
- mainListView.positionViewAtBeginning()
- mainListView.clear()
- mainListView.autoSearch('user', user[1])
- tweetsModel.phrase = ""
- tweetsModel.from = user[1]
- } else
- Qt.openUrlExternally(link)
- }
- }
- }
-
- back: Rectangle {
- width: container.ListView.view ? container.ListView.view.width : 0
- height: Math.max(72, tweet.y + tweet.height + 10)
- color: "#be4a25"
-
- Rectangle { color: "#ff6633"; width: parent.width; height: 1 }
- Rectangle { color: "#80341a"; width: parent.width; height: 1; anchors.bottom: parent.bottom }
-
- Image {
- id: avatar2
- source: model.userImage
- anchors.right: parent.right
- anchors.rightMargin: 10
- y: 9
- MouseArea {
- anchors.fill: parent
- onClicked: {
- flipBar.flipDown()
- flipBar.flipped = false
- }
- }
- }
-
- Text {
- id: username
- text: model.twitterName
- x: 10; anchors { top: avatar2.top; topMargin: -3 }
- font.pixelSize: 12
- font.bold: true
- color: "white"
- linkColor: "white"
- }
-
- Text {
- text: model.source + "<br>" + Helper.formatDate(model.published) + "<br>" + model.uri
- x: 10; anchors { top: username.bottom; topMargin: 0 }
- wrapMode: Text.WordWrap
- font.pixelSize: 12
- font.bold: false
- color: "#ffc2ad"
- linkColor: "white"
- onLinkActivated: Qt.openUrlExternally(link);
- }
- }
- }
-}
diff --git a/examples/quick/demos/tweetsearch/content/TweetsModel.qml b/examples/quick/demos/tweetsearch/content/TweetsModel.qml
deleted file mode 100644
index 492f85be76..0000000000
--- a/examples/quick/demos/tweetsearch/content/TweetsModel.qml
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "tweetsearch.js" as Helper
-
-Item {
- id: wrapper
-
- // Insert valid consumer key and secret tokens below
- // See https://dev.twitter.com/apps
-//! [auth tokens]
- property string consumerKey : ""
- property string consumerSecret : ""
-//! [auth tokens]
- property string bearerToken : ""
-
- property variant model: tweets
- property string from : ""
- property string phrase : ""
-
- property int status: XMLHttpRequest.UNSENT
- property bool isLoading: status === XMLHttpRequest.LOADING
- property bool wasLoading: false
- signal isLoaded
-
- ListModel { id: tweets }
-
- function encodePhrase(x) { return encodeURIComponent(x); }
-
- function reload() {
- tweets.clear()
-
- if (from == "" && phrase == "")
- return;
-
-//! [requesting]
- var req = new XMLHttpRequest;
- req.open("GET", "https://api.twitter.com/1.1/search/tweets.json?from=" + from +
- "&count=10&q=" + encodePhrase(phrase));
- req.setRequestHeader("Authorization", "Bearer " + bearerToken);
- req.onreadystatechange = function() {
- status = req.readyState;
- if (status === XMLHttpRequest.DONE) {
- var objectArray = JSON.parse(req.responseText);
- if (objectArray.errors !== undefined)
- console.log("Error fetching tweets: " + objectArray.errors[0].message)
- else {
- for (var key in objectArray.statuses) {
- var jsonObject = objectArray.statuses[key];
- tweets.append(jsonObject);
- }
- }
- if (wasLoading == true)
- wrapper.isLoaded()
- }
- wasLoading = (status === XMLHttpRequest.LOADING);
- }
- req.send();
-//! [requesting]
- }
-
- onPhraseChanged: reload();
- onFromChanged: reload();
-
- Component.onCompleted: {
- if (consumerKey === "" || consumerSecret == "") {
- bearerToken = encodeURIComponent(Helper.demoToken())
- return;
- }
-
- var authReq = new XMLHttpRequest;
- authReq.open("POST", "https://api.twitter.com/oauth2/token");
- authReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
- authReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(consumerKey + ":" + consumerSecret));
- authReq.onreadystatechange = function() {
- if (authReq.readyState === XMLHttpRequest.DONE) {
- var jsonResponse = JSON.parse(authReq.responseText);
- if (jsonResponse.errors !== undefined)
- console.log("Authentication error: " + jsonResponse.errors[0].message)
- else
- bearerToken = jsonResponse.access_token;
- }
- }
- authReq.send("grant_type=client_credentials");
- }
-
-}
diff --git a/examples/quick/demos/tweetsearch/content/resources/anonymous.png b/examples/quick/demos/tweetsearch/content/resources/anonymous.png
deleted file mode 100644
index 88fba26e90..0000000000
--- a/examples/quick/demos/tweetsearch/content/resources/anonymous.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/content/resources/bird-anim-sprites.png b/examples/quick/demos/tweetsearch/content/resources/bird-anim-sprites.png
deleted file mode 100644
index 4e8d7e6116..0000000000
--- a/examples/quick/demos/tweetsearch/content/resources/bird-anim-sprites.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/content/resources/icon-clear.png b/examples/quick/demos/tweetsearch/content/resources/icon-clear.png
deleted file mode 100644
index 75672f64c7..0000000000
--- a/examples/quick/demos/tweetsearch/content/resources/icon-clear.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/content/resources/icon-loading.png b/examples/quick/demos/tweetsearch/content/resources/icon-loading.png
deleted file mode 100644
index 8dbff8b70f..0000000000
--- a/examples/quick/demos/tweetsearch/content/resources/icon-loading.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/content/resources/icon-refresh.png b/examples/quick/demos/tweetsearch/content/resources/icon-refresh.png
deleted file mode 100644
index b639a638fe..0000000000
--- a/examples/quick/demos/tweetsearch/content/resources/icon-refresh.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/content/resources/icon-search.png b/examples/quick/demos/tweetsearch/content/resources/icon-search.png
deleted file mode 100644
index e41935a6c1..0000000000
--- a/examples/quick/demos/tweetsearch/content/resources/icon-search.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/content/tweetsearch.js b/examples/quick/demos/tweetsearch/content/tweetsearch.js
deleted file mode 100644
index 42a76c99fc..0000000000
--- a/examples/quick/demos/tweetsearch/content/tweetsearch.js
+++ /dev/null
@@ -1,62 +0,0 @@
-.pragma library
-
-function formatDate(date)
-{
- var da = new Date(date)
- return da.toDateString()
-}
-
-function demoToken()
-{
- var a = new Array(22).join('A')
- return a + String.fromCharCode(0x44, 0x69, 0x4a, 0x52, 0x51, 0x41, 0x41, 0x41, 0x41,
- 0x41, 0x41, 0x74, 0x2b, 0x72, 0x6a, 0x6c, 0x2b, 0x71,
- 0x6d, 0x7a, 0x30, 0x72, 0x63, 0x79, 0x2b, 0x42, 0x62,
- 0x75, 0x58, 0x42, 0x42, 0x73, 0x72, 0x55, 0x48, 0x47,
- 0x45, 0x67, 0x3d, 0x71, 0x30, 0x45, 0x4b, 0x32, 0x61,
- 0x57, 0x71, 0x51, 0x4d, 0x62, 0x31, 0x35, 0x67, 0x43,
- 0x5a, 0x4e, 0x77, 0x5a, 0x6f, 0x39, 0x79, 0x71, 0x61,
- 0x65, 0x30, 0x68, 0x70, 0x65, 0x32, 0x46, 0x44, 0x73,
- 0x53, 0x39, 0x32, 0x57, 0x41, 0x75, 0x30, 0x67)
-}
-
-function linkForEntity(entity)
-{
- return (entity.url ? entity.url :
- (entity.screen_name ? 'https://twitter.com/' + entity.screen_name :
- 'https://twitter.com/search?q=%23' + entity.text))
-}
-
-function textForEntity(entity)
-{
- return (entity.display_url ? entity.display_url :
- (entity.screen_name ? entity.screen_name : entity.text))
-}
-
-function insertLinks(text, entities)
-{
- if (typeof text !== 'string')
- return "";
-
- if (!entities)
- return text;
-
- // Add all links (urls, usernames and hashtags) to an array and sort them in
- // descending order of appearance in text
- var links = []
- if (entities.urls)
- links = entities.urls.concat(entities.hashtags, entities.user_mentions)
- else if (entities.url)
- links = entities.url.urls
-
- links.sort(function(a, b) { return b.indices[0] - a.indices[0] })
-
- for (var i = 0; i < links.length; i++) {
- var offset = links[i].url ? 0 : 1
- text = text.substring(0, links[i].indices[0] + offset) +
- '<a href=\"' + linkForEntity(links[i]) + '\">' +
- textForEntity(links[i]) + '</a>' +
- text.substring(links[i].indices[1])
- }
- return text.replace(/\n/g, '<br>');
-}
diff --git a/examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-1.png b/examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-1.png
deleted file mode 100644
index 930ee39929..0000000000
--- a/examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-1.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-2.png b/examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-2.png
deleted file mode 100644
index 9eff191a47..0000000000
--- a/examples/quick/demos/tweetsearch/doc/images/qtquick-demo-tweetsearch-med-2.png
+++ /dev/null
Binary files differ
diff --git a/examples/quick/demos/tweetsearch/doc/src/tweetsearch.qdoc b/examples/quick/demos/tweetsearch/doc/src/tweetsearch.qdoc
deleted file mode 100644
index 4145ccfc14..0000000000
--- a/examples/quick/demos/tweetsearch/doc/src/tweetsearch.qdoc
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \title Qt Quick Demo - Tweet Search
- \ingroup qtquickdemos
- \example demos/tweetsearch
- \brief A Twitter search client with 3D effects.
- \image qtquick-demo-tweetsearch-med-1.png
- \image qtquick-demo-tweetsearch-med-2.png
-
- \e{Tweet Search} is a QML application that searches items posted to Twitter
- service using a number of query parameters. Search can be done for tweets
- from a specified user, a hashtag, or a search phrase.
-
- The search result is a list of items showing the contents of the
- tweet as well as the name and image of the user who posted it.
- Hashtags, names and links in the content are clickable. Clicking
- on the image will flip the item to reveal more information.
-
- \include examples-run.qdocinc
-
- Tweet Search uses Twitter API v1.1 for running seaches.
-
- \section1 Request Authentication
-
- Each request must be authenticated on behalf of the application.
- For demonstration purposes, the application uses a hard-coded
- token for identifying itself to the Twitter service. However, this
- token is subject to rate limits for the number of requests as well
- as possible expiration.
-
- If you are having authentication or rate limit problems running the
- demo, obtain a set of application-specific tokens (consumer
- key and consumer secret) by registering a new application on
- \l{https://dev.twitter.com/apps}.
-
- Type in the two token values in \e {TweetsModel.qml}:
-
- \snippet demos/tweetsearch/content/TweetsModel.qml auth tokens
-
- Rebuild and run the demo.
-
- \section1 JSON Parsing
-
- Search results are returned in JSON (JavaScript Object Notation)
- format. \c TweetsModel uses an \l XMLHTTPRequest object to send
- an HTTP GET request, and calls JSON.parse() on the returned text
- string to convert it to a JavaScript object. Each object
- representing a tweet is then added to a \l ListModel:
-
- \snippet demos/tweetsearch/content/TweetsModel.qml requesting
-
- \sa {QML Applications}
-*/
diff --git a/examples/quick/demos/tweetsearch/main.cpp b/examples/quick/demos/tweetsearch/main.cpp
deleted file mode 100644
index fe612eaa1e..0000000000
--- a/examples/quick/demos/tweetsearch/main.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "../../shared/shared.h"
-DECLARATIVE_EXAMPLE_MAIN(demos/tweetsearch/tweetsearch)
diff --git a/examples/quick/demos/tweetsearch/tweetsearch.pro b/examples/quick/demos/tweetsearch/tweetsearch.pro
deleted file mode 100644
index 27c34bac5d..0000000000
--- a/examples/quick/demos/tweetsearch/tweetsearch.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-TEMPLATE = app
-
-QT += quick qml
-SOURCES += main.cpp
-RESOURCES += tweetsearch.qrc
-
-OTHER_FILES = tweetsearch.qml \
- content/*.qml \
- content/*.js \
- content/resources/*
-
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/tweetsearch
-INSTALLS += target
diff --git a/examples/quick/demos/tweetsearch/tweetsearch.qml b/examples/quick/demos/tweetsearch/tweetsearch.qml
deleted file mode 100644
index 40e258d79e..0000000000
--- a/examples/quick/demos/tweetsearch/tweetsearch.qml
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import "content"
-import "content/tweetsearch.js" as Helper
-
-Rectangle {
- id: main
- width: 320
- height: 480
- color: "#d6d6d6"
-
- property int inAnimDur: 250
- property int counter: 0
- property alias isLoading: tweetsModel.isLoading
- property var idx
- property var ids
-
- Component.onCompleted: ids = new Array()
-
- function idInModel(id)
- {
- for (var j = 0; j < ids.length; j++)
- if (ids[j] === id)
- return 1
- return 0
- }
-
- TweetsModel {
- id: tweetsModel
- onIsLoaded: {
- console.debug("Reload")
- idx = new Array()
- for (var i = 0; i < tweetsModel.model.count; i++) {
- var id = tweetsModel.model.get(i).id
- if (!idInModel(id))
- idx.push(i)
- }
- console.debug(idx.length + " new tweets")
- main.counter = idx.length
- }
- }
-
- Timer {
- id: timer
- interval: 500; running: main.counter; repeat: true
- onTriggered: {
- main.counter--;
- var id = tweetsModel.model.get(idx[main.counter]).id
- var item = tweetsModel.model.get(main.counter)
- mainListView.add( { "statusText": Helper.insertLinks(item.text, item.entities),
- "twitterName": item.user.screen_name,
- "name" : item.user.name,
- "userImage": item.user.profile_image_url,
- "source": item.source,
- "id": id,
- "uri": Helper.insertLinks(item.user.url, item.user.entities),
- "published": item.created_at } );
- ids.push(id)
- }
- }
-
- ListView {
- id: mainListView
- anchors.fill: parent
- delegate: TweetDelegate { }
- model: ListModel { id: finalModel }
-
- add: Transition {
- NumberAnimation { property: "hm"; from: 0; to: 1.0; duration: 300; easing.type: Easing.OutQuad }
- PropertyAction { property: "appear"; value: 250 }
- }
-
- onDragEnded: if (header.refresh) { tweetsModel.reload() }
-
- ListHeader {
- id: header
- y: -mainListView.contentY - height
- }
-
- footer: ListFooter { }
-
- function clear() {
- ids = new Array()
- model.clear()
- }
-
- function add(obj) {
- model.insert(0, obj)
- }
-
- signal autoSearch(string type, string str) // To communicate with Footer instance
- }
-}
diff --git a/examples/quick/demos/tweetsearch/tweetsearch.qmlproject b/examples/quick/demos/tweetsearch/tweetsearch.qmlproject
deleted file mode 100644
index 5a0f31117b..0000000000
--- a/examples/quick/demos/tweetsearch/tweetsearch.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.1
-
-Project {
- mainFile: "tweetsearch.qml"
-
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
-}
diff --git a/examples/quick/demos/tweetsearch/tweetsearch.qrc b/examples/quick/demos/tweetsearch/tweetsearch.qrc
deleted file mode 100644
index b23c3c5537..0000000000
--- a/examples/quick/demos/tweetsearch/tweetsearch.qrc
+++ /dev/null
@@ -1,19 +0,0 @@
-<RCC>
- <qresource prefix="/demos/tweetsearch">
- <file>tweetsearch.qml</file>
- <file>content/FlipBar.qml</file>
- <file>content/LineInput.qml</file>
- <file>content/ListFooter.qml</file>
- <file>content/ListHeader.qml</file>
- <file>content/SearchDelegate.qml</file>
- <file>content/TweetDelegate.qml</file>
- <file>content/tweetsearch.js</file>
- <file>content/TweetsModel.qml</file>
- <file>content/resources/anonymous.png</file>
- <file>content/resources/bird-anim-sprites.png</file>
- <file>content/resources/icon-clear.png</file>
- <file>content/resources/icon-loading.png</file>
- <file>content/resources/icon-refresh.png</file>
- <file>content/resources/icon-search.png</file>
- </qresource>
-</RCC>
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index ef51d98d44..deef437046 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -10,6 +10,7 @@ SUBDIRS = quick-accessibility \
localstorage \
models \
views \
+ tableview \
mousearea \
positioners \
righttoleft \
@@ -24,8 +25,7 @@ SUBDIRS = quick-accessibility \
imageresponseprovider \
window \
particles \
- shapes \
- demos
+ shapes
#OpenGL Support Required
qtConfig(opengl(es1|es2)?) {
diff --git a/examples/quick/tableview/pixelator/doc/images/qt-pixelator.png b/examples/quick/tableview/pixelator/doc/images/qt-pixelator.png
new file mode 100644
index 0000000000..a6c4a3b40b
--- /dev/null
+++ b/examples/quick/tableview/pixelator/doc/images/qt-pixelator.png
Binary files differ
diff --git a/examples/quick/tableview/pixelator/doc/src/pixelator.qdoc b/examples/quick/tableview/pixelator/doc/src/pixelator.qdoc
new file mode 100644
index 0000000000..4f8d519060
--- /dev/null
+++ b/examples/quick/tableview/pixelator/doc/src/pixelator.qdoc
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \title Qt Quick TableViews examples - Pixelator
+ \example pixelator
+ \brief The Pixelator example shows how a QML TableView and a delegate
+ can be used for custom table models.
+
+ \image qt-pixelator.png
+ \ingroup qtquickexamples
+
+ \include examples-run.qdocinc
+
+ \snippet pixelator/imagemodel.h model
+
+ We only require a simple, read-only table model. Thus, we need to implement
+ functions to indicate the dimensions of the image and supply data to the
+ TableView.
+ We use the \l{Qt property system}{Qt Property System} and a source property
+ as \c QString to set the path of the image.
+
+ \snippet pixelator/imagemodel.cpp setsource
+
+ Here we load the image when the source path is set.
+ When the source path has changed, we need to call \c beginResetModel() before.
+ After the image has been loaded, we need to call \c endResetModel().
+
+ \snippet pixelator/imagemodel.cpp rowcolcount
+
+ The row and column count is set to image height and width, respectively.
+
+ \snippet pixelator/imagemodel.cpp data
+
+ This overloaded function allows us to access the pixel data from the image.
+ When we call this function with the display role, we return the pixel's
+ gray value.
+
+ \snippet pixelator/main.cpp registertype
+
+ We need to register our model in the QML type system to be able to use it
+ from the QML side.
+
+ \snippet pixelator/main.qml pixelcomponent
+
+ Each pixel in the \c TableView is displayed via a delegate component.
+ It contains an item that has an implicit height and width defining the
+ cell size of the table.
+ It also has a property for the gray value of the pixel that is retrieved
+ from the model.
+
+ \snippet pixelator/main.qml rectshape
+
+ Inside the \c Item, there is a rounded \c Rectangle with the size and
+ radius according to the pixel's gray value.
+
+ \snippet pixelator/main.qml interaction
+
+ For a little bit of interaction, we place a \c MouseArea inside the \c Item
+ and change the Rectangle's color on mouse over.
+
+ \snippet pixelator/main.qml animation
+
+ The \c Rectangle also has a short color animation to fade between the
+ colors when it is changed.
+
+ \snippet pixelator/main.qml tableview
+
+ The \c TableView spans over the whole window and has an instance of our
+ custom \c ImageModel attached.
+
+*/
diff --git a/examples/quick/demos/rssnews/content/CategoryDelegate.qml b/examples/quick/tableview/pixelator/imagemodel.cpp
index c76bc78aca..827204bc06 100644
--- a/examples/quick/demos/rssnews/content/CategoryDelegate.qml
+++ b/examples/quick/tableview/pixelator/imagemodel.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,52 +48,61 @@
**
****************************************************************************/
-import QtQuick 2.2
+#include "imagemodel.h"
-Rectangle {
- id: delegate
+ImageModel::ImageModel(QObject *parent)
+ : QAbstractTableModel(parent)
+{
+}
- property bool selected: ListView.isCurrentItem
- property real itemSize
- width: itemSize
- height: itemSize
+QString ImageModel::source() const
+{
+ return m_source;
+}
- Image {
- anchors.centerIn: parent
- source: image
- }
+//! [setsource]
+void ImageModel::setSource(const QString &source)
+{
+ if (m_source == source)
+ return;
- Text {
- id: titleText
+ beginResetModel();
+ m_source = source;
+ m_image.load(m_source);
+ endResetModel();
+}
+//! [setsource]
- anchors {
- left: parent.left; leftMargin: 20
- right: parent.right; rightMargin: 20
- top: parent.top; topMargin: 20
- }
+//! [rowcolcount]
+int ImageModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_image.height();
+}
+
+int ImageModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_image.width();
+}
+//! [rowcolcount]
- font { pixelSize: 18; bold: true }
- text: name
- color: selected ? "#ffffff" : "#ebebdd"
- scale: selected ? 1.15 : 1.0
- Behavior on color { ColorAnimation { duration: 150 } }
- Behavior on scale { PropertyAnimation { duration: 300 } }
- }
- BusyIndicator {
- scale: 0.8
- visible: delegate.ListView.isCurrentItem && window.loading
- anchors.centerIn: parent
- }
+//! [data]
+QVariant ImageModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+ return qGray(m_image.pixel(index.column(), index.row()));
+}
+//! [data]
- MouseArea {
- anchors.fill: delegate
- onClicked: {
- delegate.ListView.view.currentIndex = index
- if (window.currentFeed == feed)
- feedModel.reload()
- else
- window.currentFeed = feed
- }
- }
+QVariant ImageModel::headerData(int /* section */, Qt::Orientation /* orientation */,
+ int role) const
+{
+ if (role == Qt::SizeHintRole)
+ return QSize(1, 1);
+ return QVariant();
}
diff --git a/examples/quick/demos/samegame/content/Settings.qml b/examples/quick/tableview/pixelator/imagemodel.h
index 2892198b27..bf0ec90da4 100644
--- a/examples/quick/demos/samegame/content/Settings.qml
+++ b/examples/quick/tableview/pixelator/imagemodel.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,23 +48,38 @@
**
****************************************************************************/
-pragma Singleton
-import QtQml 2.0
+#ifndef IMAGEMODEL_H
+#define IMAGEMODEL_H
-QtObject {
- property int screenHeight: 480
- property int screenWidth: 320
+#include <QAbstractTableModel>
+#include <QImage>
- property int menuDelay: 500
+//! [model]
+class ImageModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+public:
+ ImageModel(QObject *parent = nullptr);
- property int headerHeight: 20 // 70 on BB10
- property int footerHeight: 44 // 100 on BB10
+ QString source() const;
+ void setSource(const QString &source);
- property int fontPixelSize: 14 // 55 on BB10
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- property int blockSize: 32 // 64 on BB10
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- property int toolButtonHeight: 32 // 64 on BB10
+ QVariant headerData(int /* section */, Qt::Orientation /* orientation */,
+ int role) const override;
- property int menuButtonSpacing: 0 // 15 on BB10
-}
+signals:
+ void sourceChanged();
+
+private:
+ QString m_source;
+ QImage m_image;
+};
+//! [model]
+
+#endif // IMAGEMODEL_H
diff --git a/examples/quick/demos/photoviewer/main.cpp b/examples/quick/tableview/pixelator/main.cpp
index a269a61dcb..c57039556a 100644
--- a/examples/quick/demos/photoviewer/main.cpp
+++ b/examples/quick/tableview/pixelator/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
@@ -50,19 +50,22 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
-#include <QTranslator>
-#include <QDebug>
+
+#include "imagemodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
- QTranslator qtTranslator;
- qtTranslator.load("qml_" + QLocale::system().name(), ":/i18n/");
- app.installTranslator(&qtTranslator);
-
QQmlApplicationEngine engine;
- engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
+
+ //! [registertype]
+ qmlRegisterType<ImageModel>("ImageModel", 1, 0, "ImageModel");
+ //! [registertype]
+
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+ if (engine.rootObjects().isEmpty())
+ return -1;
return app.exec();
}
diff --git a/examples/quick/demos/stocqt/stocqt.qml b/examples/quick/tableview/pixelator/main.qml
index 1657003e53..f471fc5c6b 100644
--- a/examples/quick/demos/stocqt/stocqt.qml
+++ b/examples/quick/tableview/pixelator/main.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,63 +48,71 @@
**
****************************************************************************/
-import QtQuick 2.0
-import QtQml.Models 2.1
-import QtQuick.Layouts 1.1
-import "./content"
+import QtQuick 2.12
-Rectangle {
- id: mainRect
- width: 1000
- height: 700
+import QtQuick.Window 2.12
+import Qt.labs.tableview 1.0
- property alias currentIndex: root.currentIndex
+import ImageModel 1.0
- ColumnLayout {
- anchors.fill: parent
+Window {
+ visible: true
+ width: 900
+ height: 900
+ title: qsTr("TableView Pixelator")
- Banner {
- id: banner
- Layout.fillWidth: true
- }
+ //! [pixelcomponent]
+ Component {
+ id: pixelDelegate
- ListView {
- id: root
- Layout.fillHeight: true
- Layout.fillWidth: true
- snapMode: ListView.SnapOneItem
- highlightRangeMode: ListView.StrictlyEnforceRange
- highlightMoveDuration: 250
- focus: false
- orientation: ListView.Horizontal
- boundsBehavior: Flickable.StopAtBounds
+ Item {
+ readonly property real gray: model.display / 255.0
+ readonly property real size: 16
- StockModel {
- id: stock
- stockId: listView.currentStockId
- stockName: listView.currentStockName
- onStockIdChanged: stock.updateStock();
- onDataReady: {
- root.currentIndex = 1
- stockView.update()
- }
- }
+ implicitWidth: size
+ implicitHeight: size
+ //! [pixelcomponent]
- model: ObjectModel {
- StockListView {
- id: listView
- width: root.width
- height: root.height
- }
+ //! [rectshape]
+ Rectangle {
+ id: rect
+ anchors.centerIn: parent
+ color: "#09102b"
+ radius: size - gray * size
+ implicitWidth: radius
+ implicitHeight: radius
+ //! [rectshape]
- StockView {
- id: stockView
- width: root.width
- height: root.height
- stocklist: listView
- stock: stock
+ //! [animation]
+ ColorAnimation on color {
+ id: colorAnimation
+ running: false
+ to: "#41cd52"
+ duration: 1500
}
+ //! [animation]
+ }
+
+ //! [interaction]
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: rect.color = "#cecfd5"
+ onExited: colorAnimation.start()
}
+ //! [interaction]
+ }
+ }
+
+ //! [tableview]
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ model: ImageModel {
+ source: ":/qt.png"
}
+
+ delegate: pixelDelegate
}
+ //! [tableview]
}
diff --git a/examples/quick/tableview/pixelator/pixelator.pro b/examples/quick/tableview/pixelator/pixelator.pro
new file mode 100644
index 0000000000..6c863cb304
--- /dev/null
+++ b/examples/quick/tableview/pixelator/pixelator.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+QT += quick qml
+HEADERS += imagemodel.h
+SOURCES += main.cpp \
+ imagemodel.cpp
+
+RESOURCES += qt.png main.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/tableview/pixelator
+INSTALLS += target
diff --git a/examples/quick/tableview/pixelator/qt.png b/examples/quick/tableview/pixelator/qt.png
new file mode 100644
index 0000000000..e3301c4a02
--- /dev/null
+++ b/examples/quick/tableview/pixelator/qt.png
Binary files differ
diff --git a/examples/quick/tableview/tableview.pro b/examples/quick/tableview/tableview.pro
new file mode 100644
index 0000000000..2bcd119c31
--- /dev/null
+++ b/examples/quick/tableview/tableview.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS += pixelator
diff --git a/examples/quick/window/window.qml b/examples/quick/window/window.qml
index a1223da866..2ee7fb6e09 100644
--- a/examples/quick/window/window.qml
+++ b/examples/quick/window/window.qml
@@ -187,7 +187,7 @@ QtObject {
anchors.margins: defaultSpacing
text: "X"
width: 30
- onClicked: testWindow.visible = false
+ onClicked: testWindow.close()
}
}
}
diff --git a/src/3rdparty/masm/assembler/AssemblerBuffer.h b/src/3rdparty/masm/assembler/AssemblerBuffer.h
index 277ec1043c..45874235b6 100644
--- a/src/3rdparty/masm/assembler/AssemblerBuffer.h
+++ b/src/3rdparty/masm/assembler/AssemblerBuffer.h
@@ -102,7 +102,7 @@ namespace JSC {
void putIntegralUnchecked(IntegralType value)
{
ASSERT(isAvailable(sizeof(IntegralType)));
- *reinterpret_cast_ptr<IntegralType*>(m_buffer + m_index) = value;
+ memcpy(m_buffer + m_index, &value, sizeof(IntegralType));
m_index += sizeof(IntegralType);
}
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h
index bfd0e402ca..75b9a5c0bd 100644
--- a/src/3rdparty/masm/assembler/LinkBuffer.h
+++ b/src/3rdparty/masm/assembler/LinkBuffer.h
@@ -350,8 +350,8 @@ inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performF
#endif
ASSERT(m_size <= INT_MAX);
- ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size));
MacroAssembler::cacheFlush(code(), m_size);
+ ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size));
}
template <typename MacroAssembler>
@@ -418,8 +418,8 @@ inline void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
this->m_completed = true;
#endif
- ExecutableAllocator::makeExecutable(code(), m_initialSize);
MacroAssembler::cacheFlush(code(), m_size);
+ ExecutableAllocator::makeExecutable(code(), m_initialSize);
}
template <typename MacroAssembler>
diff --git a/src/3rdparty/masm/assembler/X86Assembler.h b/src/3rdparty/masm/assembler/X86Assembler.h
index b71cf290f8..6fa66e0dd7 100644
--- a/src/3rdparty/masm/assembler/X86Assembler.h
+++ b/src/3rdparty/masm/assembler/X86Assembler.h
@@ -1892,9 +1892,18 @@ public:
ASSERT(to.isSet());
char* code = reinterpret_cast<char*>(m_formatter.data());
- ASSERT(!reinterpret_cast<int32_t*>(code + from.m_offset)[-1]);
+ ASSERT(!loadPossiblyUnaligned<int32_t>(code, from.m_offset, -1));
setRel32(code + from.m_offset, code + to.m_offset);
}
+
+ template<typename T>
+ T loadPossiblyUnaligned(char *ptr, size_t offset, int idx)
+ {
+ T *t_ptr = &reinterpret_cast<T*>(ptr + offset)[idx];
+ T val;
+ memcpy(&val, t_ptr, sizeof(T));
+ return val;
+ }
static void linkJump(void* code, AssemblerLabel from, void* to)
{
@@ -2095,7 +2104,14 @@ private:
static void setInt32(void* where, int32_t value)
{
- reinterpret_cast<int32_t*>(where)[-1] = value;
+ storePossiblyUnaligned<int32_t>(where, -1, value);
+ }
+
+ template <typename T>
+ static void storePossiblyUnaligned(void *where, int idx, T value)
+ {
+ T *ptr = &reinterpret_cast<T*>(where)[idx];
+ memcpy(ptr, &value, sizeof(T));
}
static void setInt8(void* where, int8_t value)
diff --git a/src/3rdparty/masm/masm.pri b/src/3rdparty/masm/masm.pri
index 7dfb24f4b8..f7cdae7421 100644
--- a/src/3rdparty/masm/masm.pri
+++ b/src/3rdparty/masm/masm.pri
@@ -125,3 +125,8 @@ QMAKE_EXTRA_COMPILERS += retgen
}
}
}
+
+linux {
+ requires(qtConfig(dlopen))
+ QMAKE_USE_PRIVATE += libdl
+}
diff --git a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
index 0c902c7172..3b2a73a39a 100644
--- a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
+++ b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
@@ -31,13 +31,82 @@
#include <cstdlib>
#include "PageAllocation.h"
+#include <dlfcn.h>
#include <errno.h>
#include <sys/mman.h>
#include <wtf/Assertions.h>
#include <wtf/UnusedParam.h>
+#if OS(LINUX)
+#include <sys/syscall.h>
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#endif
+#endif
+
+#if defined(__ANDROID__) && defined(SYS_memfd_create)
+ // On Android it's been observed that permissions of memory mappings
+ // backed by a memfd could not be changed via mprotect for no obvious
+ // reason.
+# undef SYS_memfd_create
+#endif
+
namespace WTF {
+#ifdef SYS_memfd_create
+static int memfdForUsage(size_t bytes, OSAllocator::Usage usage)
+{
+ const char *type = "unknown-usage:";
+ switch (usage) {
+ case OSAllocator::UnknownUsage:
+ break;
+ case OSAllocator::FastMallocPages:
+ type = "fastmalloc:";
+ break;
+ case OSAllocator::JSGCHeapPages:
+ type = "JSGCHeap:";
+ break;
+ case OSAllocator::JSVMStackPages:
+ type = "JSVMStack:";
+ break;
+ case OSAllocator::JSJITCodePages:
+ type = "JITCode:";
+ break;
+ }
+
+ // try to get our own library name by giving dladdr a pointer pointing to
+ // something we know to be in it (using a pointer to string data)
+ static const char *libname = [=]() {
+ Dl_info info;
+ if (dladdr(type, &info) == 0)
+ info.dli_fname = nullptr;
+ return info.dli_fname;
+ }();
+
+ char buf[PATH_MAX];
+ strcpy(buf, type);
+ if (libname)
+ strcat(buf, libname);
+ else
+ strcat(buf, "QtQml");
+
+ int fd = syscall(SYS_memfd_create, buf, MFD_CLOEXEC);
+ if (fd != -1) {
+ if (ftruncate(fd, bytes) == 0)
+ return fd;
+ }
+ close(fd);
+ return -1;
+}
+#elif OS(LINUX)
+static int memfdForUsage(size_t bytes, OSAllocator::Usage usage)
+{
+ UNUSED_PARAM(bytes);
+ UNUSED_PARAM(usage);
+ return -1;
+}
+#endif
+
void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable)
{
#if OS(QNX)
@@ -46,14 +115,18 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable,
if (result == MAP_FAILED)
CRASH();
#elif OS(LINUX)
- UNUSED_PARAM(usage);
UNUSED_PARAM(writable);
UNUSED_PARAM(executable);
+ int fd = memfdForUsage(bytes, usage);
- void* result = mmap(0, bytes, PROT_NONE, MAP_NORESERVE | MAP_PRIVATE | MAP_ANON, -1, 0);
+ void* result = mmap(0, bytes, PROT_NONE, MAP_NORESERVE | MAP_PRIVATE |
+ (fd == -1 ? MAP_ANON : 0), fd, 0);
if (result == MAP_FAILED)
CRASH();
madvise(result, bytes, MADV_DONTNEED);
+
+ if (fd != -1)
+ close(fd);
#else
void* result = reserveAndCommit(bytes, usage, writable, executable);
#if HAVE(MADV_FREE_REUSE)
@@ -83,6 +156,10 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
#if OS(DARWIN)
int fd = usage;
+#elif OS(LINUX)
+ int fd = memfdForUsage(bytes, usage);
+ if (fd != -1)
+ flags &= ~MAP_ANON;
#else
UNUSED_PARAM(usage);
int fd = -1;
@@ -126,6 +203,12 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
mmap(result, pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0);
mmap(static_cast<char*>(result) + bytes - pageSize(), pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0);
}
+
+#if OS(LINUX)
+ if (fd != -1)
+ close(fd);
+#endif
+
return result;
}
diff --git a/src/3rdparty/masm/wtf/VMTags.h b/src/3rdparty/masm/wtf/VMTags.h
index 117bc3721e..af5352e471 100644
--- a/src/3rdparty/masm/wtf/VMTags.h
+++ b/src/3rdparty/masm/wtf/VMTags.h
@@ -62,6 +62,14 @@
#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69)
#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+#elif OS(LINUX)
+
+#define VM_TAG_FOR_TCMALLOC_MEMORY 0
+#define VM_TAG_FOR_COLLECTOR_MEMORY 1
+#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY 2
+#define VM_TAG_FOR_REGISTERFILE_MEMORY 3
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY 4
+
#else // OS(DARWIN)
#define VM_TAG_FOR_TCMALLOC_MEMORY -1
diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp
index 5e8b41401f..7089fed4ad 100644
--- a/src/imports/folderlistmodel/plugin.cpp
+++ b/src/imports/folderlistmodel/plugin.cpp
@@ -42,13 +42,6 @@
#include "qquickfolderlistmodel.h"
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_Qt_labs_folderlistmodel);
-#endif
-}
-
QT_BEGIN_NAMESPACE
//![class decl]
@@ -58,7 +51,7 @@ class QmlFolderListModelPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QmlFolderListModelPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QmlFolderListModelPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.folderlistmodel"));
diff --git a/src/imports/handlers/plugin.cpp b/src/imports/handlers/plugin.cpp
index d1041d6539..a98bbad9c0 100644
--- a/src/imports/handlers/plugin.cpp
+++ b/src/imports/handlers/plugin.cpp
@@ -41,13 +41,6 @@
#include <private/qquickhandlersmodule_p.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_Qt_labs_handlers);
-#endif
-}
-
QT_BEGIN_NAMESPACE
//![class decl]
@@ -56,7 +49,7 @@ class QtQuickHandlersPlugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QtQuickHandlersPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtQuickHandlersPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.handlers"));
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index e188602277..80f493da85 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,7 +1,5 @@
TEMPLATE = subdirs
-QT_FOR_CONFIG += quick-private
-
SUBDIRS += \
builtins \
qtqml \
@@ -13,11 +11,14 @@ qtConfig(settings): SUBDIRS += settings
qtConfig(statemachine): SUBDIRS += statemachine
qtHaveModule(quick) {
+ QT_FOR_CONFIG += quick-private
+
SUBDIRS += \
handlers \
layouts \
qtquick2 \
- window
+ window \
+ tableview
qtHaveModule(testlib): SUBDIRS += testlib
qtConfig(systemsemaphore): SUBDIRS += sharedimage
diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp
index c805c9fb43..80799e8859 100644
--- a/src/imports/layouts/plugin.cpp
+++ b/src/imports/layouts/plugin.cpp
@@ -42,13 +42,6 @@
#include "qquicklinearlayout_p.h"
#include "qquickstacklayout_p.h"
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_Layouts);
-#endif
-}
-
QT_BEGIN_NAMESPACE
//![class decl]
@@ -59,7 +52,6 @@ class QtQuickLayoutsPlugin : public QQmlExtensionPlugin
public:
QtQuickLayoutsPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent)
{
- initResources();
}
void registerTypes(const char *uri) override
{
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 9cca11ac5d..af32ead571 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -61,13 +61,6 @@
#include <private/qv4jscall_p.h>
#include <private/qv4objectiterator_p.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_LocalStorage);
-#endif
-}
-
QT_BEGIN_NAMESPACE
#define V4THROW_SQL(error, desc) { \
@@ -148,13 +141,13 @@ public:
static Heap::QQmlSqlDatabaseWrapper *create(QV4::ExecutionEngine *engine)
{
- return engine->memoryManager->allocObject<QQmlSqlDatabaseWrapper>();
+ return engine->memoryManager->allocate<QQmlSqlDatabaseWrapper>();
}
~QQmlSqlDatabaseWrapper() {
}
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
};
}
@@ -244,12 +237,16 @@ static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r,
}
}
-ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
+ReturnedValue QQmlSqlDatabaseWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
+ if (!id.isArrayIndex())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
+ uint index = id.asArrayIndex();
Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>());
const QQmlSqlDatabaseWrapper *r = static_cast<const QQmlSqlDatabaseWrapper *>(m);
if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
- return Object::getIndexed(m, index, hasProperty);
+ return Object::virtualGet(m, id, receiver, hasProperty);
return qmlsqldatabase_rows_index(r, r->engine(), index, hasProperty);
}
@@ -304,7 +301,7 @@ static ReturnedValue qmlsqldatabase_executeSql(const FunctionObject *b, const Va
quint32 size = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii) {
- query.bindValue(ii, toSqlVariant(scope.engine, (v = array->getIndexed(ii))));
+ query.bindValue(ii, toSqlVariant(scope.engine, (v = array->get(ii))));
}
} else if (values->as<Object>()) {
ScopedObject object(scope, values);
@@ -330,7 +327,7 @@ static ReturnedValue qmlsqldatabase_executeSql(const FunctionObject *b, const Va
if (query.exec()) {
QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
QV4::ScopedObject p(scope, databaseData(scope.engine)->rowsProto.value());
- rows->setPrototype(p.getPointer());
+ rows->setPrototypeUnchecked(p.getPointer());
rows->d()->type = Heap::QQmlSqlDatabaseWrapper::Rows;
*rows->d()->database = db;
*rows->d()->sqlQuery = query;
@@ -404,7 +401,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(const FunctionObject *b, const
Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
- w->setPrototype(p.getPointer());
+ w->setPrototypeUnchecked(p.getPointer());
w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
*w->d()->database = db;
*w->d()->version = *r->d()->version;
@@ -456,7 +453,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(const FunctionObject *b,
Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
QV4::ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
- w->setPrototype(p.getPointer());
+ w->setPrototypeUnchecked(p.getPointer());
w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
*w->d()->database = db;
*w->d()->version = *r->d()->version;
@@ -780,7 +777,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
QV4::ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
- db->setPrototype(p.getPointer());
+ db->setPrototypeUnchecked(p.getPointer());
*db->d()->database = database;
*db->d()->version = version;
@@ -814,7 +811,6 @@ class QQmlLocalStoragePlugin : public QQmlExtensionPlugin
public:
QQmlLocalStoragePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent)
{
- initResources();
}
void registerTypes(const char *uri) override
{
diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp
index 83f8597408..49e94c13aa 100644
--- a/src/imports/models/plugin.cpp
+++ b/src/imports/models/plugin.cpp
@@ -42,13 +42,6 @@
#include <private/qqmlmodelsmodule_p.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQml_Models_2);
-#endif
-}
-
QT_BEGIN_NAMESPACE
/*!
@@ -78,7 +71,7 @@ class QtQmlModelsPlugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QtQmlModelsPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtQmlModelsPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQml.Models"));
diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp
index d548f26599..e2b8712599 100644
--- a/src/imports/particles/plugin.cpp
+++ b/src/imports/particles/plugin.cpp
@@ -42,13 +42,6 @@
#include <private/qquickparticlesmodule_p.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_Particles_2);
-#endif
-}
-
QT_BEGIN_NAMESPACE
//![class decl]
@@ -57,7 +50,7 @@ class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QtQuick2ParticlesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtQuick2ParticlesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Particles"));
diff --git a/src/imports/qtqml/plugins.qmltypes b/src/imports/qtqml/plugins.qmltypes
index 82333627a0..caa04b04bb 100644
--- a/src/imports/qtqml/plugins.qmltypes
+++ b/src/imports/qtqml/plugins.qmltypes
@@ -198,9 +198,20 @@ Module {
Component {
name: "QQmlLoggingCategory"
prototype: "QObject"
- exports: ["QtQml/LoggingCategory 2.8"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQml/LoggingCategory 2.12", "QtQml/LoggingCategory 2.8"]
+ exportMetaObjectRevisions: [1, 0]
+ Enum {
+ name: "DefaultLogLevel"
+ values: {
+ "Debug": 0,
+ "Info": 4,
+ "Warning": 1,
+ "Critical": 2,
+ "Fatal": 3
+ }
+ }
Property { name: "name"; type: "string" }
+ Property { name: "defaultLogLevel"; revision: 1; type: "DefaultLogLevel" }
}
Component {
name: "QQmlTimer"
diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp
index 147f01e81b..d73a8b3688 100644
--- a/src/imports/qtquick2/plugin.cpp
+++ b/src/imports/qtquick2/plugin.cpp
@@ -41,13 +41,6 @@
#include <private/qtquick2_p.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_2);
-#endif
-}
-
QT_BEGIN_NAMESPACE
//![class decl]
@@ -56,7 +49,7 @@ class QtQuick2Plugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QtQuick2Plugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtQuick2Plugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick"));
diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp
index 65de78a2f1..3ac0ad4653 100644
--- a/src/imports/settings/plugin.cpp
+++ b/src/imports/settings/plugin.cpp
@@ -42,13 +42,6 @@
#include "qqmlsettings_p.h"
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_Qt_labs_settings);
-#endif
-}
-
QT_BEGIN_NAMESPACE
class QmlSettingsPlugin : public QQmlExtensionPlugin
@@ -57,11 +50,12 @@ class QmlSettingsPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QmlSettingsPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QmlSettingsPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QByteArray(uri) == QByteArray("Qt.labs.settings"));
qmlRegisterType<QQmlSettings>(uri, 1, 0, "Settings");
+ qmlRegisterType<QQmlSettings,1>(uri, 1, 1, "Settings");
}
};
diff --git a/src/imports/settings/plugins.qmltypes b/src/imports/settings/plugins.qmltypes
index 40d8746525..ae3de3dfff 100644
--- a/src/imports/settings/plugins.qmltypes
+++ b/src/imports/settings/plugins.qmltypes
@@ -4,15 +4,20 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -noforceqtquick Qt.labs.settings 1.0'
+// 'qmlplugindump -nonrelocatable -noforceqtquick Qt.labs.settings 1.1'
Module {
dependencies: []
Component {
name: "QQmlSettings"
prototype: "QObject"
- exports: ["Qt.labs.settings/Settings 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "Qt.labs.settings/Settings 1.0",
+ "Qt.labs.settings/Settings 1.1"
+ ]
+ exportMetaObjectRevisions: [0, 1]
Property { name: "category"; type: "string" }
+ Property { name: "fileName"; revision: 1; type: "string" }
}
}
+
diff --git a/src/imports/settings/qqmlsettings.cpp b/src/imports/settings/qqmlsettings.cpp
index 2271774643..6b3904909a 100644
--- a/src/imports/settings/qqmlsettings.cpp
+++ b/src/imports/settings/qqmlsettings.cpp
@@ -156,7 +156,8 @@ QT_BEGIN_NAMESPACE
Application specific settings are identified by providing application
\l {QCoreApplication::applicationName}{name},
\l {QCoreApplication::organizationName}{organization} and
- \l {QCoreApplication::organizationDomain}{domain}.
+ \l {QCoreApplication::organizationDomain}{domain}, or by specifying
+ \l fileName.
\code
#include <QGuiApplication>
@@ -258,6 +259,7 @@ public:
int timerId = 0;
bool initialized = false;
QString category;
+ QString fileName;
mutable QPointer<QSettings> settings;
QHash<const char *, QVariant> changedProperties;
};
@@ -268,7 +270,7 @@ QSettings *QQmlSettingsPrivate::instance() const
{
if (!settings) {
QQmlSettings *q = const_cast<QQmlSettings*>(q_func());
- settings = new QSettings(q);
+ settings = fileName.isEmpty() ? new QSettings(q) : new QSettings(fileName, QSettings::IniFormat, q);
if (!category.isEmpty())
settings->beginGroup(category);
if (initialized)
@@ -299,6 +301,11 @@ void QQmlSettingsPrivate::load()
const QMetaObject *mo = q->metaObject();
const int offset = mo->propertyOffset();
const int count = mo->propertyCount();
+
+ // don't save built-in properties if there aren't any qml properties
+ if (offset == 1)
+ return;
+
for (int i = offset; i < count; ++i) {
QMetaProperty property = mo->property(i);
@@ -398,6 +405,66 @@ void QQmlSettings::setCategory(const QString &category)
}
}
+/*!
+ \qmlproperty string Settings::fileName
+
+ This property holds the path to the settings file. If the file doesn't
+ already exist, it is created.
+
+ \sa QSettings::fileName, QSettings::IniFormat
+
+ \since Qt.labs.settings 1.1
+*/
+QString QQmlSettings::fileName() const
+{
+ Q_D(const QQmlSettings);
+ return d->fileName;
+}
+
+void QQmlSettings::setFileName(const QString &fileName)
+{
+ Q_D(QQmlSettings);
+ if (d->fileName != fileName) {
+ d->reset();
+ d->fileName = fileName;
+ if (d->initialized)
+ d->load();
+ }
+}
+
+/*!
+ \qmlmethod var Settings::value(string key, var defaultValue)
+
+ Returns the value for setting \a key. If the setting doesn't exist,
+ returns \a defaultValue.
+
+ \sa QSettings::value
+
+ \since Qt.labs.settings 1.1
+*/
+QVariant QQmlSettings::value(const QString &key, const QVariant &defaultValue) const
+{
+ Q_D(const QQmlSettings);
+ return d->instance()->value(key, defaultValue);
+}
+
+/*!
+ \qmlmethod Settings::setValue(string key, var value)
+
+ Sets the value of setting key to value. If the key already exists,
+ the previous value is overwritten.
+
+ \sa QSettings::setValue
+
+ \since Qt.labs.settings 1.1
+*/
+void QQmlSettings::setValue(const QString &key, const QVariant &value)
+{
+ Q_D(const QQmlSettings);
+ d->instance()->setValue(key, value);
+ qCDebug(lcSettings) << "QQmlSettings: setValue" << key << ":" << value;
+}
+
void QQmlSettings::classBegin()
{
}
diff --git a/src/imports/settings/qqmlsettings_p.h b/src/imports/settings/qqmlsettings_p.h
index ce942d7564..f73e595557 100644
--- a/src/imports/settings/qqmlsettings_p.h
+++ b/src/imports/settings/qqmlsettings_p.h
@@ -65,6 +65,7 @@ class QQmlSettings : public QObject, public QQmlParserStatus
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QString category READ category WRITE setCategory FINAL)
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL REVISION 1)
public:
explicit QQmlSettings(QObject *parent = 0);
@@ -73,6 +74,12 @@ public:
QString category() const;
void setCategory(const QString &category);
+ QString fileName() const;
+ void setFileName(const QString &fileName);
+
+ Q_REVISION(1) Q_INVOKABLE QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+ Q_REVISION(1) Q_INVOKABLE void setValue(const QString &key, const QVariant &value);
+
protected:
void timerEvent(QTimerEvent *event) override;
diff --git a/src/imports/settings/settings.pro b/src/imports/settings/settings.pro
index 29229f59cb..816a6a9fef 100644
--- a/src/imports/settings/settings.pro
+++ b/src/imports/settings/settings.pro
@@ -1,7 +1,7 @@
CXX_MODULE = qml
TARGET = qmlsettingsplugin
TARGETPATH = Qt/labs/settings
-IMPORT_VERSION = 1.0
+IMPORT_VERSION = 1.1
QT = core qml
diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp
index f0e66479b6..e3a9017681 100644
--- a/src/imports/shapes/plugin.cpp
+++ b/src/imports/shapes/plugin.cpp
@@ -39,16 +39,7 @@
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
-
-#include "qquickshape_p.h"
-
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_Shapes);
-#endif
- Q_INIT_RESOURCE(qtquickshapesplugin);
-}
+#include <QtQuickShapes/private/qquickshape_p.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +49,11 @@ class QmlShapesPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QmlShapesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QmlShapesPlugin(QObject *parent = nullptr)
+ : QQmlExtensionPlugin(parent)
+ {
+ }
+
void registerTypes(const char *uri) override
{
Q_ASSERT(QByteArray(uri) == QByteArray("QtQuick.Shapes"));
diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro
index 4d6e9508af..71bb456866 100644
--- a/src/imports/shapes/shapes.pro
+++ b/src/imports/shapes/shapes.pro
@@ -3,31 +3,9 @@ TARGET = qmlshapesplugin
TARGETPATH = QtQuick/Shapes
IMPORT_VERSION = 1.11
-QT = core gui-private qml quick-private
-
-HEADERS += \
- qquickshape_p.h \
- qquickshape_p_p.h \
- qquickshapegenericrenderer_p.h \
- qquickshapesoftwarerenderer_p.h
+QT = core gui-private qml quick-private quickshapes-private
SOURCES += \
plugin.cpp \
- qquickshape.cpp \
- qquickshapegenericrenderer.cpp \
- qquickshapesoftwarerenderer.cpp
-
-qtConfig(opengl) {
- HEADERS += \
- qquicknvprfunctions_p.h \
- qquicknvprfunctions_p_p.h \
- qquickshapenvprrenderer_p.h
-
- SOURCES += \
- qquicknvprfunctions.cpp \
- qquickshapenvprrenderer.cpp
-}
-
-RESOURCES += qtquickshapesplugin.qrc
load(qml_plugin)
diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp
index 93ced6e280..bf7499b31a 100644
--- a/src/imports/statemachine/plugin.cpp
+++ b/src/imports/statemachine/plugin.cpp
@@ -47,13 +47,6 @@
#include <QQmlExtensionPlugin>
#include <qqml.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQml_StateMachine);
-#endif
-}
-
QT_BEGIN_NAMESPACE
class QtQmlStateMachinePlugin : public QQmlExtensionPlugin
@@ -62,7 +55,7 @@ class QtQmlStateMachinePlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QtQmlStateMachinePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtQmlStateMachinePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
qmlRegisterType<State>(uri, 1, 0, "State");
diff --git a/src/imports/tableview/plugin.cpp b/src/imports/tableview/plugin.cpp
new file mode 100644
index 0000000000..3bd9b72a8d
--- /dev/null
+++ b/src/imports/tableview/plugin.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQuick/private/qquicktableview_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//![class decl]
+class QtQuickTableViewPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+public:
+ QtQuickTableViewPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent)
+ {}
+
+ void registerTypes(const char *uri) override
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.tableview"));
+ qmlRegisterType<QQuickTableView>(uri, 1, 0, "TableView");
+ }
+};
+//![class decl]
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/tableview/plugins.qmltypes b/src/imports/tableview/plugins.qmltypes
new file mode 100644
index 0000000000..8510b698a9
--- /dev/null
+++ b/src/imports/tableview/plugins.qmltypes
@@ -0,0 +1,33 @@
+import QtQuick.tooling 1.2
+
+// 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 Qt.labs.tableview 1.0'
+
+Module {
+ dependencies: ["QtQuick 2.8"]
+ Component {
+ name: "QQuickTableView"
+ defaultProperty: "flickableData"
+ prototype: "QQuickFlickable"
+ exports: ["Qt.labs.tableview/TableView 1.0"]
+ exportMetaObjectRevisions: [0]
+ attachedType: "QQuickTableViewAttached"
+ Property { name: "rows"; type: "int"; isReadonly: true }
+ Property { name: "columns"; type: "int"; isReadonly: true }
+ Property { name: "rowSpacing"; type: "double" }
+ Property { name: "columnSpacing"; type: "double" }
+ Property { name: "cacheBuffer"; type: "int" }
+ Property { name: "model"; type: "QVariant" }
+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
+ }
+ Component {
+ name: "QQuickTableViewAttached"
+ prototype: "QObject"
+ Property { name: "tableView"; type: "QQuickTableView"; isReadonly: true; isPointer: true }
+ Property { name: "row"; type: "int"; isReadonly: true }
+ Property { name: "column"; type: "int"; isReadonly: true }
+ }
+}
diff --git a/src/imports/tableview/qmldir b/src/imports/tableview/qmldir
new file mode 100644
index 0000000000..dac976794a
--- /dev/null
+++ b/src/imports/tableview/qmldir
@@ -0,0 +1,5 @@
+module Qt.labs.tableview
+plugin tableviewplugin
+classname QtQuickTableViewPlugin
+typeinfo plugins.qmltypes
+
diff --git a/src/imports/tableview/tableview.pro b/src/imports/tableview/tableview.pro
new file mode 100644
index 0000000000..97ced65e6b
--- /dev/null
+++ b/src/imports/tableview/tableview.pro
@@ -0,0 +1,10 @@
+CXX_MODULE = qml
+TARGET = tableviewplugin
+TARGETPATH = Qt/labs/tableview
+IMPORT_VERSION = 1.0
+
+SOURCES += $$PWD/plugin.cpp
+
+QT += quick-private qml-private
+
+load(qml_plugin)
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 77b644d3f2..535e29ee70 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -1084,6 +1084,24 @@ Item {
does not occur, then the test will fail. Similar to
\c{QTest::ignoreMessage(QtWarningMsg, message)} in C++.
+ Since Qt 5.12, \a message can be either a string, or a regular
+ expression providing a pattern of messages to ignore.
+
+ For example, the following snippet will ignore a string warning message:
+ \qml
+ ignoreWarning("Something sort of bad happened")
+ \endqml
+
+ And the following snippet will ignore a regular expression matching a
+ number of possible warning messages:
+ \qml
+ ignoreWarning(new RegExp("[0-9]+ bad things happened"))
+ \endqml
+
+ \note Despite being a JavaScript RegExp object, it will not be
+ interpreted as such; instead, the pattern will be passed to
+ \l QRegularExpression.
+
\sa warn()
*/
function ignoreWarning(msg) {
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index 443229bee9..af15a44012 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -54,13 +54,6 @@ QML_DECLARE_TYPE(QuickTestEvent)
#include <QtDebug>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtTest);
-#endif
-}
-
QT_BEGIN_NAMESPACE
class QuickTestUtil : public QObject
@@ -150,7 +143,7 @@ class QTestQmlModule : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QTestQmlModule(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QTestQmlModule(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtTest"));
diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp
index 907eecb060..3e45730bb1 100644
--- a/src/imports/window/plugin.cpp
+++ b/src/imports/window/plugin.cpp
@@ -41,13 +41,6 @@
#include <private/qquickwindowmodule_p.h>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_Window_2);
-#endif
-}
-
QT_BEGIN_NAMESPACE
/*!
@@ -72,7 +65,7 @@ class QtQuick2WindowPlugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QtQuick2WindowPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtQuick2WindowPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Window"));
diff --git a/src/imports/xmllistmodel/plugin.cpp b/src/imports/xmllistmodel/plugin.cpp
index 82e11eeeb3..c5356b8534 100644
--- a/src/imports/xmllistmodel/plugin.cpp
+++ b/src/imports/xmllistmodel/plugin.cpp
@@ -42,13 +42,6 @@
#include "qqmlxmllistmodel_p.h"
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtQuick_XmlListModel);
-#endif
-}
-
QT_BEGIN_NAMESPACE
class QmlXmlListModelPlugin : public QQmlExtensionPlugin
@@ -57,7 +50,7 @@ class QmlXmlListModelPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- QmlXmlListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ QmlXmlListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.XmlListModel"));
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
index 773d9747f0..df0881092b 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
@@ -54,8 +54,10 @@
#include <QXmlResultItems>
#include <QXmlNodeModelIndex>
#include <QBuffer>
+#if QT_CONFIG(qml_network)
#include <QNetworkRequest>
#include <QNetworkReply>
+#endif
#include <QTimer>
#include <QMutex>
@@ -542,7 +544,10 @@ class QQuickXmlListModelPrivate : public QAbstractItemModelPrivate
public:
QQuickXmlListModelPrivate()
: isComponentComplete(true), size(0), highestRole(Qt::UserRole)
- , reply(0), status(QQuickXmlListModel::Null), progress(0.0)
+#if QT_CONFIG(qml_network)
+ , reply(0)
+#endif
+ , status(QQuickXmlListModel::Null), progress(0.0)
, queryId(-1), roleObjects(), redirectCount(0) {}
@@ -555,6 +560,7 @@ public:
emit q->statusChanged(status);
}
+#if QT_CONFIG(qml_network)
void deleteReply() {
Q_Q(QQuickXmlListModel);
if (reply) {
@@ -563,6 +569,7 @@ public:
reply = 0;
}
}
+#endif
bool isComponentComplete;
QUrl src;
@@ -574,7 +581,9 @@ public:
QStringList roleNames;
int highestRole;
+#if QT_CONFIG(qml_network)
QNetworkReply *reply;
+#endif
QQuickXmlListModel::Status status;
QString errorString;
qreal progress;
@@ -1036,10 +1045,12 @@ void QQuickXmlListModel::reload()
if (d->size < 0)
d->size = 0;
+#if QT_CONFIG(qml_network)
if (d->reply) {
d->reply->abort();
d->deleteReply();
}
+#endif
if (!d->xml.isEmpty()) {
d->queryId = QQuickXmlQueryEngine::instance(qmlEngine(this))->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache);
@@ -1050,7 +1061,19 @@ void QQuickXmlListModel::reload()
d->notifyQueryStarted(false);
QTimer::singleShot(0, this, SLOT(dataCleared()));
+ } else if (QQmlFile::isLocalFile(d->src)) {
+ QFile file(QQmlFile::urlToLocalFileOrQrc(d->src));
+ QByteArray data = file.open(QIODevice::ReadOnly) ? file.readAll() : QByteArray();
+ d->notifyQueryStarted(false);
+ if (data.isEmpty()) {
+ d->queryId = XMLLISTMODEL_CLEAR_ID;
+ QTimer::singleShot(0, this, SLOT(dataCleared()));
+ } else {
+ d->queryId = QQuickXmlQueryEngine::instance(qmlEngine(this))->doQuery(
+ d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
+ }
} else {
+#if QT_CONFIG(qml_network)
d->notifyQueryStarted(true);
QNetworkRequest req(d->src);
req.setRawHeader("Accept", "application/xml,*/*");
@@ -1058,11 +1081,17 @@ void QQuickXmlListModel::reload()
QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished()));
QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(requestProgress(qint64,qint64)));
+#else
+ d->queryId = XMLLISTMODEL_CLEAR_ID;
+ d->notifyQueryStarted(false);
+ QTimer::singleShot(0, this, SLOT(dataCleared()));
+#endif
}
}
#define XMLLISTMODEL_MAX_REDIRECT 16
+#if QT_CONFIG(qml_network)
void QQuickXmlListModel::requestFinished()
{
Q_D(QQuickXmlListModel);
@@ -1108,6 +1137,7 @@ void QQuickXmlListModel::requestFinished()
emit progressChanged(d->progress);
}
}
+#endif
void QQuickXmlListModel::requestProgress(qint64 received, qint64 total)
{
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h
index e6a0898bb9..65f1299324 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h
@@ -144,7 +144,9 @@ public Q_SLOTS:
void reload();
private Q_SLOTS:
+#if QT_CONFIG(qml_network)
void requestFinished();
+#endif
void requestProgress(qint64,qint64);
void dataCleared();
void queryCompleted(const QQuickXmlQueryResult &);
diff --git a/src/imports/xmllistmodel/xmllistmodel.pro b/src/imports/xmllistmodel/xmllistmodel.pro
index b5f559fc93..8ee9ea311f 100644
--- a/src/imports/xmllistmodel/xmllistmodel.pro
+++ b/src/imports/xmllistmodel/xmllistmodel.pro
@@ -3,7 +3,8 @@ TARGET = qmlxmllistmodelplugin
TARGETPATH = QtQuick/XmlListModel
IMPORT_VERSION = 2.$$QT_MINOR_VERSION
-QT = network xmlpatterns qml-private core-private
+QT = xmlpatterns qml-private core-private
+qtConfig(qml-network): QT += network
SOURCES += qqmlxmllistmodel.cpp plugin.cpp
HEADERS += qqmlxmllistmodel_p.h
diff --git a/src/particles/qquickcustomaffector.cpp b/src/particles/qquickcustomaffector.cpp
index 53557e1d0b..ccb00eeba2 100644
--- a/src/particles/qquickcustomaffector.cpp
+++ b/src/particles/qquickcustomaffector.cpp
@@ -154,7 +154,7 @@ void QQuickCustomAffector::affectSystem(qreal dt)
QV4::ScopedArrayObject array(scope, v4->newArrayObject(toAffect.size()));
QV4::ScopedValue v(scope);
for (int i=0; i<toAffect.size(); i++)
- array->putIndexed(i, (v = toAffect[i]->v4Value(m_system)));
+ array->put(i, (v = toAffect[i]->v4Value(m_system)));
if (dt >= simulationCutoff || dt <= simulationDelta) {
affectProperties(toAffect, dt);
diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp
index cd4cdcf3ef..5ec834a463 100644
--- a/src/particles/qquickparticleemitter.cpp
+++ b/src/particles/qquickparticleemitter.cpp
@@ -494,7 +494,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp)
QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size()));
QV4::ScopedValue v(scope);
for (int i=0; i<toEmit.size(); i++)
- array->putIndexed(i, (v = toEmit[i]->v4Value(m_system)));
+ array->put(i, (v = toEmit[i]->v4Value(m_system)));
emitParticles(QQmlV4Handle(array));//A chance for arbitrary JS changes
}
diff --git a/src/particles/qquicktrailemitter.cpp b/src/particles/qquicktrailemitter.cpp
index f0a0b297e2..ca3ebbd4ec 100644
--- a/src/particles/qquicktrailemitter.cpp
+++ b/src/particles/qquicktrailemitter.cpp
@@ -273,7 +273,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp)
QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size()));
QV4::ScopedValue v(scope);
for (int i=0; i<toEmit.size(); i++)
- array->putIndexed(i, (v = toEmit[i]->v4Value(m_system)));
+ array->put(i, (v = toEmit[i]->v4Value(m_system)));
if (isEmitFollowConnected())
emitFollowParticles(QQmlV4Handle(array), d->v4Value(m_system));//A chance for many arbitrary JS changes
diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp
index eb9d2288d6..42b30f0472 100644
--- a/src/particles/qquickv4particledata.cpp
+++ b/src/particles/qquickv4particledata.cpp
@@ -518,9 +518,9 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV4::ExecutionEngine* v4, QQuickParti
QV4::Scope scope(v4);
QV4ParticleDataDeletable *d = particleV4Data(scope.engine);
- QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QV4ParticleData>(datum, system));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocate<QV4ParticleData>(datum, system));
QV4::ScopedObject p(scope, d->proto.value());
- o->setPrototype(p);
+ o->setPrototypeUnchecked(p);
m_v4Value = o;
}
diff --git a/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
index e1d6263e36..c256501301 100644
--- a/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
@@ -106,6 +106,9 @@ class QPacketProtocolPrivate : public QObjectPrivate
public:
QPacketProtocolPrivate(QIODevice *dev);
+ bool writeToDevice(const char *bytes, qint64 size);
+ bool readFromDevice(char *buffer, qint64 size);
+
QList<qint32> sendingPackets;
QList<QByteArray> packets;
QByteArray inProgress;
@@ -143,18 +146,18 @@ void QPacketProtocol::send(const QByteArray &data)
return; // We don't send empty packets
if (data.size() > maxSize) {
- emit invalidPacket();
+ emit error();
return;
}
- qint32 sendSize = data.size() + sizeof(qint32);
+ const qint32 sendSize = data.size() + static_cast<qint32>(sizeof(qint32));
d->sendingPackets.append(sendSize);
+
qint32 sendSizeLE = qToLittleEndian(sendSize);
- qint64 writeBytes = d->dev->write((char *)&sendSizeLE, sizeof(qint32));
- Q_UNUSED(writeBytes);
- Q_ASSERT(writeBytes == sizeof(qint32));
- writeBytes = d->dev->write(data);
- Q_ASSERT(writeBytes == data.size());
+ if (!d->writeToDevice((const char *)&sendSizeLE, sizeof(qint32))
+ || !d->writeToDevice(data.data(), data.size())) {
+ emit error();
+ }
}
/*!
@@ -240,28 +243,41 @@ void QPacketProtocol::readyToRead()
// Need to get trailing data
if (-1 == d->inProgressSize) {
// We need a size header of sizeof(qint32)
- if (sizeof(qint32) > (uint)d->dev->bytesAvailable())
+ if (static_cast<qint64>(sizeof(qint32)) > d->dev->bytesAvailable())
return;
// Read size header
qint32 inProgressSizeLE;
- const qint64 read = d->dev->read((char *)&inProgressSizeLE, sizeof(qint32));
+ if (!d->readFromDevice((char *)&inProgressSizeLE, sizeof(qint32))) {
+ emit error();
+ return;
+ }
d->inProgressSize = qFromLittleEndian(inProgressSizeLE);
// Check sizing constraints
- if (read != sizeof(qint32) || d->inProgressSize < read) {
+ if (d->inProgressSize < qint32(sizeof(qint32))) {
disconnect(d->dev, &QIODevice::readyRead, this, &QPacketProtocol::readyToRead);
disconnect(d->dev, &QIODevice::aboutToClose, this, &QPacketProtocol::aboutToClose);
disconnect(d->dev, &QIODevice::bytesWritten, this, &QPacketProtocol::bytesWritten);
d->dev = nullptr;
- emit invalidPacket();
+ emit error();
return;
}
- d->inProgressSize -= read;
+ d->inProgressSize -= sizeof(qint32);
} else {
- d->inProgress.append(d->dev->read(d->inProgressSize - d->inProgress.size()));
+ const int bytesToRead = static_cast<int>(
+ qMin(d->dev->bytesAvailable(),
+ static_cast<qint64>(d->inProgressSize - d->inProgress.size())));
+
+ QByteArray toRead(bytesToRead, Qt::Uninitialized);
+ if (!d->readFromDevice(toRead.data(), toRead.length())) {
+ emit error();
+ return;
+ }
+
+ d->inProgress.append(toRead);
if (d->inProgressSize == d->inProgress.size()) {
// Packet has arrived!
d->packets.append(d->inProgress);
@@ -281,6 +297,30 @@ QPacketProtocolPrivate::QPacketProtocolPrivate(QIODevice *dev) :
{
}
+bool QPacketProtocolPrivate::writeToDevice(const char *bytes, qint64 size)
+{
+ qint64 totalWritten = 0;
+ while (totalWritten < size) {
+ const qint64 chunkSize = dev->write(bytes + totalWritten, size - totalWritten);
+ if (chunkSize < 0)
+ return false;
+ totalWritten += chunkSize;
+ }
+ return totalWritten == size;
+}
+
+bool QPacketProtocolPrivate::readFromDevice(char *buffer, qint64 size)
+{
+ qint64 totalRead = 0;
+ while (totalRead < size) {
+ const qint64 chunkSize = dev->read(buffer + totalRead, size - totalRead);
+ if (chunkSize < 0)
+ return false;
+ totalRead += chunkSize;
+ }
+ return totalRead == size;
+}
+
/*!
\fn void QPacketProtocol::readyRead()
diff --git a/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
index 35edb568aa..a478fc9996 100644
--- a/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
@@ -72,7 +72,7 @@ public:
Q_SIGNALS:
void readyRead();
- void invalidPacket();
+ void error();
private:
void aboutToClose();
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index 95e6d5704c..a437b7ccc7 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -46,6 +46,7 @@
#include <private/qv4objectiterator_p.h>
#include <private/qv4identifier_p.h>
#include <private/qv4runtime_p.h>
+#include <private/qv4identifiertable_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qqmlengine_p.h>
@@ -96,18 +97,17 @@ int QV4DataCollector::encodeScopeType(QV4::Heap::ExecutionContext::ContextType s
{
switch (scopeType) {
case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
- case QV4::Heap::ExecutionContext::Type_CatchContext:
- return 4;
+ break;
case QV4::Heap::ExecutionContext::Type_WithContext:
return 2;
case QV4::Heap::ExecutionContext::Type_CallContext:
return 1;
case QV4::Heap::ExecutionContext::Type_QmlContext:
return 3;
- default:
- return -1;
+ case QV4::Heap::ExecutionContext::Type_BlockContext:
+ return 4;
}
+ return 0;
}
QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine)
@@ -268,9 +268,9 @@ bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr)
Refs collectedRefs;
QV4::ScopedValue v(scope);
- QV4::InternalClass *ic = ctxt->internalClass();
+ QV4::Heap::InternalClass *ic = ctxt->internalClass();
for (uint i = 0; i < ic->size; ++i) {
- QString name = ic->nameMap[i]->string;
+ QString name = ic->nameMap[i].toQString();
names.append(name);
v = static_cast<QV4::Heap::CallContext *>(ctxt->d())->locals[i];
collectedRefs.append(collect(v));
@@ -394,18 +394,18 @@ QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicat
{ std::swap(*hasExceptionLoc, hadException); }
};
- // if we wouldn't do this, the putIndexed won't work.
+ // if we wouldn't do this, the put won't work.
ExceptionStateSaver resetExceptionState(engine());
QV4::Scope scope(engine());
QV4::ScopedObject array(scope, m_values.value());
if (deduplicate) {
for (Ref i = 0; i < array->getLength(); ++i) {
- if (array->getIndexed(i) == value.rawValue() && !m_specialRefs.contains(i))
+ if (array->get(i) == value.rawValue() && !m_specialRefs.contains(i))
return i;
}
}
Ref ref = array->getLength();
- array->putIndexed(ref, value);
+ array->put(ref, value);
Q_ASSERT(array->getLength() - 1 == ref);
return ref;
}
@@ -415,7 +415,7 @@ QV4::ReturnedValue QV4DataCollector::getValue(Ref ref)
QV4::Scope scope(engine());
QV4::ScopedObject array(scope, m_values.value());
Q_ASSERT(ref < array->getLength());
- return array->getIndexed(ref, nullptr);
+ return array->get(ref, nullptr);
}
// TODO: Drop this method once we don't need to support namesAsObjects anymore
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index 7950d21612..70f71de6ca 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -65,7 +65,7 @@ void JavaScriptJob::run()
QV4::Scope scope(engine);
QV4::ScopedContext ctx(scope, engine->currentStackFrame ? engine->currentContext()
- : engine->rootContext());
+ : engine->scriptContext());
QObject scopeObject;
QV4::CppStackFrame *frame = engine->currentStackFrame;
@@ -103,7 +103,7 @@ void JavaScriptJob::run()
}
}
- QV4::Script script(ctx, QV4::Compiler::EvalCode, this->script);
+ QV4::Script script(ctx, QV4::Compiler::ContextType::Eval, this->script);
if (const QV4::Function *function = frame ? frame->v4Function : engine->globalCode)
script.strictMode = function->isStrict();
diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
index b19115aa60..b98cfffb6e 100644
--- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
@@ -51,6 +51,7 @@
#include <private/qv4runtime_p.h>
#include <private/qversionedpacket_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qv4identifiertable_p.h>
#include <QtQml/qjsengine.h>
#include <QtCore/qjsonarray.h>
@@ -252,9 +253,9 @@ QV4::ReturnedValue NativeDebugger::evaluateExpression(const QString &expression)
m_runningJob = true;
QV4::ExecutionContext *ctx = m_engine->currentStackFrame ? m_engine->currentContext()
- : m_engine->rootContext();
+ : m_engine->scriptContext();
- QV4::Script script(ctx, QV4::Compiler::EvalCode, expression);
+ QV4::Script script(ctx, QV4::Compiler::ContextType::Eval, expression);
if (const QV4::Function *function = m_engine->currentStackFrame
? m_engine->currentStackFrame->v4Function : m_engine->globalCode)
script.strictMode = function->isStrict();
@@ -414,7 +415,7 @@ void Collector::collect(QJsonArray *out, const QString &parentIName, const QStri
if (isExpanded(iname)) {
QJsonArray children;
for (uint i = 0; i < n; ++i) {
- QV4::ReturnedValue v = array->getIndexed(i);
+ QV4::ReturnedValue v = array->get(i);
QV4::ScopedValue sval(scope, v);
collect(&children, iname, QString::number(i), *sval);
}
@@ -493,10 +494,10 @@ void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &a
collector.collect(&output, QString(), QStringLiteral("this"), thisObject);
QV4::Scoped<QV4::CallContext> callContext(scope, frame->callContext());
if (callContext) {
- QV4::InternalClass *ic = callContext->internalClass();
+ QV4::Heap::InternalClass *ic = callContext->internalClass();
QV4::ScopedValue v(scope);
for (uint i = 0; i < ic->size; ++i) {
- QString name = ic->nameMap[i]->string;
+ QString name = ic->nameMap[i].toQString();
v = callContext->d()->locals[i];
collector.collect(&output, QString(), name, v);
}
diff --git a/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro b/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro
new file mode 100644
index 0000000000..08686a43e3
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro
@@ -0,0 +1,29 @@
+QT += core-private qml-private packetprotocol-private network quick-private gui-private
+
+TARGET = qmldbg_preview
+
+SOURCES += \
+ $$PWD/qqmlpreviewblacklist.cpp \
+ $$PWD/qqmlpreviewfileengine.cpp \
+ $$PWD/qqmlpreviewfileloader.cpp \
+ $$PWD/qqmlpreviewhandler.cpp \
+ $$PWD/qqmlpreviewposition.cpp \
+ $$PWD/qqmlpreviewservice.cpp \
+ $$PWD/qqmlpreviewservicefactory.cpp
+
+HEADERS += \
+ $$PWD/qqmlpreviewblacklist.h \
+ $$PWD/qqmlpreviewfileengine.h \
+ $$PWD/qqmlpreviewfileloader.h \
+ $$PWD/qqmlpreviewhandler.h \
+ $$PWD/qqmlpreviewposition.h \
+ $$PWD/qqmlpreviewservice.h \
+ $$PWD/qqmlpreviewservicefactory.h
+
+OTHER_FILES += \
+ $$PWD/qqmlpreviewservice.json
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlPreviewServiceFactory
+
+load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.cpp
new file mode 100644
index 0000000000..d942740db3
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewblacklist.h"
+
+QT_BEGIN_NAMESPACE
+
+void QQmlPreviewBlacklist::blacklist(const QString &path)
+{
+ if (!path.isEmpty())
+ m_root.insert(path, 0);
+}
+
+void QQmlPreviewBlacklist::whitelist(const QString &path)
+{
+ if (!path.isEmpty())
+ m_root.remove(path, 0);
+}
+
+bool QQmlPreviewBlacklist::isBlacklisted(const QString &path) const
+{
+ return path.isEmpty() ? true : m_root.containedPrefixLeaf(path, 0) > 0;
+}
+
+void QQmlPreviewBlacklist::clear()
+{
+ m_root = Node();
+}
+
+QQmlPreviewBlacklist::Node::Node()
+{
+}
+
+QQmlPreviewBlacklist::Node::Node(const QQmlPreviewBlacklist::Node &other) :
+ m_mine(other.m_mine), m_isLeaf(other.m_isLeaf)
+{
+ for (auto it = other.m_next.begin(), end = other.m_next.end(); it != end; ++it)
+ m_next.insert(it.key(), new Node(**it));
+}
+
+QQmlPreviewBlacklist::Node::Node(QQmlPreviewBlacklist::Node &&other) Q_DECL_NOEXCEPT
+{
+ m_mine.swap(other.m_mine);
+ m_next.swap(other.m_next);
+ m_isLeaf = other.m_isLeaf;
+}
+
+QQmlPreviewBlacklist::Node::~Node()
+{
+ qDeleteAll(m_next);
+}
+
+QQmlPreviewBlacklist::Node &QQmlPreviewBlacklist::Node::operator=(
+ const QQmlPreviewBlacklist::Node &other)
+{
+ if (&other != this) {
+ m_mine = other.m_mine;
+ for (auto it = other.m_next.begin(), end = other.m_next.end(); it != end; ++it)
+ m_next.insert(it.key(), new Node(**it));
+ m_isLeaf = other.m_isLeaf;
+ }
+ return *this;
+}
+
+QQmlPreviewBlacklist::Node &QQmlPreviewBlacklist::Node::operator=(
+ QQmlPreviewBlacklist::Node &&other) Q_DECL_NOEXCEPT
+{
+ if (&other != this) {
+ m_mine.swap(other.m_mine);
+ m_next.swap(other.m_next);
+ m_isLeaf = other.m_isLeaf;
+ }
+ return *this;
+}
+
+void QQmlPreviewBlacklist::Node::split(QString::iterator it, QString::iterator end)
+{
+ QString existing;
+ existing.resize(end - it - 1);
+ std::copy(it + 1, end, existing.begin());
+
+ Node *node = new Node(existing, m_next, m_isLeaf);
+ m_next.clear();
+ m_next.insert(*it, node);
+ m_mine.resize(it - m_mine.begin());
+ m_isLeaf = false;
+}
+
+void QQmlPreviewBlacklist::Node::insert(const QString &path, int offset)
+{
+ for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
+ if (offset == path.size()) {
+ split(it, end);
+ m_isLeaf = true;
+ return;
+ }
+
+ if (path.at(offset) != *it) {
+ split(it, end);
+
+ QString inserted;
+ inserted.resize(path.size() - offset - 1);
+ std::copy(path.begin() + offset + 1, path.end(), inserted.begin());
+ m_next.insert(path.at(offset), new Node(inserted));
+ return;
+ }
+
+ ++offset;
+ }
+
+ if (offset == path.size()) {
+ m_isLeaf = true;
+ return;
+ }
+
+ Node *&node = m_next[path.at(offset++)];
+ if (node == nullptr) {
+ QString inserted;
+ inserted.resize(path.size() - offset);
+ std::copy(path.begin() + offset, path.end(), inserted.begin());
+ node = new Node(inserted);
+ } else {
+ node->insert(path, offset);
+ }
+}
+
+void QQmlPreviewBlacklist::Node::remove(const QString &path, int offset)
+{
+ for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
+ if (offset == path.size() || path.at(offset) != *it) {
+ split(it, end);
+ return;
+ }
+ ++offset;
+ }
+
+ m_isLeaf = false;
+ if (offset == path.size())
+ return;
+
+ auto it = m_next.find(path.at(offset));
+ if (it != m_next.end())
+ (*it)->remove(path, ++offset);
+}
+
+int QQmlPreviewBlacklist::Node::containedPrefixLeaf(const QString &path, int offset) const
+{
+ if (offset == path.size())
+ return (m_mine.isEmpty() && m_isLeaf) ? offset : -1;
+
+ for (auto it = m_mine.begin(), end = m_mine.end(); it != end; ++it) {
+ if (path.at(offset) != *it)
+ return -1;
+
+ if (++offset == path.size())
+ return (++it == end && m_isLeaf) ? offset : -1;
+ }
+
+ const QChar c = path.at(offset);
+ if (m_isLeaf && c == '/')
+ return offset;
+
+ auto it = m_next.find(c);
+ if (it == m_next.end())
+ return -1;
+
+ return (*it)->containedPrefixLeaf(path, ++offset);
+}
+
+QQmlPreviewBlacklist::Node::Node(const QString &mine,
+ const QHash<QChar, QQmlPreviewBlacklist::Node *> &next,
+ bool isLeaf)
+ : m_mine(mine), m_next(next), m_isLeaf(isLeaf)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.h
new file mode 100644
index 0000000000..ab9c3a3d8a
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWBLACKLIST_H
+#define QQMLPREVIEWBLACKLIST_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qhash.h>
+#include <QtCore/qchar.h>
+#include <QtCore/qstring.h>
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewBlacklist
+{
+public:
+ void blacklist(const QString &path);
+ void whitelist(const QString &path);
+ bool isBlacklisted(const QString &path) const;
+ void clear();
+
+private:
+ class Node {
+ public:
+ Node();
+ Node(const Node &other);
+ Node(Node &&other) Q_DECL_NOEXCEPT;
+
+ ~Node();
+
+ Node &operator=(const Node &other);
+ Node &operator=(Node &&other) Q_DECL_NOEXCEPT;
+
+ void split(QString::iterator it, QString::iterator end);
+ void insert(const QString &path, int offset);
+ void remove(const QString &path, int offset);
+ int containedPrefixLeaf(const QString &path, int offset) const;
+
+ private:
+ Node(const QString &mine, const QHash<QChar, Node *> &next = QHash<QChar, Node *>(),
+ bool isLeaf = true);
+
+ QString m_mine;
+ QHash<QChar, Node *> m_next;
+ bool m_isLeaf = false;
+ };
+
+ Node m_root;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWBLACKLIST_H
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.cpp
new file mode 100644
index 0000000000..f88cebf806
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewfileengine.h"
+#include "qqmlpreviewservice.h"
+
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qwaitcondition.h>
+
+#include <cstring>
+
+QT_BEGIN_NAMESPACE
+
+static bool isRelative(const QString &path)
+{
+ if (path.isEmpty())
+ return true;
+ if (path.at(0) == '/')
+ return false;
+ if (path.at(0) == ':' && path.length() >= 2 && path.at(1) == '/')
+ return false;
+#ifdef Q_OS_WIN
+ if (path.length() >= 2 && path.at(1) == ':')
+ return false;
+#endif
+ return true;
+}
+
+static QString absolutePath(const QString &path)
+{
+ return QDir::cleanPath(isRelative(path) ? (QDir::currentPath() + '/' + path) : path);
+}
+
+bool isRootPath(const QString &path)
+{
+ return QFileSystemEntry::isRootPath(path);
+}
+
+class QQmlPreviewFileEngineIterator : public QAbstractFileEngineIterator
+{
+public:
+ QQmlPreviewFileEngineIterator(QDir::Filters filters, const QStringList &filterNames,
+ const QStringList &m_entries);
+ ~QQmlPreviewFileEngineIterator();
+
+ QString next() override;
+ bool hasNext() const override;
+ QString currentFileName() const override;
+
+private:
+ const QStringList m_entries;
+ int m_index;
+};
+
+QQmlPreviewFileEngineIterator::QQmlPreviewFileEngineIterator(QDir::Filters filters,
+ const QStringList &filterNames,
+ const QStringList &entries)
+ : QAbstractFileEngineIterator(filters, filterNames), m_entries(entries), m_index(0)
+{
+}
+
+QQmlPreviewFileEngineIterator::~QQmlPreviewFileEngineIterator()
+{
+}
+
+QString QQmlPreviewFileEngineIterator::next()
+{
+ if (!hasNext())
+ return QString();
+ ++m_index;
+ return currentFilePath();
+}
+
+bool QQmlPreviewFileEngineIterator::hasNext() const
+{
+ return m_index < m_entries.size();
+}
+
+QString QQmlPreviewFileEngineIterator::currentFileName() const
+{
+ if (m_index == 0 || m_index > m_entries.size())
+ return QString();
+ return m_entries.at(m_index - 1);
+}
+
+QQmlPreviewFileEngine::QQmlPreviewFileEngine(const QString &file, const QString &absolute,
+ QQmlPreviewFileLoader *loader) :
+ m_name(file), m_absolute(absolute), m_loader(loader)
+{
+ load();
+}
+
+void QQmlPreviewFileEngine::setFileName(const QString &file)
+{
+ m_name = file;
+ m_absolute = absolutePath(file);
+ m_fallback.reset();
+ m_contents.close();
+ m_contents.setData(QByteArray());
+ m_entries.clear();
+ load();
+}
+
+bool QQmlPreviewFileEngine::open(QIODevice::OpenMode flags)
+{
+ switch (m_result) {
+ case QQmlPreviewFileLoader::File:
+ return m_contents.open(flags);
+ case QQmlPreviewFileLoader::Directory:
+ return false;
+ case QQmlPreviewFileLoader::Fallback:
+ return m_fallback->open(flags);
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+bool QQmlPreviewFileEngine::close()
+{
+ switch (m_result) {
+ case QQmlPreviewFileLoader::Fallback:
+ return m_fallback->close();
+ case QQmlPreviewFileLoader::File:
+ m_contents.close();
+ return true;
+ case QQmlPreviewFileLoader::Directory:
+ return false;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+qint64 QQmlPreviewFileEngine::size() const
+{
+ return m_fallback ? m_fallback->size() : m_contents.size();
+}
+
+qint64 QQmlPreviewFileEngine::pos() const
+{
+ return m_fallback ? m_fallback->pos() : m_contents.pos();
+}
+
+bool QQmlPreviewFileEngine::seek(qint64 newPos)
+{
+ return m_fallback? m_fallback->seek(newPos) : m_contents.seek(newPos);
+}
+
+qint64 QQmlPreviewFileEngine::read(char *data, qint64 maxlen)
+{
+ return m_fallback ? m_fallback->read(data, maxlen) : m_contents.read(data, maxlen);
+}
+
+QAbstractFileEngine::FileFlags QQmlPreviewFileEngine::fileFlags(
+ QAbstractFileEngine::FileFlags type) const
+{
+ if (m_fallback)
+ return m_fallback->fileFlags(type);
+
+ QAbstractFileEngine::FileFlags ret = 0;
+
+ if (type & PermsMask) {
+ ret |= QAbstractFileEngine::FileFlags(
+ ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm);
+ }
+
+ if (type & TypesMask) {
+ if (m_result == QQmlPreviewFileLoader::Directory)
+ ret |= DirectoryType;
+ else
+ ret |= FileType;
+ }
+
+ if (type & FlagsMask) {
+ ret |= ExistsFlag;
+ if (isRootPath(m_name))
+ ret |= RootFlag;
+ }
+
+ return ret;
+}
+
+QString QQmlPreviewFileEngine::fileName(QAbstractFileEngine::FileName file) const
+{
+ if (m_fallback)
+ return m_fallback->fileName(file);
+
+ if (file == BaseName) {
+ int slashPos = m_name.lastIndexOf('/');
+ if (slashPos == -1)
+ return m_name;
+ return m_name.mid(slashPos + 1);
+ } else if (file == PathName || file == AbsolutePathName) {
+ const QString path = (file == AbsolutePathName) ? m_absolute : m_name;
+ const int slashPos = path.lastIndexOf('/');
+ if (slashPos == -1)
+ return QString();
+ else if (slashPos == 0)
+ return "/";
+ return path.left(slashPos);
+ } else if (file == CanonicalName || file == CanonicalPathName) {
+ if (file == CanonicalPathName) {
+ const int slashPos = m_absolute.lastIndexOf('/');
+ if (slashPos != -1)
+ return m_absolute.left(slashPos);
+ }
+ return m_absolute;
+ }
+ return m_name;
+}
+
+uint QQmlPreviewFileEngine::ownerId(QAbstractFileEngine::FileOwner owner) const
+{
+ return m_fallback ? m_fallback->ownerId(owner) : static_cast<uint>(-2);
+}
+
+QAbstractFileEngine::Iterator *QQmlPreviewFileEngine::beginEntryList(QDir::Filters filters,
+ const QStringList &filterNames)
+{
+ return m_fallback ? m_fallback->beginEntryList(filters, filterNames)
+ : new QQmlPreviewFileEngineIterator(filters, filterNames, m_entries);
+}
+
+QAbstractFileEngine::Iterator *QQmlPreviewFileEngine::endEntryList()
+{
+ return m_fallback ? m_fallback->endEntryList() : nullptr;
+}
+
+bool QQmlPreviewFileEngine::flush()
+{
+ return m_fallback ? m_fallback->flush() : true;
+}
+
+bool QQmlPreviewFileEngine::syncToDisk()
+{
+ return m_fallback ? m_fallback->syncToDisk() : false;
+}
+
+bool QQmlPreviewFileEngine::isSequential() const
+{
+ return m_fallback ? m_fallback->isSequential() : m_contents.isSequential();
+}
+
+bool QQmlPreviewFileEngine::remove()
+{
+ return m_fallback ? m_fallback->remove() : false;
+}
+
+bool QQmlPreviewFileEngine::copy(const QString &newName)
+{
+ return m_fallback ? m_fallback->copy(newName) : false;
+}
+
+bool QQmlPreviewFileEngine::rename(const QString &newName)
+{
+ return m_fallback ? m_fallback->rename(newName) : false;
+}
+
+bool QQmlPreviewFileEngine::renameOverwrite(const QString &newName)
+{
+ return m_fallback ? m_fallback->renameOverwrite(newName) : false;
+}
+
+bool QQmlPreviewFileEngine::link(const QString &newName)
+{
+ return m_fallback ? m_fallback->link(newName) : false;
+}
+
+bool QQmlPreviewFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const
+{
+ return m_fallback ? m_fallback->mkdir(dirName, createParentDirectories) : false;
+}
+
+bool QQmlPreviewFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
+{
+ return m_fallback ? m_fallback->rmdir(dirName, recurseParentDirectories) : false;
+}
+
+bool QQmlPreviewFileEngine::setSize(qint64 size)
+{
+ switch (m_result) {
+ case QQmlPreviewFileLoader::Fallback:
+ return m_fallback->setSize(size);
+ case QQmlPreviewFileLoader::File:
+ if (size < 0 || size > std::numeric_limits<int>::max())
+ return false;
+ m_contents.buffer().resize(static_cast<int>(size));
+ return true;
+ case QQmlPreviewFileLoader::Directory:
+ return false;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+bool QQmlPreviewFileEngine::caseSensitive() const
+{
+ return m_fallback ? m_fallback->caseSensitive() : true;
+}
+
+bool QQmlPreviewFileEngine::isRelativePath() const
+{
+ return m_fallback ? m_fallback->isRelativePath() : isRelative(m_name);
+}
+
+QStringList QQmlPreviewFileEngine::entryList(QDir::Filters filters,
+ const QStringList &filterNames) const
+{
+ return m_fallback ? m_fallback->entryList(filters, filterNames)
+ : QAbstractFileEngine::entryList(filters, filterNames);
+}
+
+bool QQmlPreviewFileEngine::setPermissions(uint perms)
+{
+ return m_fallback ? m_fallback->setPermissions(perms) : false;
+}
+
+QByteArray QQmlPreviewFileEngine::id() const
+{
+ return m_fallback ? m_fallback->id() : QByteArray();
+}
+
+QString QQmlPreviewFileEngine::owner(FileOwner owner) const
+{
+ return m_fallback ? m_fallback->owner(owner) : QString();
+}
+
+QDateTime QQmlPreviewFileEngine::fileTime(FileTime time) const
+{
+ // Files we replace are always newer than the ones we had before. This makes the QML engine
+ // actually recompile them, rather than pick them from the cache.
+ return m_fallback ? m_fallback->fileTime(time) : QDateTime::currentDateTime();
+}
+
+int QQmlPreviewFileEngine::handle() const
+{
+ return m_fallback ? m_fallback->handle() : -1;
+}
+
+qint64 QQmlPreviewFileEngine::readLine(char *data, qint64 maxlen)
+{
+ return m_fallback ? m_fallback->readLine(data, maxlen) : m_contents.readLine(data, maxlen);
+}
+
+qint64 QQmlPreviewFileEngine::write(const char *data, qint64 len)
+{
+ return m_fallback ? m_fallback->write(data, len) : m_contents.write(data, len);
+}
+
+bool QQmlPreviewFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
+{
+ return m_fallback ? m_fallback->extension(extension, option, output) : false;
+}
+
+bool QQmlPreviewFileEngine::supportsExtension(Extension extension) const
+{
+ return m_fallback ? m_fallback->supportsExtension(extension) : false;
+}
+
+void QQmlPreviewFileEngine::load() const
+{
+ m_result = m_loader->load(m_absolute);
+ switch (m_result) {
+ case QQmlPreviewFileLoader::File:
+ m_contents.setData(m_loader->contents());
+ break;
+ case QQmlPreviewFileLoader::Directory:
+ m_entries = m_loader->entries();
+ break;
+ case QQmlPreviewFileLoader::Fallback:
+ m_fallback.reset(QAbstractFileEngine::create(m_name));
+ break;
+ case QQmlPreviewFileLoader::Unknown:
+ Q_UNREACHABLE();
+ break;
+ }
+}
+
+QQmlPreviewFileEngineHandler::QQmlPreviewFileEngineHandler(QQmlPreviewFileLoader *loader)
+ : m_loader(loader)
+{
+}
+
+QAbstractFileEngine *QQmlPreviewFileEngineHandler::create(const QString &fileName) const
+{
+ // Don't load compiled QML/JS over the network
+ if (fileName.endsWith(".qmlc") || fileName.endsWith(".jsc") || isRootPath(fileName)) {
+ return nullptr;
+ }
+
+ QString relative = fileName;
+ while (relative.endsWith('/'))
+ relative.chop(1);
+
+ if (relative.isEmpty() || relative == ":")
+ return nullptr;
+
+ const QString absolute = relative.startsWith(':') ? relative : absolutePath(relative);
+
+ return m_loader->isBlacklisted(absolute)
+ ? nullptr : new QQmlPreviewFileEngine(relative, absolute, m_loader.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.h
new file mode 100644
index 0000000000..60af76c334
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileengine.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWFILEENGINE_H
+#define QQMLPREVIEWFILEENGINE_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 "qqmlpreviewfileloader.h"
+
+#include <private/qabstractfileengine_p.h>
+#include <private/qfsfileengine_p.h>
+#include <QtCore/qbuffer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewFileEngine : public QAbstractFileEngine
+{
+public:
+ QQmlPreviewFileEngine(const QString &file, const QString &absolute,
+ QQmlPreviewFileLoader *loader);
+
+ void setFileName(const QString &file) override;
+
+ bool open(QIODevice::OpenMode flags) override ;
+ bool close() override;
+ qint64 size() const override;
+ qint64 pos() const override;
+ bool seek(qint64) override;
+ qint64 read(char *data, qint64 maxlen) override;
+
+ FileFlags fileFlags(FileFlags type) const override;
+ QString fileName(QAbstractFileEngine::FileName file) const override;
+ uint ownerId(FileOwner) const override;
+
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
+ Iterator *endEntryList() override;
+
+ // Forwarding to fallback if exists
+ bool flush() override;
+ bool syncToDisk() override;
+ bool isSequential() const override;
+ bool remove() override;
+ bool copy(const QString &newName) override;
+ bool rename(const QString &newName) override;
+ bool renameOverwrite(const QString &newName) override;
+ bool link(const QString &newName) override;
+ bool mkdir(const QString &dirName, bool createParentDirectories) const override;
+ bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
+ bool setSize(qint64 size) override;
+ bool caseSensitive() const override;
+ bool isRelativePath() const override;
+ QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
+ bool setPermissions(uint perms) override;
+ QByteArray id() const override;
+ QString owner(FileOwner) const override;
+ QDateTime fileTime(FileTime time) const override;
+ int handle() const override;
+ qint64 readLine(char *data, qint64 maxlen) override;
+ qint64 write(const char *data, qint64 len) override;
+ bool extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) override;
+ bool supportsExtension(Extension extension) const override;
+
+private:
+ void load() const;
+
+ QString m_name;
+ QString m_absolute;
+ QPointer<QQmlPreviewFileLoader> m_loader;
+
+ mutable QBuffer m_contents;
+ mutable QStringList m_entries;
+ mutable QScopedPointer<QAbstractFileEngine> m_fallback;
+ mutable QQmlPreviewFileLoader::Result m_result = QQmlPreviewFileLoader::Unknown;
+};
+
+class QQmlPreviewFileEngineHandler : public QAbstractFileEngineHandler
+{
+public:
+ QQmlPreviewFileEngineHandler(QQmlPreviewFileLoader *loader);
+ QAbstractFileEngine *create(const QString &fileName) const override;
+
+private:
+ QPointer<QQmlPreviewFileLoader> m_loader;
+};
+
+
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWFILEENGINE_H
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.cpp
new file mode 100644
index 0000000000..17a3a48184
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewfileloader.h"
+#include "qqmlpreviewservice.h"
+
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qstandardpaths.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlPreviewFileLoader::QQmlPreviewFileLoader(QQmlPreviewServiceImpl *service) : m_service(service)
+{
+ // Exclude some resource paths used by Qt itself. There is no point in loading those from the
+ // client as the client will not have the files (or even worse, it may have different ones).
+ m_blacklist.blacklist(":/qt-project.org");
+ m_blacklist.blacklist(":/QtQuick/Controls/Styles");
+ m_blacklist.blacklist(":/ExtrasImports/QtQuick/Controls/Styles");
+ m_blacklist.blacklist(":/qgradient");
+
+ // Target specific configuration should not replaced with files from the host.
+ m_blacklist.blacklist("/etc");
+
+ for (int loc = QLibraryInfo::PrefixPath; loc <= QLibraryInfo::TestsPath; ++loc) {
+ m_blacklist.blacklist(QLibraryInfo::location(
+ static_cast<QLibraryInfo::LibraryLocation>(loc)));
+ }
+ m_blacklist.blacklist(QLibraryInfo::location(QLibraryInfo::SettingsPath));
+
+ static const QStandardPaths::StandardLocation blackListLocations[] = {
+ QStandardPaths::DataLocation,
+ QStandardPaths::CacheLocation,
+ QStandardPaths::GenericDataLocation,
+ QStandardPaths::RuntimeLocation,
+ QStandardPaths::ConfigLocation,
+ QStandardPaths::GenericCacheLocation,
+ QStandardPaths::GenericConfigLocation,
+ QStandardPaths::AppDataLocation,
+ QStandardPaths::AppConfigLocation
+ };
+
+ for (auto locationType : blackListLocations) {
+ const QStringList locations = QStandardPaths::standardLocations(locationType);
+ for (const QString &location : locations)
+ m_blacklist.blacklist(location);
+ }
+
+ connect(this, &QQmlPreviewFileLoader::request, service, &QQmlPreviewServiceImpl::forwardRequest,
+ Qt::DirectConnection);
+ connect(service, &QQmlPreviewServiceImpl::directory, this, &QQmlPreviewFileLoader::directory);
+ connect(service, &QQmlPreviewServiceImpl::file, this, &QQmlPreviewFileLoader::file);
+ connect(service, &QQmlPreviewServiceImpl::error, this, &QQmlPreviewFileLoader::error);
+ connect(service, &QQmlPreviewServiceImpl::clearCache, this, &QQmlPreviewFileLoader::clearCache);
+ moveToThread(&m_thread);
+ m_thread.start();
+}
+
+QQmlPreviewFileLoader::~QQmlPreviewFileLoader() {
+ m_thread.quit();
+ m_thread.wait();
+}
+
+QQmlPreviewFileLoader::Result QQmlPreviewFileLoader::load(const QString &path)
+{
+ QMutexLocker locker(&m_mutex);
+ m_path = path;
+
+ auto fileIterator = m_fileCache.constFind(path);
+ if (fileIterator != m_fileCache.constEnd()) {
+ m_result = File;
+ m_contents = *fileIterator;
+ m_entries.clear();
+ return m_result;
+ }
+
+ auto dirIterator = m_directoryCache.constFind(path);
+ if (dirIterator != m_directoryCache.constEnd()) {
+ m_result = Directory;
+ m_contents.clear();
+ m_entries = *dirIterator;
+ return m_result;
+ }
+
+ m_result = Unknown;
+ m_entries.clear();
+ m_contents.clear();
+ emit request(path);
+ m_waitCondition.wait(&m_mutex);
+ return m_result;
+}
+
+QByteArray QQmlPreviewFileLoader::contents()
+{
+ QMutexLocker locker(&m_mutex);
+ return m_contents;
+}
+
+QStringList QQmlPreviewFileLoader::entries()
+{
+ QMutexLocker locker(&m_mutex);
+ return m_entries;
+}
+
+void QQmlPreviewFileLoader::whitelist(const QUrl &url)
+{
+ const QString path = QQmlFile::urlToLocalFileOrQrc(url);
+ if (!path.isEmpty()) {
+ QMutexLocker locker(&m_mutex);
+ m_blacklist.whitelist(path);
+ }
+}
+
+bool QQmlPreviewFileLoader::isBlacklisted(const QString &path)
+{
+ QMutexLocker locker(&m_mutex);
+ return m_blacklist.isBlacklisted(path);
+}
+
+void QQmlPreviewFileLoader::file(const QString &path, const QByteArray &contents)
+{
+ QMutexLocker locker(&m_mutex);
+ m_blacklist.whitelist(path);
+ m_fileCache[path] = contents;
+ if (path == m_path) {
+ m_contents = contents;
+ m_result = File;
+ m_waitCondition.wakeOne();
+ }
+}
+
+void QQmlPreviewFileLoader::directory(const QString &path, const QStringList &entries)
+{
+ QMutexLocker locker(&m_mutex);
+ m_blacklist.whitelist(path);
+ m_directoryCache[path] = entries;
+ if (path == m_path) {
+ m_entries = entries;
+ m_result = Directory;
+ m_waitCondition.wakeOne();
+ }
+}
+
+void QQmlPreviewFileLoader::error(const QString &path)
+{
+ QMutexLocker locker(&m_mutex);
+ m_blacklist.blacklist(path);
+ if (path == m_path) {
+ m_result = Fallback;
+ m_waitCondition.wakeOne();
+ }
+}
+
+void QQmlPreviewFileLoader::clearCache()
+{
+ QMutexLocker locker(&m_mutex);
+ m_fileCache.clear();
+ m_directoryCache.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.h
new file mode 100644
index 0000000000..de0a9cadea
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWFILELOADER_H
+#define QQMLPREVIEWFILELOADER_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 "qqmlpreviewblacklist.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewServiceImpl;
+class QQmlPreviewFileLoader : public QObject
+{
+ Q_OBJECT
+public:
+ enum Result {
+ File,
+ Directory,
+ Fallback,
+ Unknown
+ };
+
+ QQmlPreviewFileLoader(QQmlPreviewServiceImpl *service);
+ ~QQmlPreviewFileLoader();
+
+ Result load(const QString &file);
+ QByteArray contents();
+ QStringList entries();
+
+ void whitelist(const QUrl &url);
+ bool isBlacklisted(const QString &file);
+
+signals:
+ void request(const QString &file);
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+
+ QThread m_thread;
+ QPointer<QQmlPreviewServiceImpl> m_service;
+
+ QString m_path;
+ QByteArray m_contents;
+ QStringList m_entries;
+ Result m_result;
+
+ QQmlPreviewBlacklist m_blacklist;
+ QHash<QString, QByteArray> m_fileCache;
+ QHash<QString, QStringList> m_directoryCache;
+
+ void file(const QString &file, const QByteArray &contents);
+ void directory(const QString &file, const QStringList &entries);
+ void error(const QString &file);
+ void clearCache();
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWFILELOADER_H
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp
new file mode 100644
index 0000000000..fdfa9dcc34
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewhandler.h"
+
+#include <QtCore/qtimer.h>
+#include <QtCore/qsettings.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qguiapplication.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQml/qqmlcomponent.h>
+
+#include <private/qquickpixmapcache_p.h>
+#include <private/qquickview_p.h>
+#include <private/qhighdpiscaling_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QuitLockDisabler
+{
+ const bool quitLockEnabled;
+
+ QuitLockDisabler() : quitLockEnabled(QCoreApplication::isQuitLockEnabled())
+ {
+ QCoreApplication::setQuitLockEnabled(false);
+ }
+
+ ~QuitLockDisabler()
+ {
+ QCoreApplication::setQuitLockEnabled(quitLockEnabled);
+ }
+};
+
+QQmlPreviewHandler::QQmlPreviewHandler(QObject *parent) : QObject(parent)
+{
+ m_dummyItem.reset(new QQuickItem);
+
+ // TODO: Is there a better way to determine this? We want to keep the window alive when possible
+ // as otherwise it will reappear in a different place when (re)loading a file. However,
+ // the file we load might create another window, in which case the eglfs plugin (and
+ // others?) will do a qFatal as it only supports a single window.
+ const QString platformName = QGuiApplication::platformName();
+ m_supportsMultipleWindows = (platformName == QStringLiteral("windows")
+ || platformName == QStringLiteral("cocoa")
+ || platformName == QStringLiteral("xcb")
+ || platformName == QStringLiteral("wayland"));
+
+ QCoreApplication::instance()->installEventFilter(this);
+}
+
+QQmlPreviewHandler::~QQmlPreviewHandler()
+{
+ clear();
+}
+
+static void closeAllWindows()
+{
+ const QWindowList windows = QGuiApplication::allWindows();
+ for (QWindow *window : windows)
+ window->close();
+}
+
+bool QQmlPreviewHandler::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::Show) {
+ if (QWindow *window = qobject_cast<QQuickWindow*>(obj)) {
+ m_lastPosition.initLastSavedWindowPosition(window);
+ }
+ }
+ if ((event->type() == QEvent::Move || event->type() == QEvent::Resize) &&
+ qobject_cast<QQuickWindow*>(obj) == m_currentWindow) {
+ // we always start with factor 1 so calculate and save the origin as it would be not scaled
+ m_lastPosition.setPosition(m_currentWindow->framePosition() *
+ QHighDpiScaling::factor(m_currentWindow));
+ }
+
+ return QObject::eventFilter(obj, event);
+}
+
+void QQmlPreviewHandler::addEngine(QQmlEngine *qmlEngine)
+{
+ m_engines.append(qmlEngine);
+}
+
+void QQmlPreviewHandler::removeEngine(QQmlEngine *qmlEngine)
+{
+ const bool found = m_engines.removeOne(qmlEngine);
+ Q_ASSERT(found);
+ for (QObject *obj : m_createdObjects)
+ if (obj && QtQml::qmlEngine(obj) == qmlEngine)
+ delete obj;
+ m_createdObjects.removeAll(nullptr);
+}
+
+void QQmlPreviewHandler::loadUrl(const QUrl &url)
+{
+ QSharedPointer<QuitLockDisabler> disabler(new QuitLockDisabler);
+
+ clear();
+ m_component.reset(nullptr);
+ QQuickPixmap::purgeCache();
+
+ const int numEngines = m_engines.count();
+ if (numEngines > 1) {
+ emit error(QString::fromLatin1("%1 QML engines available. We cannot decide which one "
+ "should load the component.").arg(numEngines));
+ return;
+ } else if (numEngines == 0) {
+ emit error(QLatin1String("No QML engines found."));
+ return;
+ }
+ m_lastPosition.loadWindowPositionSettings(url);
+
+ QQmlEngine *engine = m_engines.front();
+ engine->clearComponentCache();
+ m_component.reset(new QQmlComponent(engine, url, this));
+
+ auto onStatusChanged = [disabler, this](QQmlComponent::Status status) {
+ switch (status) {
+ case QQmlComponent::Null:
+ case QQmlComponent::Loading:
+ return true; // try again later
+ case QQmlComponent::Ready:
+ tryCreateObject();
+ break;
+ case QQmlComponent::Error:
+ emit error(m_component->errorString());
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ disconnect(m_component.data(), &QQmlComponent::statusChanged, this, nullptr);
+ return false; // we're done
+ };
+
+ if (onStatusChanged(m_component->status()))
+ connect(m_component.data(), &QQmlComponent::statusChanged, this, onStatusChanged);
+}
+
+void QQmlPreviewHandler::rerun()
+{
+ if (m_component.isNull() || !m_component->isReady())
+ emit error(QLatin1String("Component is not ready."));
+
+ QuitLockDisabler disabler;
+ Q_UNUSED(disabler);
+ clear();
+ tryCreateObject();
+}
+
+void QQmlPreviewHandler::zoom(qreal newFactor)
+{
+ if (!m_currentWindow)
+ return;
+ if (qFuzzyIsNull(newFactor)) {
+ emit error(QString::fromLatin1("Zooming with factor: %1 will result in nothing " \
+ "so it will be ignored.").arg(newFactor));
+ return;
+ }
+ QString errorMessage;
+ bool resetZoom = false;
+
+ if (newFactor < 0) {
+ resetZoom = true;
+ newFactor = 1.0;
+ }
+
+ // On single-window devices we allow any scale factor as the window will adapt to the screen.
+ if (m_supportsMultipleWindows) {
+ const QSize newAvailableScreenSize = QQmlPreviewPosition::currentScreenSize(m_currentWindow)
+ * QHighDpiScaling::factor(m_currentWindow) / newFactor;
+ if (m_currentWindow->size().width() > newAvailableScreenSize.width()) {
+ errorMessage = QString::fromLatin1(
+ "Zooming with factor: "
+ "%1 will result in a too wide preview.").arg(newFactor);
+ }
+ if (m_currentWindow->size().height() > newAvailableScreenSize.height()) {
+ errorMessage = QString::fromLatin1(
+ "Zooming with factor: "
+ "%1 will result in a too heigh preview.").arg(newFactor);
+ }
+ }
+
+ if (errorMessage.isEmpty()) {
+ const QPoint newToOriginMappedPosition = m_currentWindow->position() *
+ QHighDpiScaling::factor(m_currentWindow) / newFactor;
+ m_currentWindow->destroy();
+ QHighDpiScaling::setScreenFactor(m_currentWindow->screen(), newFactor);
+ if (resetZoom)
+ QHighDpiScaling::updateHighDpiScaling();
+ m_currentWindow->setPosition(newToOriginMappedPosition);
+ m_currentWindow->show();
+ } else {
+ emit error(errorMessage);
+ }
+}
+
+void QQmlPreviewHandler::clear()
+{
+ qDeleteAll(m_createdObjects);
+ m_createdObjects.clear();
+ m_currentWindow = nullptr;
+}
+
+Qt::WindowFlags fixFlags(Qt::WindowFlags flags)
+{
+ // If only the type flag is given, some other window flags are automatically assumed. When we
+ // add a flag, we need to make those explicit.
+ switch (flags) {
+ case Qt::Window:
+ return flags | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
+ case Qt::Dialog:
+ case Qt::Tool:
+ return flags | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+ default:
+ return flags;
+ }
+}
+
+void QQmlPreviewHandler::showObject(QObject *object)
+{
+ if (QWindow *window = qobject_cast<QWindow *>(object)) {
+ m_currentWindow = qobject_cast<QQuickWindow *>(window);
+ for (QWindow *otherWindow : QGuiApplication::allWindows()) {
+ if (QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(otherWindow)) {
+ if (quickWindow == m_currentWindow)
+ continue;
+ quickWindow->setVisible(false);
+ quickWindow->setFlags(quickWindow->flags() & ~Qt::WindowStaysOnTopHint);
+ }
+ }
+ } else if (QQuickItem *item = qobject_cast<QQuickItem *>(object)) {
+ m_currentWindow = nullptr;
+ for (QWindow *window : QGuiApplication::allWindows()) {
+ if (QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window)) {
+ if (m_currentWindow != nullptr) {
+ emit error(QLatin1String("Multiple QQuickWindows available. We cannot "
+ "decide which one to use."));
+ return;
+ }
+ m_currentWindow = quickWindow;
+ } else {
+ window->setVisible(false);
+ window->setFlag(Qt::WindowStaysOnTopHint, false);
+ }
+ }
+
+ if (m_currentWindow == nullptr) {
+ m_currentWindow = new QQuickWindow;
+ m_createdObjects.append(m_currentWindow.data());
+ }
+
+ for (QQuickItem *oldItem : m_currentWindow->contentItem()->childItems())
+ oldItem->setParentItem(m_dummyItem.data());
+
+ // Special case for QQuickView, as that keeps a "root" pointer around, and uses it to
+ // automatically resize the window or the item.
+ if (QQuickView *view = qobject_cast<QQuickView *>(m_currentWindow))
+ QQuickViewPrivate::get(view)->setRootObject(item);
+ else
+ item->setParentItem(m_currentWindow->contentItem());
+
+ m_currentWindow->resize(item->size().toSize());
+ } else {
+ emit error(QLatin1String("Created object is neither a QWindow nor a QQuickItem."));
+ }
+
+ if (m_currentWindow) {
+ m_lastPosition.initLastSavedWindowPosition(m_currentWindow);
+ m_currentWindow->setFlags(fixFlags(m_currentWindow->flags()) | Qt::WindowStaysOnTopHint);
+ m_currentWindow->setVisible(true);
+ }
+}
+
+void QQmlPreviewHandler::tryCreateObject()
+{
+ if (!m_supportsMultipleWindows)
+ closeAllWindows();
+ QObject *object = m_component->create();
+ m_createdObjects.append(object);
+ showObject(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h
new file mode 100644
index 0000000000..78099fb1e5
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWHANDLER_H
+#define QQMLPREVIEWHANDLER_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 "qqmlpreviewposition.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpointer.h>
+#include <QtQml/qqmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngine;
+class QQuickItem;
+class QQmlPreviewUrlInterceptor;
+class QQuickWindow;
+class QQmlPreviewHandler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QQmlPreviewHandler(QObject *parent = nullptr);
+ ~QQmlPreviewHandler();
+
+ void addEngine(QQmlEngine *engine);
+ void removeEngine(QQmlEngine *engine);
+
+ void loadUrl(const QUrl &url);
+ void rerun();
+ void zoom(qreal newFactor);
+
+ void clear();
+
+signals:
+ void error(const QString &message);
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+private:
+ void tryCreateObject();
+ void showObject(QObject *object);
+
+ QScopedPointer<QQuickItem> m_dummyItem;
+ QList<QQmlEngine *> m_engines;
+ QVector<QPointer<QObject>> m_createdObjects;
+ QScopedPointer<QQmlComponent> m_component;
+ QPointer<QQuickWindow> m_currentWindow;
+ bool m_supportsMultipleWindows;
+ QQmlPreviewPosition m_lastPosition;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWHANDLER_H
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
new file mode 100644
index 0000000000..2382f72fe3
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewposition.h"
+
+#include <QtGui/qwindow.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qguiapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+static const QSize availableScreenSize(const QPoint &point)
+{
+ if (const QScreen *screen = QGuiApplication::screenAt(point))
+ return screen->availableGeometry().size();
+ return QSize();
+}
+
+QQmlPreviewPosition::QQmlPreviewPosition()
+ : m_settings("QtProject", "QtQmlPreview")
+{
+ m_savePositionTimer.setSingleShot(true);
+ m_savePositionTimer.setInterval(500);
+ QObject::connect(&m_savePositionTimer, &QTimer::timeout, [this]() {
+ saveWindowPosition();
+ });
+}
+
+void QQmlPreviewPosition::setPosition(const QPoint &point)
+{
+ m_hasPosition = true;
+ m_lastWindowPosition = point;
+ m_savePositionTimer.start();
+}
+
+void QQmlPreviewPosition::saveWindowPosition()
+{
+ if (m_hasPosition) {
+ if (!m_settingsKey.isNull())
+ m_settings.setValue(m_settingsKey, m_lastWindowPosition);
+
+ m_settings.setValue(QLatin1String("global_lastpostion"), m_lastWindowPosition);
+ }
+}
+
+void QQmlPreviewPosition::loadWindowPositionSettings(const QUrl &url)
+{
+ m_settingsKey = url.toString(QUrl::PreferLocalFile) + QLatin1String("_lastpostion");
+
+ if (m_settings.contains(m_settingsKey)) {
+ m_hasPosition = true;
+ m_lastWindowPosition = m_settings.value(m_settingsKey).toPoint();
+ }
+}
+
+void QQmlPreviewPosition::initLastSavedWindowPosition(QWindow *window)
+{
+ if (m_positionedWindows.contains(window))
+ return;
+ if (!m_hasPosition) {
+ // in case there was nothing saved, we do not want to set anything
+ if (!m_settings.contains(QLatin1String("global_lastpostion")))
+ return;
+ m_lastWindowPosition = m_settings.value(QLatin1String("global_lastpostion")).toPoint();
+ }
+ if (QGuiApplication::screenAt(m_lastWindowPosition))
+ window->setFramePosition(m_lastWindowPosition);
+
+ m_positionedWindows.append(window);
+}
+
+const QSize QQmlPreviewPosition::currentScreenSize(QWindow *window)
+{
+ return availableScreenSize(window->position());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
new file mode 100644
index 0000000000..8683757007
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWPOSITION_H
+#define QQMLPREVIEWPOSITION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qvector.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qsettings.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+class QQmlPreviewPosition
+{
+public:
+ QQmlPreviewPosition();
+
+ void setPosition(const QPoint &point);
+ void saveWindowPosition();
+ void loadWindowPositionSettings(const QUrl &url);
+ void initLastSavedWindowPosition(QWindow *window);
+ static const QSize currentScreenSize(QWindow *window);
+
+private:
+ bool m_hasPosition = false;
+ QPoint m_lastWindowPosition;
+ QSettings m_settings;
+ QString m_settingsKey;
+ QTimer m_savePositionTimer;
+ QVector<QWindow *> m_positionedWindows;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWPOSITION_H
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp
new file mode 100644
index 0000000000..70e895e78c
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewservice.h"
+
+#include <QtCore/qpointer.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qquickitem.h>
+#include <QtGui/qguiapplication.h>
+
+#include <private/qquickpixmapcache_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qversionedpacket_p.h>
+
+QT_BEGIN_NAMESPACE
+
+const QString QQmlPreviewServiceImpl::s_key = QStringLiteral("QmlPreview");
+using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
+
+QQmlPreviewServiceImpl::QQmlPreviewServiceImpl(QObject *parent) :
+ QQmlDebugService(s_key, 1.0f, parent)
+{
+ m_loader.reset(new QQmlPreviewFileLoader(this));
+ connect(this, &QQmlPreviewServiceImpl::load,
+ m_loader.data(), &QQmlPreviewFileLoader::whitelist, Qt::DirectConnection);
+ connect(this, &QQmlPreviewServiceImpl::load, &m_handler, &QQmlPreviewHandler::loadUrl);
+ connect(this, &QQmlPreviewServiceImpl::rerun, &m_handler, &QQmlPreviewHandler::rerun);
+ connect(this, &QQmlPreviewServiceImpl::zoom, &m_handler, &QQmlPreviewHandler::zoom);
+ connect(&m_handler, &QQmlPreviewHandler::error, this, &QQmlPreviewServiceImpl::forwardError,
+ Qt::DirectConnection);
+
+}
+
+QQmlPreviewServiceImpl::~QQmlPreviewServiceImpl()
+{
+}
+
+void QQmlPreviewServiceImpl::messageReceived(const QByteArray &data)
+{
+ QQmlDebugPacket packet(data);
+ qint8 command;
+
+ packet >> command;
+ switch (command) {
+ case File: {
+ QString path;
+ QByteArray contents;
+ packet >> path >> contents;
+ emit file(path, contents);
+
+ // Replace the whole scene with the first file successfully loaded over the debug
+ // connection. This is an OK approximation of the root component, and if the client wants
+ // something specific, it will send an explicit Load anyway.
+ if (m_currentUrl.isEmpty() && path.endsWith(".qml")) {
+ if (path.startsWith(':'))
+ m_currentUrl = QUrl("qrc" + path);
+ else
+ m_currentUrl = QUrl::fromLocalFile(path);
+ emit load(m_currentUrl);
+ }
+ break;
+ }
+ case Directory: {
+ QString path;
+ QStringList entries;
+ packet >> path >> entries;
+ emit directory(path, entries);
+ break;
+ }
+ case Load: {
+ QUrl url;
+ packet >> url;
+ if (url.isEmpty())
+ url = m_currentUrl;
+ else
+ m_currentUrl = url;
+ emit load(url);
+ break;
+ }
+ case Error: {
+ QString file;
+ packet >> file;
+ emit error(file);
+ break;
+ }
+ case Rerun:
+ emit rerun();
+ break;
+ case ClearCache:
+ emit clearCache();
+ break;
+ case Zoom: {
+ float factor;
+ packet >> factor;
+ emit zoom(static_cast<qreal>(factor));
+ break;
+ }
+ default:
+ forwardError(QString::fromLatin1("Invalid command: %1").arg(command));
+ break;
+ }
+}
+
+void QQmlPreviewServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
+{
+ if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine))
+ m_handler.addEngine(qmlEngine);
+ emit attachedToEngine(engine);
+}
+
+void QQmlPreviewServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
+{
+ if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine))
+ m_handler.removeEngine(qmlEngine);
+ emit detachedFromEngine(engine);
+}
+
+void QQmlPreviewServiceImpl::stateChanged(QQmlDebugService::State state)
+{
+ m_fileEngine.reset(state == Enabled ? new QQmlPreviewFileEngineHandler(m_loader.data())
+ : nullptr);
+}
+
+void QQmlPreviewServiceImpl::forwardRequest(const QString &file)
+{
+ QQmlDebugPacket packet;
+ packet << static_cast<qint8>(Request) << file;
+ emit messageToClient(name(), packet.data());
+}
+
+void QQmlPreviewServiceImpl::forwardError(const QString &error)
+{
+ QQmlDebugPacket packet;
+ packet << static_cast<qint8>(Error) << error;
+ emit messageToClient(name(), packet.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h
new file mode 100644
index 0000000000..6c35ef52dd
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of th QML Preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWSERVICE_H
+#define QQMLPREVIEWSERVICE_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 "qqmlpreviewhandler.h"
+#include "qqmlpreviewfileengine.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewFileEngineHandler;
+class QQmlPreviewHandler;
+class QQmlPreviewServiceImpl : public QQmlDebugService
+{
+ Q_OBJECT
+
+public:
+ enum Command {
+ File,
+ Load,
+ Request,
+ Error,
+ Rerun,
+ Directory,
+ ClearCache,
+ Zoom
+ };
+
+ static const QString s_key;
+
+ QQmlPreviewServiceImpl(QObject *parent = nullptr);
+ virtual ~QQmlPreviewServiceImpl();
+
+ void messageReceived(const QByteArray &message) override;
+ void engineAboutToBeAdded(QJSEngine *engine) override;
+ void engineAboutToBeRemoved(QJSEngine *engine) override;
+ void stateChanged(State state) override;
+
+ void forwardRequest(const QString &file);
+ void forwardError(const QString &error);
+
+signals:
+ void error(const QString &file);
+ void file(const QString &file, const QByteArray &contents);
+ void directory(const QString &file, const QStringList &entries);
+ void load(const QUrl &url);
+ void rerun();
+ void clearCache();
+ void zoom(qreal factor);
+
+private:
+ QScopedPointer<QQmlPreviewFileEngineHandler> m_fileEngine;
+ QScopedPointer<QQmlPreviewFileLoader> m_loader;
+ QQmlPreviewHandler m_handler;
+ QUrl m_currentUrl;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWSERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json
new file mode 100644
index 0000000000..d7e1ef1f10
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys" : [ "QmlPreview" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp
new file mode 100644
index 0000000000..4e09bd1002
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpreviewservicefactory.h"
+#include "qqmlpreviewservice.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebugService *QQmlPreviewServiceFactory::create(const QString &key)
+{
+ return key == QQmlPreviewServiceImpl::s_key ? new QQmlPreviewServiceImpl(this) : nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.h
new file mode 100644
index 0000000000..f51e696fe6
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QML preview debug service.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWSERVCIEFACTORY_H
+#define QQMLPREVIEWSERVCIEFACTORY_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/qqmldebugservicefactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewServiceFactory : public QQmlDebugServiceFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmlpreviewservice.json")
+
+public:
+ QQmlDebugService *create(const QString &key) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWSERVCIEFACTORY_H
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index 19104927f2..a688e98b3f 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -80,8 +80,7 @@ void QQmlProfilerAdapter::init(QQmlProfilerService *service, QQmlProfiler *profi
// convert to QByteArrays that can be sent to the debug client
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
QQmlProfiler::LocationHash &locations,
- QList<QByteArray> &messages,
- bool trackLocations)
+ QList<QByteArray> &messages)
{
QQmlDebugPacket ds;
Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
@@ -96,7 +95,7 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
if (decodedMessageType == QQmlProfilerDefinitions::RangeEnd
|| decodedMessageType == QQmlProfilerDefinitions::RangeStart) {
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
- if (trackLocations && d.locationId != 0)
+ if (d.locationId != 0)
ds << static_cast<qint64>(d.locationId);
} else {
auto i = locations.find(d.locationId);
@@ -107,8 +106,7 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
<< static_cast<qint32>(i->location.column);
if (d.messageType & (1 << QQmlProfilerDefinitions::RangeData)) {
// Send both, location and data ...
- if (trackLocations)
- ds << static_cast<qint64>(d.locationId);
+ ds << static_cast<qint64>(d.locationId);
messages.append(ds.squeezedData());
ds.clear();
ds << d.time << int(QQmlProfilerDefinitions::RangeData)
@@ -116,10 +114,8 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
<< (i->location.sourceFile.isEmpty() ? i->url.toString() :
i->location.sourceFile);
}
- if (trackLocations) {
- ds << static_cast<qint64>(d.locationId);
- locations.erase(i); // ... so that we can erase here without missing anything.
- }
+ ds << static_cast<qint64>(d.locationId);
+ locations.erase(i); // ... so that we can erase here without missing anything.
} else {
// Skip RangeData and RangeLocation: We've already sent them
continue;
@@ -130,14 +126,13 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
}
}
-qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
- bool trackLocations)
+qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
while (next != data.length()) {
const QQmlProfilerData &nextData = data.at(next);
if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
return nextData.time;
- qQmlProfilerDataToByteArrays(nextData, locations, messages, trackLocations);
+ qQmlProfilerDataToByteArrays(nextData, locations, messages);
++next;
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index b14b72d254..12544a19c2 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -61,8 +61,7 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
public:
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlTypeLoader *loader);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
- bool trackLocations) override;
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages) override;
void receiveData(const QVector<QQmlProfilerData> &new_data,
const QQmlProfiler::LocationHash &locations);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 21a5663f59..462401a093 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -58,7 +58,7 @@ Q_QML_DEBUG_PLUGIN_LOADER(QQmlAbstractProfilerAdapter)
QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
- m_waitingForStop(false), m_useMessageTypes(false), m_globalEnabled(false), m_globalFeatures(0)
+ m_waitingForStop(false), m_globalEnabled(false), m_globalFeatures(0)
{
m_timer.start();
QQmlAbstractProfilerAdapter *quickAdapter =
@@ -332,7 +332,7 @@ void QQmlProfilerServiceImpl::stopProfiling(QJSEngine *engine)
m_waitingForStop = true;
for (QQmlAbstractProfilerAdapter *profiler : qAsConst(reporting))
- profiler->reportData(m_useMessageTypes);
+ profiler->reportData();
for (QQmlAbstractProfilerAdapter *profiler : qAsConst(stopping))
profiler->stopProfiling();
@@ -367,8 +367,7 @@ void QQmlProfilerServiceImpl::sendMessages()
m_startTimes.erase(m_startTimes.begin());
qint64 next = first->sendMessages(m_startTimes.isEmpty() ?
std::numeric_limits<qint64>::max() :
- m_startTimes.begin().key(), messages,
- m_useMessageTypes);
+ m_startTimes.begin().key(), messages);
if (next != -1)
m_startTimes.insert(next, first);
@@ -454,13 +453,15 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
&m_flushTimer, &QTimer::stop);
}
}
+
+ bool useMessageTypes = false;
if (!stream.atEnd())
- stream >> m_useMessageTypes;
+ stream >> useMessageTypes;
// If engineId == -1 objectForId() and then the cast will return 0.
- if (enabled)
+ if (enabled && useMessageTypes) // If the client doesn't support message types don't profile.
startProfiling(qobject_cast<QJSEngine *>(objectForId(engineId)), features);
- else
+ else if (!enabled) // On stopProfiling the client doesn't repeat useMessageTypes.
stopProfiling(qobject_cast<QJSEngine *>(objectForId(engineId)));
stopWaiting();
@@ -486,7 +487,7 @@ void QQmlProfilerServiceImpl::flush()
}
for (QQmlAbstractProfilerAdapter *profiler : qAsConst(reporting))
- profiler->reportData(m_useMessageTypes);
+ profiler->reportData();
}
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
index 2b92a478c1..3791ab29ae 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
@@ -117,7 +117,6 @@ private:
QElapsedTimer m_timer;
QTimer m_flushTimer;
bool m_waitingForStop;
- bool m_useMessageTypes;
bool m_globalEnabled;
quint64 m_globalFeatures;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index f1ac8ef998..e4f2f556fc 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -104,8 +104,7 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
}
-qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
- bool trackLocations)
+qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QQmlDebugPacket d;
@@ -134,24 +133,17 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
appendMemoryEvents(props.start, messages, d);
auto location = m_functionLocations.find(props.id);
- d << props.start << int(RangeStart) << int(Javascript);
- if (trackLocations)
- d << static_cast<qint64>(props.id);
+ d << props.start << int(RangeStart) << int(Javascript) << static_cast<qint64>(props.id);
if (location != m_functionLocations.end()) {
messages.push_back(d.squeezedData());
d.clear();
d << props.start << int(RangeLocation) << int(Javascript) << location->file << location->line
- << location->column;
- if (trackLocations)
- d << static_cast<qint64>(props.id);
+ << location->column << static_cast<qint64>(props.id);
messages.push_back(d.squeezedData());
d.clear();
- d << props.start << int(RangeData) << int(Javascript) << location->name;
-
- if (trackLocations) {
- d << static_cast<qint64>(props.id);
- m_functionLocations.erase(location);
- }
+ d << props.start << int(RangeData) << int(Javascript) << location->name
+ << static_cast<qint64>(props.id);
+ m_functionLocations.erase(location);
}
messages.push_back(d.squeezedData());
d.clear();
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index 2211c82fc5..c4ca38d9b0 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -68,8 +68,7 @@ class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter {
public:
QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine);
- virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
- bool trackLocations) override;
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) override;
void receiveData(const QV4::Profiling::FunctionLocationHash &,
const QVector<QV4::Profiling::FunctionCallProperties> &,
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
index 2c152e4cd5..79a1c82411 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
@@ -152,10 +152,8 @@ static void qQuickProfilerDataToByteArrays(const QQuickProfilerData &data,
}
}
-qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
- bool trackLocations)
+qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
- Q_UNUSED(trackLocations);
while (next < m_data.size()) {
if (m_data[next].time <= until && messages.length() <= s_numMessagesPerBatch)
qQuickProfilerDataToByteArrays(m_data[next++], messages);
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
index 1ad020afd6..1f3467c1d0 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
@@ -61,7 +61,7 @@ class QQuickProfilerAdapter : public QQmlAbstractProfilerAdapter {
public:
QQuickProfilerAdapter(QObject *parent = 0);
~QQuickProfilerAdapter();
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) override;
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages) override;
void receiveData(const QVector<QQuickProfilerData> &new_data);
private:
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index c1e86f0b3c..8293e88038 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -177,14 +177,13 @@ private:
void changeServiceState(const QString &serviceName, QQmlDebugService::State state);
void removeThread();
void receiveMessage();
- void invalidPacket();
+ void protocolError();
QQmlDebugServerConnection *m_connection;
QHash<QString, QQmlDebugService *> m_plugins;
QStringList m_clientPlugins;
bool m_gotHello;
bool m_blockingMode;
- bool m_clientSupportsMultiPackets;
QHash<QJSEngine *, EngineCondition> m_engineConditions;
@@ -277,8 +276,7 @@ static void cleanupOnShutdown()
QQmlDebugServerImpl::QQmlDebugServerImpl() :
m_connection(nullptr),
m_gotHello(false),
- m_blockingMode(false),
- m_clientSupportsMultiPackets(false)
+ m_blockingMode(false)
{
static bool postRoutineAdded = false;
if (!postRoutineAdded) {
@@ -464,10 +462,9 @@ void QQmlDebugServerImpl::receiveMessage()
s_dataStreamVersion = QDataStream::Qt_DefaultCompiledVersion;
}
+ bool clientSupportsMultiPackets = false;
if (!in.atEnd())
- in >> m_clientSupportsMultiPackets;
- else
- m_clientSupportsMultiPackets = false;
+ in >> clientSupportsMultiPackets;
// Send the hello answer immediately, since it needs to arrive before
// the plugins below start sending messages.
@@ -475,13 +472,15 @@ void QQmlDebugServerImpl::receiveMessage()
QQmlDebugPacket out;
QStringList pluginNames;
QList<float> pluginVersions;
- const int count = m_plugins.count();
- pluginNames.reserve(count);
- pluginVersions.reserve(count);
- for (QHash<QString, QQmlDebugService *>::ConstIterator i = m_plugins.constBegin();
- i != m_plugins.constEnd(); ++i) {
- pluginNames << i.key();
- pluginVersions << i.value()->version();
+ if (clientSupportsMultiPackets) { // otherwise, disable all plugins
+ const int count = m_plugins.count();
+ pluginNames.reserve(count);
+ pluginVersions.reserve(count);
+ for (QHash<QString, QQmlDebugService *>::ConstIterator i = m_plugins.constBegin();
+ i != m_plugins.constEnd(); ++i) {
+ pluginNames << i.key();
+ pluginVersions << i.value()->version();
+ }
}
out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
@@ -523,7 +522,7 @@ void QQmlDebugServerImpl::receiveMessage()
} else {
qWarning("QML Debugger: Invalid control message %d.", op);
- invalidPacket();
+ protocolError();
return;
}
@@ -701,16 +700,11 @@ void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &mes
void QQmlDebugServerImpl::sendMessages(const QString &name, const QList<QByteArray> &messages)
{
if (canSendMessage(name)) {
- if (m_clientSupportsMultiPackets) {
- QQmlDebugPacket out;
- out << name;
- for (const QByteArray &message : messages)
- out << message;
- m_protocol->send(out.data());
- } else {
- for (const QByteArray &message : messages)
- doSendMessage(name, message);
- }
+ QQmlDebugPacket out;
+ out << name;
+ for (const QByteArray &message : messages)
+ out << message;
+ m_protocol->send(out.data());
m_connection->flush();
}
}
@@ -743,16 +737,16 @@ void QQmlDebugServerImpl::setDevice(QIODevice *socket)
m_protocol = new QPacketProtocol(socket, this);
QObject::connect(m_protocol, &QPacketProtocol::readyRead,
this, &QQmlDebugServerImpl::receiveMessage);
- QObject::connect(m_protocol, &QPacketProtocol::invalidPacket,
- this, &QQmlDebugServerImpl::invalidPacket);
+ QObject::connect(m_protocol, &QPacketProtocol::error,
+ this, &QQmlDebugServerImpl::protocolError);
if (blockingMode())
m_protocol->waitForReadyRead(-1);
}
-void QQmlDebugServerImpl::invalidPacket()
+void QQmlDebugServerImpl::protocolError()
{
- qWarning("QML Debugger: Received a corrupted packet! Giving up ...");
+ qWarning("QML Debugger: A protocol error has occurred! Giving up ...");
m_connection->disconnect();
// protocol might still be processing packages at this point
m_protocol->deleteLater();
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 119415372b..fd4a3eac65 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -35,7 +35,10 @@ qmldbg_nativedebugger.depends = packetprotocol
qtHaveModule(quick) {
SUBDIRS += \
qmldbg_inspector \
- qmldbg_quickprofiler
+ qmldbg_quickprofiler \
+ qmldbg_preview
+
qmldbg_inspector.depends = packetprotocol
qmldbg_quickprofiler.depends = packetprotocol
+ qmldbg_preview.depends = packetprotocol
}
diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp
index 0bd51cbf46..d728686248 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp
@@ -176,6 +176,12 @@ void QSGOpenVGInternalRectangleNode::setGradientStops(const QGradientStops &stop
m_fillDirty = true;
}
+void QSGOpenVGInternalRectangleNode::setGradientVertical(bool vertical)
+{
+ m_vertical = vertical;
+ m_fillDirty = true;
+}
+
void QSGOpenVGInternalRectangleNode::setRadius(qreal radius)
{
m_radius = radius;
@@ -242,13 +248,13 @@ void QSGOpenVGInternalRectangleNode::render()
} else {
// Linear Gradient
vgSetParameteri(m_rectanglePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
- const VGfloat verticalLinearGradient[] = {
- 0.0f,
+ const VGfloat linearGradient[] = {
0.0f,
0.0f,
- static_cast<VGfloat>(m_rect.height())
+ m_vertical ? 0.0f : static_cast<VGfloat>(m_rect.width()),
+ m_vertical ? static_cast<VGfloat>(m_rect.height()) : 0.0f
};
- vgSetParameterfv(m_rectanglePaint, VG_PAINT_LINEAR_GRADIENT, 4, verticalLinearGradient);
+ vgSetParameterfv(m_rectanglePaint, VG_PAINT_LINEAR_GRADIENT, 4, linearGradient);
vgSetParameteri(m_rectanglePaint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD);
vgSetParameteri(m_rectanglePaint, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, false);
diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h
index e8d25c94f8..86d2c3318c 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h
+++ b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h
@@ -59,6 +59,7 @@ public:
void setPenColor(const QColor &color) override;
void setPenWidth(qreal width) override;
void setGradientStops(const QGradientStops &stops) override;
+ void setGradientVertical(bool vertical) override;
void setRadius(qreal radius) override;
void setAligned(bool aligned) override;
void update() override;
@@ -85,6 +86,7 @@ private:
qreal m_penWidth = 0.0;
qreal m_radius = 0.0;
bool m_aligned = false;
+ bool m_vertical = true;
QGradientStops m_gradientStops;
VGPath m_rectanglePath;
diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp
index 3f33e7e81b..4e82c7a062 100644
--- a/src/qml/animations/qabstractanimationjob.cpp
+++ b/src/qml/animations/qabstractanimationjob.cpp
@@ -78,7 +78,7 @@ QQmlAnimationTimer *QQmlAnimationTimer::instance(bool create)
inst = animationTimer() ? animationTimer()->localData() : 0;
}
#else
- static QAnimationTimer unifiedTimer;
+ static QQmlAnimationTimer unifiedTimer;
inst = &unifiedTimer;
#endif
return inst;
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h
index 63fd4b0dac..0be6ca96ea 100644
--- a/src/qml/animations/qabstractanimationjob_p.h
+++ b/src/qml/animations/qabstractanimationjob_p.h
@@ -56,6 +56,8 @@
#include <QtCore/private/qabstractanimation_p.h>
#include <vector>
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class QAnimationGroupJob;
diff --git a/src/qml/animations/qanimationgroupjob_p.h b/src/qml/animations/qanimationgroupjob_p.h
index fb567dc019..b01b2f3b36 100644
--- a/src/qml/animations/qanimationgroupjob_p.h
+++ b/src/qml/animations/qanimationgroupjob_p.h
@@ -54,6 +54,8 @@
#include "private/qabstractanimationjob_p.h"
#include <QtCore/qdebug.h>
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QAnimationGroupJob : public QAbstractAnimationJob
diff --git a/src/qml/animations/qanimationjobutil_p.h b/src/qml/animations/qanimationjobutil_p.h
index 0bb9e83b2d..e3d6fe9178 100644
--- a/src/qml/animations/qanimationjobutil_p.h
+++ b/src/qml/animations/qanimationjobutil_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+QT_REQUIRE_CONFIG(qml_animation);
+
#define RETURN_IF_DELETED(func) \
{ \
bool *prevWasDeleted = m_wasDeleted; \
diff --git a/src/qml/animations/qcontinuinganimationgroupjob_p.h b/src/qml/animations/qcontinuinganimationgroupjob_p.h
index baf4ff1ae5..c67b8d39ad 100644
--- a/src/qml/animations/qcontinuinganimationgroupjob_p.h
+++ b/src/qml/animations/qcontinuinganimationgroupjob_p.h
@@ -53,6 +53,8 @@
#include "private/qanimationgroupjob_p.h"
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QContinuingAnimationGroupJob : public QAnimationGroupJob
diff --git a/src/qml/animations/qparallelanimationgroupjob_p.h b/src/qml/animations/qparallelanimationgroupjob_p.h
index 67ba626247..0265fe3274 100644
--- a/src/qml/animations/qparallelanimationgroupjob_p.h
+++ b/src/qml/animations/qparallelanimationgroupjob_p.h
@@ -53,6 +53,8 @@
#include "private/qanimationgroupjob_p.h"
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QParallelAnimationGroupJob : public QAnimationGroupJob
diff --git a/src/qml/animations/qpauseanimationjob_p.h b/src/qml/animations/qpauseanimationjob_p.h
index d0e8d57fc7..6c9bbf0dab 100644
--- a/src/qml/animations/qpauseanimationjob_p.h
+++ b/src/qml/animations/qpauseanimationjob_p.h
@@ -53,6 +53,8 @@
#include <private/qanimationgroupjob_p.h>
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QPauseAnimationJob : public QAbstractAnimationJob
diff --git a/src/qml/animations/qsequentialanimationgroupjob_p.h b/src/qml/animations/qsequentialanimationgroupjob_p.h
index 800f0c3b90..13f9806be1 100644
--- a/src/qml/animations/qsequentialanimationgroupjob_p.h
+++ b/src/qml/animations/qsequentialanimationgroupjob_p.h
@@ -53,6 +53,8 @@
#include <private/qanimationgroupjob_p.h>
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class QPauseAnimationJob;
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index 95096db51d..da3c173545 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -11,7 +11,8 @@ HEADERS += \
$$PWD/qv4codegen_p.h \
$$PWD/qqmlirbuilder_p.h \
$$PWD/qqmltypecompiler_p.h \
- $$PWD/qv4instr_moth_p.h
+ $$PWD/qv4instr_moth_p.h \
+ $$PWD/qv4bytecodehandler_p.h
SOURCES += \
$$PWD/qv4bytecodegenerator.cpp \
@@ -21,7 +22,8 @@ SOURCES += \
$$PWD/qv4compilerscanfunctions.cpp \
$$PWD/qv4codegen.cpp \
$$PWD/qqmlirbuilder.cpp \
- $$PWD/qv4instr_moth.cpp
+ $$PWD/qv4instr_moth.cpp \
+ $$PWD/qv4bytecodehandler.cpp
!qmldevtools_build {
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 8a1b3744ee..820f127331 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -96,23 +96,24 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, cons
declarationsOverride = nullptr;
}
-QString Object::sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation)
+QString IRBuilder::sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation)
{
QSet<int> functionNames;
- for (Function *f = functions->first; f; f = f->next) {
- QQmlJS::AST::FunctionDeclaration *function = f->functionDeclaration;
- Q_ASSERT(function);
- *errorLocation = function->identifierToken;
+ for (auto functionit = obj->functionsBegin(); functionit != obj->functionsEnd(); ++functionit) {
+ Function *f = functionit.ptr;
+ errorLocation->startLine = f->location.line;
+ errorLocation->startColumn = f->location.column;
if (functionNames.contains(f->nameIndex))
return tr("Duplicate method name");
functionNames.insert(f->nameIndex);
- for (QmlIR::Signal *s = qmlSignals->first; s; s = s->next) {
+ for (auto signalit = obj->signalsBegin(); signalit != obj->signalsEnd(); ++signalit) {
+ QmlIR::Signal *s = signalit.ptr;
if (s->nameIndex == f->nameIndex)
return tr("Duplicate method name");
}
- const QString name = function->name.toString();
+ const QString name = stringAt(f->nameIndex);
if (name.at(0).isUpper())
return tr("Method names cannot begin with an upper case letter");
if (illegalNames.contains(name))
@@ -497,7 +498,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiObjectBinding *node)
bool IRBuilder::visit(QQmlJS::AST::UiScriptBinding *node)
{
- appendBinding(node->qualifiedId, node->statement);
+ appendBinding(node->qualifiedId, node->statement, node);
return false;
}
@@ -601,7 +602,7 @@ bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qu
return false;
QQmlJS::AST::SourceLocation loc;
- QString error = obj->sanityCheckFunctionNames(illegalNames, &loc);
+ QString error = sanityCheckFunctionNames(obj, illegalNames, &loc);
if (!error.isEmpty()) {
recordError(loc, error);
return false;
@@ -957,7 +958,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
QQmlJS::AST::Node::accept(node->binding, this);
} else if (node->statement) {
if (!isRedundantNullInitializerForPropertyDeclaration(_propertyDeclaration, node->statement))
- appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement, node);
}
qSwap(_propertyDeclaration, property);
}
@@ -971,26 +972,27 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node)
if (QQmlJS::AST::FunctionDeclaration *funDecl = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration *>(node->sourceElement)) {
CompiledFunctionOrExpression *foe = New<CompiledFunctionOrExpression>();
foe->node = funDecl;
+ foe->parentNode = funDecl;
foe->nameIndex = registerString(funDecl->name.toString());
foe->disableAcceleratedLookups = false;
const int index = _object->functionsAndExpressions->append(foe);
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 = index;
f->nameIndex = registerString(funDecl->name.toString());
- int formalsCount = 0;
- for (QQmlJS::AST::FormalParameterList *it = funDecl->formals; it; it = it->next)
- ++formalsCount;
+ const QStringList formals = funDecl->formals ? funDecl->formals->formals() : QStringList();
+ int formalsCount = formals.size();
f->formals.allocate(pool, formalsCount);
int i = 0;
- for (QQmlJS::AST::FormalParameterList *it = funDecl->formals; it; it = it->next, ++i)
- f->formals[i] = registerString(it->name.toString());
+ for (const QString &arg : formals) {
+ f->formals[i] = registerString(arg);
+ ++i;
+ }
_object->appendFunction(f);
} else {
@@ -1044,7 +1046,7 @@ QStringRef IRBuilder::textRefAt(const QQmlJS::AST::SourceLocation &first, const
return QStringRef(&sourceCode, first.offset, last.offset + last.length - first.offset);
}
-void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement)
+void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, QQmlJS::AST::Node *parentNode)
{
QQmlJS::AST::SourceLocation loc = statement->firstSourceLocation();
binding->valueLocation.line = loc.startLine;
@@ -1090,6 +1092,7 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST
CompiledFunctionOrExpression *expr = New<CompiledFunctionOrExpression>();
expr->node = statement;
+ expr->parentNode = parentNode;
expr->nameIndex = registerString(QLatin1String("expression for ")
+ stringAt(binding->propertyNameIndex));
expr->disableAcceleratedLookups = false;
@@ -1216,7 +1219,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
}
}
-void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value)
+void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode)
{
const QQmlJS::AST::SourceLocation qualifiedNameLocation = name->identifierToken;
Object *object = nullptr;
@@ -1227,7 +1230,7 @@ void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Sta
return;
}
qSwap(_object, object);
- appendBinding(qualifiedNameLocation, name->identifierToken, registerString(name->name.toString()), value);
+ appendBinding(qualifiedNameLocation, name->identifierToken, registerString(name->name.toString()), value, parentNode);
qSwap(_object, object);
}
@@ -1242,7 +1245,8 @@ void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex,
qSwap(_object, object);
}
-void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value)
+void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex,
+ QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode)
{
Binding *binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
@@ -1250,7 +1254,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
binding->location.line = nameLocation.startLine;
binding->location.column = nameLocation.startColumn;
binding->flags = 0;
- setBindingValue(binding, value);
+ setBindingValue(binding, value, parentNode);
QString error = bindingsTarget()->appendBinding(binding, /*isListBinding*/false);
if (!error.isEmpty()) {
recordError(qualifiedNameLocation, error);
@@ -1806,24 +1810,36 @@ void JSCodeGen::beginObjectScope(QQmlPropertyCache *scopeObject)
QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions)
{
+ auto qmlName = [&](const CompiledFunctionOrExpression &c) {
+ if (c.nameIndex != 0)
+ return stringPool->stringForIndex(c.nameIndex);
+ else
+ return QStringLiteral("%qml-expression-entry");
+ };
QVector<int> runtimeFunctionIndices(functions.size());
- QV4::Compiler::ScanFunctions scan(this, sourceCode, QV4::Compiler::GlobalCode);
- scan.enterGlobalEnvironment(QV4::Compiler::QmlBinding);
+ QV4::Compiler::ScanFunctions scan(this, sourceCode, QV4::Compiler::ContextType::Global);
+ scan.enterGlobalEnvironment(QV4::Compiler::ContextType::Binding);
for (const CompiledFunctionOrExpression &f : functions) {
Q_ASSERT(f.node != qmlRoot);
+ Q_ASSERT(f.parentNode && f.parentNode != qmlRoot);
QQmlJS::AST::FunctionDeclaration *function = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(f.node);
- if (function)
+ if (function) {
scan.enterQmlFunction(function);
- else
- scan.enterEnvironment(f.node, QV4::Compiler::QmlBinding);
+ } else {
+ Q_ASSERT(f.node != f.parentNode);
+ scan.enterEnvironment(f.parentNode, QV4::Compiler::ContextType::Binding, qmlName(f));
+ }
scan(function ? function->body : f.node);
scan.leaveEnvironment();
}
scan.leaveEnvironment();
+ if (hasError)
+ return QVector<int>();
+
_context = nullptr;
for (int i = 0; i < functions.count(); ++i) {
@@ -1836,15 +1852,13 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
QString name;
if (function)
name = function->name.toString();
- else if (qmlFunction.nameIndex != 0)
- name = stringPool->stringForIndex(qmlFunction.nameIndex);
else
- name = QStringLiteral("%qml-expression-entry");
+ name = qmlName(qmlFunction);
- QQmlJS::AST::SourceElements *body;
- if (function)
- body = function->body ? function->body->elements : nullptr;
- else {
+ QQmlJS::AST::StatementList *body;
+ if (function) {
+ body = function->body;
+ } else {
// Synthesize source elements.
QQmlJS::MemoryPool *pool = jsEngine->pool();
@@ -1854,13 +1868,12 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
QQmlJS::AST::ExpressionNode *expr = node->expressionCast();
stmt = new (pool) QQmlJS::AST::ExpressionStatement(expr);
}
- QQmlJS::AST::SourceElement *element = new (pool) QQmlJS::AST::StatementSourceElement(stmt);
- body = new (pool) QQmlJS::AST::SourceElements(element);
+ body = new (pool) QQmlJS::AST::StatementList(stmt);
body = body->finish();
}
_disableAcceleratedLookups = qmlFunction.disableAcceleratedLookups;
- int idx = defineFunction(name, node,
+ int idx = defineFunction(name, function ? function : qmlFunction.parentNode,
function ? function->formals : nullptr,
body);
runtimeFunctionIndices[i] = idx;
@@ -1869,7 +1882,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
return runtimeFunctionIndices;
}
-int JSCodeGen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::SourceElements *body)
+int JSCodeGen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::StatementList *body)
{
int qmlContextTemp = -1;
int importedScriptsTemp = -1;
@@ -2190,7 +2203,7 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n
// Look for IDs first.
for (const IdMapping &mapping : qAsConst(_idObjects)) {
if (name == mapping.name) {
- if (_context->compilationMode == QV4::Compiler::QmlBinding)
+ if (_context->contextType == QV4::Compiler::ContextType::Binding)
_context->idObjectDependencies.insert(mapping.idIndex);
Instruction::LoadIdObject load;
@@ -2446,8 +2459,6 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
}
}
- QQmlJS::Engine *jsParserEngine = &output->jsParserEngine;
-
const quint32_le *functionIdx = serializedObject->functionOffsetTable();
for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
QmlIR::Function *f = pool->New<QmlIR::Function>();
@@ -2458,26 +2469,10 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
f->location = compiledFunction->location;
f->nameIndex = compiledFunction->nameIndex;
- QQmlJS::AST::FormalParameterList *paramList = nullptr;
- const quint32_le *formalNameIdx = compiledFunction->formalsTable();
- for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx) {
- const QString formal = unit->stringAt(*formalNameIdx);
- QStringRef paramNameRef = jsParserEngine->newStringRef(formal);
-
- if (paramList)
- paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, paramNameRef);
- else
- paramList = new (pool) QQmlJS::AST::FormalParameterList(paramNameRef);
- }
-
- if (paramList)
- paramList = paramList->finish();
-
const QString name = unit->stringAt(compiledFunction->nameIndex);
- f->functionDeclaration = new(pool) QQmlJS::AST::FunctionDeclaration(jsParserEngine->newStringRef(name), paramList, /*body*/nullptr);
f->formals.allocate(pool, int(compiledFunction->nFormals));
- formalNameIdx = compiledFunction->formalsTable();
+ const quint32_le *formalNameIdx = compiledFunction->formalsTable();
for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
f->formals[i] = *formalNameIdx;
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 689b232b1c..f8d481e14f 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -57,7 +57,6 @@
#include <private/qqmljsmemorypool_p.h>
#include <private/qv4codegen_p.h>
#include <private/qv4compiler_p.h>
-#include <private/qqmljslexer_p.h>
#include <QTextStream>
#include <QCoreApplication>
@@ -325,7 +324,6 @@ struct Alias : public QV4::CompiledData::Alias
struct Function
{
- QQmlJS::AST::FunctionDeclaration *functionDeclaration;
QV4::CompiledData::Location location;
int nameIndex;
quint32 index; // index in parsedQML::functions
@@ -342,12 +340,9 @@ struct Function
struct Q_QML_PRIVATE_EXPORT CompiledFunctionOrExpression
{
CompiledFunctionOrExpression()
-
{}
- CompiledFunctionOrExpression(QQmlJS::AST::Node *n)
- : node(n)
- {}
+ QQmlJS::AST::Node *parentNode = nullptr; // FunctionDeclaration, Statement or Expression
QQmlJS::AST::Node *node = nullptr; // FunctionDeclaration, Statement or Expression
quint32 nameIndex = 0;
bool disableAcceleratedLookups = false;
@@ -400,8 +395,6 @@ public:
void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation());
- QString sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
-
QString appendEnum(Enum *enumeration);
QString appendSignal(Signal *signal);
QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
@@ -520,12 +513,12 @@ public:
QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first,
const QQmlJS::AST::SourceLocation &last) const;
- void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement);
+ void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, AST::Node *parentNode);
void tryGeneratingTranslationBinding(const QStringRef &base, QQmlJS::AST::ArgumentList *args, QV4::CompiledData::Binding *binding);
- void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value);
+ void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, AST::Node *parentNode);
void appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment = false);
- void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value);
+ void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value, AST::Node *parentNode);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false);
bool appendAlias(QQmlJS::AST::UiPublicMember *node);
@@ -548,6 +541,8 @@ public:
static bool isStatementNodeScript(QQmlJS::AST::Statement *statement);
static bool isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement);
+ QString sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
+
QList<QQmlJS::DiagnosticMessage> errors;
QSet<QString> illegalNames;
@@ -578,7 +573,7 @@ private:
#ifndef V4_BOOTSTRAP
struct Q_QML_EXPORT PropertyResolver
{
- PropertyResolver(const QQmlPropertyCache *cache)
+ PropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
: cache(cache)
{}
@@ -597,7 +592,7 @@ struct Q_QML_EXPORT PropertyResolver
// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
- const QQmlPropertyCache *cache;
+ QQmlRefPointer<QQmlPropertyCache> cache;
};
#endif
@@ -623,7 +618,7 @@ struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
int defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
- AST::SourceElements *body) override;
+ AST::StatementList *body) override;
protected:
void beginFunctionBodyHook() override;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 8bbc8291b4..02517ea6bb 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -99,8 +99,8 @@ public:
protected:
QQmlCompileError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context);
- QQmlPropertyCache *propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlCompileError *error) const;
- QQmlCompileError createMetaObject(int objectIndex, const CompiledObject *obj, QQmlPropertyCache *baseTypeCache);
+ QQmlRefPointer<QQmlPropertyCache> propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlCompileError *error) const;
+ QQmlCompileError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache);
QString stringAt(int index) const { return objectContainer->stringAt(index); }
@@ -152,7 +152,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
auto *typeRef = objectContainer->resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
- QQmlPropertyCache *baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ QQmlRefPointer<QQmlPropertyCache> baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
QQmlCompileError error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache);
if (error.isSet())
return error;
@@ -166,7 +166,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
}
}
- QQmlPropertyCache *baseTypeCache;
+ QQmlRefPointer<QQmlPropertyCache> baseTypeCache;
{
QQmlCompileError error;
baseTypeCache = propertyCacheForObject(obj, context, &error);
@@ -209,7 +209,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
}
template <typename ObjectContainer>
-inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlCompileError *error) const
+inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlCompileError *error) const
{
if (context.instantiatingProperty) {
return context.instantiatingPropertyCache(enginePrivate);
@@ -241,14 +241,12 @@ inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCac
QString propertyName = stringAt(context.instantiatingBinding->propertyNameIndex);
if (imports->resolveType(propertyName, &qmltype, nullptr, nullptr, nullptr)) {
if (qmltype.isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
+ QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
auto compilationUnit = tdata->compilationUnit();
qmltype = QQmlMetaType::qmlType(compilationUnit->metaTypeId);
-
- tdata->release();
}
}
}
@@ -264,7 +262,7 @@ inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCac
}
template <typename ObjectContainer>
-inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int objectIndex, const CompiledObject *obj, QQmlPropertyCache *baseTypeCache)
+inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache)
{
QQmlRefPointer<QQmlPropertyCache> cache;
cache.adopt(baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(),
@@ -314,7 +312,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
}
}
if (newClassName.isEmpty()) {
- newClassName = QQmlMetaObject(baseTypeCache).className();
+ newClassName = QQmlMetaObject(baseTypeCache.data()).className();
newClassName.append("_QML_");
newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
}
@@ -354,7 +352,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
// 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;
+ QQmlPropertyCache *parentCache = cache.data();
while ((parentCache = parentCache->parent())) {
if (int pSigCount = parentCache->signalCount()) {
int pSigOffset = parentCache->signalOffset();
@@ -440,15 +438,13 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
return QQmlCompileError(s->location, QQmlPropertyCacheCreatorBase::tr("Invalid signal parameter type: %1").arg(customTypeName));
if (qmltype.isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
+ QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
auto compilationUnit = tdata->compilationUnit();
paramTypes[i + 1] = compilationUnit->metaTypeId;
-
- tdata->release();
} else {
paramTypes[i + 1] = qmltype.typeId();
}
@@ -523,7 +519,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
Q_ASSERT(qmltype.isValid());
if (qmltype.isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
+ QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
@@ -534,8 +530,6 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
} else {
propertyType = compilationUnit->listMetaTypeId;
}
-
- tdata->release();
} else {
if (p->type == QV4::CompiledData::Property::Custom) {
propertyType = qmltype.typeId();
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index ffd3b5975a..afa2e4ad81 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -45,8 +45,9 @@
QT_BEGIN_NAMESPACE
-QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, QV4::CompiledData::CompilationUnit *compilationUnit)
+QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
: enginePrivate(enginePrivate)
+ , compilationUnit(compilationUnit)
, imports(imports)
, qmlUnit(compilationUnit->data)
, resolvedTypes(compilationUnit->resolvedTypes)
@@ -629,7 +630,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(binding->value.objectIndex);
if (auto *typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex)) {
- QQmlPropertyCache *cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ QQmlRefPointer<QQmlPropertyCache> cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
const QMetaObject *mo = cache->firstCppMetaObject();
QQmlType qmlType;
while (mo && !qmlType.isValid()) {
@@ -670,7 +671,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
return noError;
} else if (QQmlValueTypeFactory::isValueType(property->propType())) {
- return QQmlCompileError(binding->location, tr("Unexpected object assignment"));
+ return QQmlCompileError(binding->location, tr("Unexpected object assignment for property \"%1\"").arg(propertyName));
} else if (property->propType() == qMetaTypeId<QQmlScriptString>()) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected"));
} else {
@@ -680,7 +681,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
// Using -1 for the minor version ensures that we get the raw metaObject.
QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType(), -1);
- // Will be true if the assgned type inherits propertyMetaObject
+ // Will be true if the assigned type inherits propertyMetaObject
bool isAssignable = false;
// Determine isAssignable value
if (propertyMetaObject) {
@@ -692,7 +693,8 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
}
if (!isAssignable) {
- return QQmlCompileError(binding->valueLocation, tr("Cannot assign object to property"));
+ return QQmlCompileError(binding->valueLocation, tr("Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.")
+ .arg(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex)).arg(QLatin1String(QMetaType::typeName(property->propType()))));
}
}
return noError;
diff --git a/src/qml/compiler/qqmlpropertyvalidator_p.h b/src/qml/compiler/qqmlpropertyvalidator_p.h
index e37b8141f4..a8f75a0a7e 100644
--- a/src/qml/compiler/qqmlpropertyvalidator_p.h
+++ b/src/qml/compiler/qqmlpropertyvalidator_p.h
@@ -58,7 +58,7 @@ class QQmlPropertyValidator
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
- QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, QV4::CompiledData::CompilationUnit *compilationUnit);
+ QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
QVector<QQmlCompileError> validate();
@@ -74,6 +74,7 @@ private:
QString stringAt(int index) const { return qmlUnit->stringAt(index); }
QQmlEnginePrivate *enginePrivate;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
const QQmlImports &imports;
const QV4::CompiledData::Unit *qmlUnit;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index a896745b3f..37271e2c54 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -67,7 +67,7 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *type
{
}
-QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
+QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
{
// Build property caches and VME meta object data
@@ -147,7 +147,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
document->jsModule.fileName = typeData->urlString();
document->jsModule.finalUrl = typeData->finalUrlString();
QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine,
- document->program, typeNameCache, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
+ document->program, typeNameCache.data(), &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
v4CodeGenerator.setUseFastLookups(false);
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
@@ -165,7 +165,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
// The js unit owns the data and will free the qml unit.
document->javaScriptCompilationUnit->data = qmlUnit;
- QV4::CompiledData::CompilationUnit *compilationUnit = document->javaScriptCompilationUnit;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = document->javaScriptCompilationUnit;
compilationUnit = document->javaScriptCompilationUnit;
compilationUnit->typeNameCache = typeNameCache;
compilationUnit->resolvedTypes = resolvedTypes;
@@ -339,14 +339,12 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (!type.isValid()) {
if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) {
if (type.isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type.sourceUrl());
+ QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(type.sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
auto compilationUnit = tdata->compilationUnit();
type = QQmlMetaType::qmlType(compilationUnit->metaTypeId);
-
- tdata->release();
}
}
}
@@ -466,14 +464,12 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
for (const QString &param : qAsConst(parameters)) {
QStringRef paramNameRef = compiler->newStringRef(param);
- if (paramList)
- paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, paramNameRef);
- else
- paramList = new (pool) QQmlJS::AST::FormalParameterList(paramNameRef);
+ QQmlJS::AST::PatternElement *b = new (pool) QQmlJS::AST::PatternElement(paramNameRef, nullptr);
+ paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, b);
}
if (paramList)
- paramList = paramList->finish();
+ paramList = paramList->finish(pool);
QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex);
QQmlJS::AST::FunctionDeclaration *functionDeclaration = nullptr;
@@ -490,11 +486,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
if (!functionDeclaration) {
QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(foe->node);
- QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement);
- QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement);
- elements = elements->finish();
-
- QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements);
+ QQmlJS::AST::StatementList *body = new (pool) QQmlJS::AST::StatementList(statement);
+ body = body->finish();
functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body);
functionDeclaration->lbraceToken = functionDeclaration->functionToken
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index b8eddcb9b2..537f87ab4c 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -92,7 +92,7 @@ public:
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypes;
// ---
- QV4::CompiledData::CompilationUnit *compile();
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile();
QList<QQmlError> compilationErrors() const { return errors; }
void recordError(QQmlError error);
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 4d50654d27..7e1f49ee86 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -70,14 +70,14 @@ int BytecodeGenerator::newRegisterArray(int n)
void BytecodeGenerator::packInstruction(I &i)
{
- uchar type = *reinterpret_cast<uchar *>(i.packed);
- Q_ASSERT(type >= MOTH_NUM_INSTRUCTIONS());
- if (type >= MOTH_NUM_INSTRUCTIONS())
- type -= MOTH_NUM_INSTRUCTIONS();
+ Instr::Type type = Instr::unpack(i.packed);
+ Q_ASSERT(int(type) < MOTH_NUM_INSTRUCTIONS());
+ type = Instr::narrowInstructionType(type);
int instructionsAsInts[sizeof(Instr)/sizeof(int)] = {};
int nMembers = Moth::InstrInfo::argumentCount[static_cast<int>(i.type)];
+ uchar *code = i.packed + Instr::encodedLength(type);
for (int j = 0; j < nMembers; ++j) {
- instructionsAsInts[j] = qFromLittleEndian<qint32>(i.packed + 1 + j * sizeof(int));
+ instructionsAsInts[j] = qFromLittleEndian<qint32>(code + j * sizeof(int));
}
enum {
Normal,
@@ -89,11 +89,10 @@ void BytecodeGenerator::packInstruction(I &i)
break;
}
}
- char *code = i.packed;
+ code = i.packed;
switch (width) {
case Normal:
- *reinterpret_cast<uchar *>(code) = type;
- ++code;
+ code = Instr::pack(code, type);
for (int n = 0; n < nMembers; ++n) {
qint8 v = static_cast<qint8>(instructionsAsInts[n]);
memcpy(code, &v, 1);
@@ -122,7 +121,7 @@ void BytecodeGenerator::adjustJumpOffsets()
// qDebug() << "adjusting jump offset for instruction" << index << i.position << i.size << "offsetForJump" << i.offsetForJump << "target"
// << labels.at(i.linkedLabel) << linkedInstruction.position << "jumpOffset" << jumpOffset;
uchar type = *reinterpret_cast<const uchar *>(i.packed);
- if (type >= MOTH_NUM_INSTRUCTIONS()) {
+ if (Instr::isWide(Instr::Type(type))) {
Q_ASSERT(i.offsetForJump == i.size - 4);
qToLittleEndian<qint32>(jumpOffset, c);
} else {
@@ -177,7 +176,7 @@ void BytecodeGenerator::finalize(Compiler::Context *context)
entry.line = currentLine;
lineNumbers.append(entry);
}
- code.append(i.packed, i.size);
+ code.append(reinterpret_cast<const char *>(i.packed), i.size);
}
context->code = code;
@@ -185,6 +184,25 @@ void BytecodeGenerator::finalize(Compiler::Context *context)
}
int BytecodeGenerator::addInstructionHelper(Instr::Type type, const Instr &i, int offsetOfOffset) {
+ if (lastInstrType == int(Instr::Type::StoreReg)) {
+ if (type == Instr::Type::LoadReg) {
+ if (i.LoadReg.reg == lastInstr.StoreReg.reg) {
+ // value is already in the accumulator
+ return -1;
+ }
+ }
+ if (type == Instr::Type::MoveReg) {
+ if (i.MoveReg.srcReg == lastInstr.StoreReg.reg) {
+ Instruction::StoreReg store;
+ store.reg = i.MoveReg.destReg;
+ addInstruction(store);
+ return -1;
+ }
+ }
+ }
+ lastInstrType = int(type);
+ lastInstr = i;
+
#if QT_CONFIG(qml_debug)
if (debugMode && type != Instr::Type::Debug) {
QT_WARNING_PUSH
@@ -207,12 +225,10 @@ QT_WARNING_POP
const int argCount = Moth::InstrInfo::argumentCount[static_cast<int>(type)];
int s = argCount*sizeof(int);
if (offsetOfOffset != -1)
- offsetOfOffset += 1;
- I instr{type, static_cast<short>(s + 1), 0, currentLine, offsetOfOffset, -1, "\0\0" };
- char *code = instr.packed;
- *reinterpret_cast<uchar *>(code) = static_cast<uchar>(MOTH_NUM_INSTRUCTIONS() + static_cast<int>(type));
- ++code;
- Q_ASSERT(MOTH_NUM_INSTRUCTIONS() + static_cast<int>(type) < 256);
+ offsetOfOffset += Instr::encodedLength(type);
+ I instr{type, static_cast<short>(s + Instr::encodedLength(type)), 0, currentLine, offsetOfOffset, -1, "\0\0" };
+ uchar *code = instr.packed;
+ code = Instr::pack(code, Instr::wideInstructionType(type));
for (int j = 0; j < argCount; ++j) {
qToLittleEndian<qint32>(i.argumentsAsInts[j], code);
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index e69f2cd310..dca5771356 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -77,22 +77,18 @@ public:
Label(BytecodeGenerator *generator, LinkMode mode = LinkNow)
: generator(generator),
index(generator->labels.size()) {
- generator->labels.append(mode == LinkNow ? generator->instructions.size() : -1);
- }
- static Label returnLabel() {
- Label l;
- l.index = INT_MAX;
- return l;
- }
- bool isReturn() const {
- return index == INT_MAX;
+ generator->labels.append(-1);
+ if (mode == LinkNow)
+ link();
}
void link() {
Q_ASSERT(index >= 0);
Q_ASSERT(generator->labels[index] == -1);
generator->labels[index] = generator->instructions.size();
+ generator->clearLastInstruction();
}
+ bool isValid() const { return generator != nullptr; }
BytecodeGenerator *generator = nullptr;
int index = -1;
@@ -133,14 +129,16 @@ public:
};
struct ExceptionHandler : public Label {
+ ExceptionHandler() = default;
ExceptionHandler(BytecodeGenerator *generator)
: Label(generator, LinkLater)
{
}
~ExceptionHandler()
{
- Q_ASSERT(generator->currentExceptionHandler != this);
+ Q_ASSERT(!generator || generator->currentExceptionHandler != this);
}
+ bool isValid() const { return generator != nullptr; }
};
Label label() {
@@ -181,6 +179,18 @@ public:
return addJumpInstruction(data);
}
+ Q_REQUIRED_RESULT Jump jumpNotUndefined()
+ {
+ Instruction::JumpNotUndefined data;
+ return addJumpInstruction(data);
+ }
+
+ Q_REQUIRED_RESULT Jump jumpNoException()
+ {
+ Instruction::JumpNoException data;
+ return addJumpInstruction(data);
+ }
+
void jumpStrictEqual(const StackSlot &lhs, const Label &target)
{
Instruction::CmpStrictEqual cmp;
@@ -197,26 +207,10 @@ public:
addJumpInstruction(Instruction::JumpTrue()).link(target);
}
- Q_REQUIRED_RESULT Jump jumpStrictEqualStackSlotInt(const StackSlot &lhs, int rhs)
- {
- Instruction::JumpStrictEqualStackSlotInt data;
- data.lhs = lhs;
- data.rhs = rhs;
- return addJumpInstruction(data);
- }
-
- Q_REQUIRED_RESULT Jump jumpStrictNotEqualStackSlotInt(const StackSlot &lhs, int rhs)
- {
- Instruction::JumpStrictNotEqualStackSlotInt data;
- data.lhs = lhs;
- data.rhs = rhs;
- return addJumpInstruction(data);
- }
-
- void setExceptionHandler(ExceptionHandler *handler)
+ void setUnwindHandler(ExceptionHandler *handler)
{
currentExceptionHandler = handler;
- Instruction::SetExceptionHandler data;
+ Instruction::SetUnwindHandler data;
data.offset = 0;
if (!handler)
addInstruction(data);
@@ -224,6 +218,19 @@ public:
addJumpInstruction(data).link(*handler);
}
+ void unwindToLabel(int level, const Label &target)
+ {
+ if (level) {
+ Instruction::UnwindToLabel unwind;
+ unwind.level = level;
+ addJumpInstruction(unwind).link(target);
+ } else {
+ jump().link(target);
+ }
+ }
+
+
+
void setLocation(const QQmlJS::AST::SourceLocation &loc);
ExceptionHandler *exceptionHandler() const {
@@ -233,6 +240,7 @@ public:
int newRegister();
int newRegisterArray(int n);
int registerCount() const { return regCount; }
+ int currentRegister() const { return currentReg; }
void finalize(Compiler::Context *context);
@@ -252,6 +260,11 @@ public:
addJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
}
+ void clearLastInstruction()
+ {
+ lastInstrType = -1;
+ }
+
private:
friend struct Jump;
friend struct Label;
@@ -266,7 +279,7 @@ private:
int line;
int offsetForJump;
int linkedLabel;
- char packed[sizeof(Instr) + 2]; // 2 for instruction and prefix
+ unsigned char packed[sizeof(Instr) + 2]; // 2 for instruction type
};
void compressInstructions();
@@ -275,7 +288,7 @@ private:
QVector<I> instructions;
QVector<int> labels;
- ExceptionHandler *currentExceptionHandler;
+ ExceptionHandler *currentExceptionHandler = nullptr;
int regCount = 0;
public:
int currentReg = 0;
@@ -283,6 +296,9 @@ private:
int startLine = 0;
int currentLine = 0;
bool debugMode = false;
+
+ int lastInstrType = -1;
+ Moth::Instr lastInstr;
};
}
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
new file mode 100644
index 0000000000..23f7051718
--- /dev/null
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -0,0 +1,529 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qv4bytecodehandler_p.h>
+
+QT_USE_NAMESPACE
+using namespace QV4;
+using namespace Moth;
+
+ByteCodeHandler::~ByteCodeHandler()
+{
+}
+
+#define DISPATCH_INSTRUCTION(name, nargs, ...) \
+ generate_##name( \
+ __VA_ARGS__ \
+ );
+
+#define DECODE_AND_DISPATCH(instr) \
+ { \
+ INSTR_##instr(MOTH_DECODE_WITH_BASE) \
+ Q_UNUSED(base_ptr); \
+ startInstruction(Instr::Type::instr); \
+ _offset = code - start; \
+ INSTR_##instr(DISPATCH) \
+ endInstruction(Instr::Type::instr); \
+ continue; \
+ }
+
+void ByteCodeHandler::decode(const char *code, uint len)
+{
+ MOTH_JUMP_TABLE;
+
+ const char *start = code;
+ const char *end = code + len;
+ while (code < end) {
+ MOTH_DISPATCH()
+
+ FOR_EACH_MOTH_INSTR(DECODE_AND_DISPATCH)
+ }
+}
+
+#undef DECODE_AND_DISPATCH
+#undef DISPATCH_INSTRUCTION
+
+#define MOTH_UNUSED_ARGS0()
+#define MOTH_UNUSED_ARGS1(arg) \
+ Q_UNUSED(arg);
+#define MOTH_UNUSED_ARGS2(arg1, arg2) \
+ Q_UNUSED(arg1); \
+ Q_UNUSED(arg2);
+#define MOTH_UNUSED_ARGS3(arg1, arg2, arg3) \
+ Q_UNUSED(arg1); \
+ Q_UNUSED(arg2); \
+ Q_UNUSED(arg3);
+#define MOTH_UNUSED_ARGS4(arg1, arg2, arg3, arg4) \
+ Q_UNUSED(arg1); \
+ Q_UNUSED(arg2); \
+ Q_UNUSED(arg3); \
+ Q_UNUSED(arg4);
+
+#define MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, ...) \
+ MOTH_EXPAND_FOR_MSVC(MOTH_UNUSED_ARGS##nargs(__VA_ARGS__))
+
+#define MOTH_MARK_ARGS_UNUSED_INSTRUCTION(name, nargs, ...) \
+ MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, __VA_ARGS__)
+
+#define COLLECTOR_BEGIN_INSTR(instr) \
+ { \
+ INSTR_##instr(MOTH_DECODE_WITH_BASE) \
+ INSTR_##instr(MOTH_MARK_ARGS_UNUSED) \
+ Q_UNUSED(base_ptr);
+
+#define COLLECTOR_END_INSTR(instr) \
+ continue; \
+ }
+
+std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint len)
+{
+ MOTH_JUMP_TABLE;
+
+ std::vector<int> labels;
+
+ const auto addLabel = [&labels,len](int offset) {
+ Q_ASSERT(offset >= 0 && offset < static_cast<int>(len));
+ labels.push_back(offset);
+ };
+
+ const char *start = code;
+ const char *end = code + len;
+ while (code < end) {
+ MOTH_DISPATCH()
+ Q_UNREACHABLE();
+
+ COLLECTOR_BEGIN_INSTR(LoadReg)
+ COLLECTOR_END_INSTR(LoadReg)
+
+ COLLECTOR_BEGIN_INSTR(StoreReg)
+ COLLECTOR_END_INSTR(StoreReg)
+
+ COLLECTOR_BEGIN_INSTR(MoveReg)
+ COLLECTOR_END_INSTR(MoveReg)
+
+ COLLECTOR_BEGIN_INSTR(LoadConst)
+ COLLECTOR_END_INSTR(LoadConst)
+
+ COLLECTOR_BEGIN_INSTR(LoadNull)
+ COLLECTOR_END_INSTR(LoadNull)
+
+ COLLECTOR_BEGIN_INSTR(LoadZero)
+ COLLECTOR_END_INSTR(LoadZero)
+
+ COLLECTOR_BEGIN_INSTR(LoadTrue)
+ COLLECTOR_END_INSTR(LoadTrue)
+
+ COLLECTOR_BEGIN_INSTR(LoadFalse)
+ COLLECTOR_END_INSTR(LoadFalse)
+
+ COLLECTOR_BEGIN_INSTR(LoadUndefined)
+ COLLECTOR_END_INSTR(LoadUndefined)
+
+ COLLECTOR_BEGIN_INSTR(LoadInt)
+ COLLECTOR_END_INSTR(LoadInt)
+
+ COLLECTOR_BEGIN_INSTR(MoveConst)
+ COLLECTOR_END_INSTR(MoveConst)
+
+ COLLECTOR_BEGIN_INSTR(LoadLocal)
+ COLLECTOR_END_INSTR(LoadLocal)
+
+ COLLECTOR_BEGIN_INSTR(StoreLocal)
+ COLLECTOR_END_INSTR(StoreLocal)
+
+ COLLECTOR_BEGIN_INSTR(LoadScopedLocal)
+ COLLECTOR_END_INSTR(LoadScopedLocal)
+
+ COLLECTOR_BEGIN_INSTR(StoreScopedLocal)
+ COLLECTOR_END_INSTR(StoreScopedLocal)
+
+ COLLECTOR_BEGIN_INSTR(LoadRuntimeString)
+ COLLECTOR_END_INSTR(LoadRuntimeString)
+
+ COLLECTOR_BEGIN_INSTR(MoveRegExp)
+ COLLECTOR_END_INSTR(MoveRegExp)
+
+ COLLECTOR_BEGIN_INSTR(LoadClosure)
+ COLLECTOR_END_INSTR(LoadClosure)
+
+ COLLECTOR_BEGIN_INSTR(LoadName)
+ COLLECTOR_END_INSTR(LoadName)
+
+ COLLECTOR_BEGIN_INSTR(LoadGlobalLookup)
+ COLLECTOR_END_INSTR(LoadGlobalLookup)
+
+ COLLECTOR_BEGIN_INSTR(StoreNameSloppy)
+ COLLECTOR_END_INSTR(StoreNameSloppy)
+
+ COLLECTOR_BEGIN_INSTR(StoreNameStrict)
+ COLLECTOR_END_INSTR(StoreNameStrict)
+
+ COLLECTOR_BEGIN_INSTR(LoadElement)
+ COLLECTOR_END_INSTR(LoadElement)
+
+ COLLECTOR_BEGIN_INSTR(StoreElement)
+ COLLECTOR_END_INSTR(StoreElement)
+
+ COLLECTOR_BEGIN_INSTR(LoadProperty)
+ COLLECTOR_END_INSTR(LoadProperty)
+
+ COLLECTOR_BEGIN_INSTR(GetLookup)
+ COLLECTOR_END_INSTR(GetLookup)
+
+ COLLECTOR_BEGIN_INSTR(StoreProperty)
+ COLLECTOR_END_INSTR(StoreProperty)
+
+ COLLECTOR_BEGIN_INSTR(SetLookup)
+ COLLECTOR_END_INSTR(SetLookup)
+
+ COLLECTOR_BEGIN_INSTR(LoadSuperProperty)
+ COLLECTOR_END_INSTR(LoadSuperProperty)
+
+ COLLECTOR_BEGIN_INSTR(StoreSuperProperty)
+ COLLECTOR_END_INSTR(StoreSuperProperty)
+
+ COLLECTOR_BEGIN_INSTR(StoreScopeObjectProperty)
+ COLLECTOR_END_INSTR(StoreScopeObjectProperty)
+
+ COLLECTOR_BEGIN_INSTR(LoadScopeObjectProperty)
+ COLLECTOR_END_INSTR(LoadScopeObjectProperty)
+
+ COLLECTOR_BEGIN_INSTR(StoreContextObjectProperty)
+ COLLECTOR_END_INSTR(StoreContextObjectProperty)
+
+ COLLECTOR_BEGIN_INSTR(LoadContextObjectProperty)
+ COLLECTOR_END_INSTR(LoadContextObjectProperty)
+
+ COLLECTOR_BEGIN_INSTR(LoadIdObject)
+ COLLECTOR_END_INSTR(LoadIdObject)
+
+ COLLECTOR_BEGIN_INSTR(Yield)
+ COLLECTOR_END_INSTR(Yield)
+
+ COLLECTOR_BEGIN_INSTR(Resume)
+ COLLECTOR_END_INSTR(Resume)
+
+ COLLECTOR_BEGIN_INSTR(CallValue)
+ COLLECTOR_END_INSTR(CallValue)
+
+ COLLECTOR_BEGIN_INSTR(CallProperty)
+ COLLECTOR_END_INSTR(CallProperty)
+
+ COLLECTOR_BEGIN_INSTR(CallPropertyLookup)
+ COLLECTOR_END_INSTR(CallPropertyLookup)
+
+ COLLECTOR_BEGIN_INSTR(CallElement)
+ COLLECTOR_END_INSTR(CallElement)
+
+ COLLECTOR_BEGIN_INSTR(CallName)
+ COLLECTOR_END_INSTR(CallName)
+
+ COLLECTOR_BEGIN_INSTR(CallPossiblyDirectEval)
+ COLLECTOR_END_INSTR(CallPossiblyDirectEval)
+
+ COLLECTOR_BEGIN_INSTR(CallGlobalLookup)
+ COLLECTOR_END_INSTR(CallGlobalLookup)
+
+ COLLECTOR_BEGIN_INSTR(CallScopeObjectProperty)
+ COLLECTOR_END_INSTR(CallScopeObjectProperty)
+
+ COLLECTOR_BEGIN_INSTR(CallContextObjectProperty)
+ COLLECTOR_END_INSTR(CallContextObjectProperty)
+
+ COLLECTOR_BEGIN_INSTR(CallWithSpread)
+ COLLECTOR_END_INSTR(CallWithSpread)
+
+ COLLECTOR_BEGIN_INSTR(Construct)
+ COLLECTOR_END_INSTR(Construct)
+
+ COLLECTOR_BEGIN_INSTR(ConstructWithSpread)
+ COLLECTOR_END_INSTR(ConstructWithSpread)
+
+ COLLECTOR_BEGIN_INSTR(SetUnwindHandler)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(SetUnwindHandler)
+
+ COLLECTOR_BEGIN_INSTR(UnwindDispatch)
+ COLLECTOR_END_INSTR(UnwindDispatch)
+
+ COLLECTOR_BEGIN_INSTR(UnwindToLabel)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(UnwindToLabel)
+
+ COLLECTOR_BEGIN_INSTR(ThrowException)
+ COLLECTOR_END_INSTR(ThrowException)
+
+ COLLECTOR_BEGIN_INSTR(GetException)
+ COLLECTOR_END_INSTR(HasException)
+
+ COLLECTOR_BEGIN_INSTR(SetException)
+ COLLECTOR_END_INSTR(SetExceptionFlag)
+
+ COLLECTOR_BEGIN_INSTR(CreateCallContext)
+ COLLECTOR_END_INSTR(CreateCallContext)
+
+ COLLECTOR_BEGIN_INSTR(PushCatchContext)
+ COLLECTOR_END_INSTR(PushCatchContext)
+
+ COLLECTOR_BEGIN_INSTR(PushWithContext)
+ COLLECTOR_END_INSTR(PushWithContext)
+
+ COLLECTOR_BEGIN_INSTR(PushBlockContext)
+ COLLECTOR_END_INSTR(PushBlockContext)
+
+ COLLECTOR_BEGIN_INSTR(CloneBlockContext)
+ COLLECTOR_END_INSTR(CloneBlockContext)
+
+ COLLECTOR_BEGIN_INSTR(PushScriptContext)
+ COLLECTOR_END_INSTR(PushScriptContext)
+
+ COLLECTOR_BEGIN_INSTR(PopScriptContext)
+ COLLECTOR_END_INSTR(PopScriptContext)
+
+ COLLECTOR_BEGIN_INSTR(PopContext)
+ COLLECTOR_END_INSTR(PopContext)
+
+ COLLECTOR_BEGIN_INSTR(GetIterator)
+ COLLECTOR_END_INSTR(GetIterator)
+
+ COLLECTOR_BEGIN_INSTR(IteratorNext)
+ COLLECTOR_END_INSTR(IteratorNext)
+
+ COLLECTOR_BEGIN_INSTR(IteratorClose)
+ COLLECTOR_END_INSTR(IteratorClose)
+
+ COLLECTOR_BEGIN_INSTR(DestructureRestElement)
+ COLLECTOR_END_INSTR(DestructureRestElement)
+
+ COLLECTOR_BEGIN_INSTR(DeleteProperty)
+ COLLECTOR_END_INSTR(DeleteProperty)
+
+ COLLECTOR_BEGIN_INSTR(DeleteName)
+ COLLECTOR_END_INSTR(DeleteName)
+
+ COLLECTOR_BEGIN_INSTR(TypeofName)
+ COLLECTOR_END_INSTR(TypeofName)
+
+ COLLECTOR_BEGIN_INSTR(TypeofValue)
+ COLLECTOR_END_INSTR(TypeofValue)
+
+ COLLECTOR_BEGIN_INSTR(DeclareVar)
+ COLLECTOR_END_INSTR(DeclareVar)
+
+ COLLECTOR_BEGIN_INSTR(DefineArray)
+ COLLECTOR_END_INSTR(DefineArray)
+
+ COLLECTOR_BEGIN_INSTR(DefineObjectLiteral)
+ COLLECTOR_END_INSTR(DefineObjectLiteral)
+
+ COLLECTOR_BEGIN_INSTR(CreateClass)
+ COLLECTOR_END_INSTR(CreateClass)
+
+ COLLECTOR_BEGIN_INSTR(CreateMappedArgumentsObject)
+ COLLECTOR_END_INSTR(CreateMappedArgumentsObject)
+
+ COLLECTOR_BEGIN_INSTR(CreateUnmappedArgumentsObject)
+ COLLECTOR_END_INSTR(CreateUnmappedArgumentsObject)
+
+ COLLECTOR_BEGIN_INSTR(CreateRestParameter)
+ COLLECTOR_END_INSTR(CreateRestParameter)
+
+ COLLECTOR_BEGIN_INSTR(ConvertThisToObject)
+ COLLECTOR_END_INSTR(ConvertThisToObject)
+
+ COLLECTOR_BEGIN_INSTR(LoadSuperConstructor)
+ COLLECTOR_END_INSTR(LoadSuperConstructor)
+
+ COLLECTOR_BEGIN_INSTR(ToObject)
+ COLLECTOR_END_INSTR(ToObject)
+
+ COLLECTOR_BEGIN_INSTR(Jump)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(Jump)
+
+ COLLECTOR_BEGIN_INSTR(JumpTrue)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(JumpTrue)
+
+ COLLECTOR_BEGIN_INSTR(JumpFalse)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(JumpFalse)
+
+ COLLECTOR_BEGIN_INSTR(JumpNoException)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(JumpNoException)
+
+ COLLECTOR_BEGIN_INSTR(JumpNotUndefined)
+ addLabel(code - start + offset);
+ COLLECTOR_END_INSTR(JumpNotUndefined)
+
+ COLLECTOR_BEGIN_INSTR(CmpEqNull)
+ COLLECTOR_END_INSTR(CmpEqNull)
+
+ COLLECTOR_BEGIN_INSTR(CmpNeNull)
+ COLLECTOR_END_INSTR(CmpNeNull)
+
+ COLLECTOR_BEGIN_INSTR(CmpEqInt)
+ COLLECTOR_END_INSTR(CmpEq)
+
+ COLLECTOR_BEGIN_INSTR(CmpNeInt)
+ COLLECTOR_END_INSTR(CmpNeInt)
+
+ COLLECTOR_BEGIN_INSTR(CmpEq)
+ COLLECTOR_END_INSTR(CmpEq)
+
+ COLLECTOR_BEGIN_INSTR(CmpNe)
+ COLLECTOR_END_INSTR(CmpNe)
+
+ COLLECTOR_BEGIN_INSTR(CmpGt)
+ COLLECTOR_END_INSTR(CmpGt)
+
+ COLLECTOR_BEGIN_INSTR(CmpGe)
+ COLLECTOR_END_INSTR(CmpGe)
+
+ COLLECTOR_BEGIN_INSTR(CmpLt)
+ COLLECTOR_END_INSTR(CmpLt)
+
+ COLLECTOR_BEGIN_INSTR(CmpLe)
+ COLLECTOR_END_INSTR(CmpLe)
+
+ COLLECTOR_BEGIN_INSTR(CmpStrictEqual)
+ COLLECTOR_END_INSTR(CmpStrictEqual)
+
+ COLLECTOR_BEGIN_INSTR(CmpStrictNotEqual)
+ COLLECTOR_END_INSTR(CmpStrictNotEqual)
+
+ COLLECTOR_BEGIN_INSTR(CmpIn)
+ COLLECTOR_END_INSTR(CmpIn)
+
+ COLLECTOR_BEGIN_INSTR(CmpInstanceOf)
+ COLLECTOR_END_INSTR(CmpInstanceOf)
+
+ COLLECTOR_BEGIN_INSTR(UNot)
+ COLLECTOR_END_INSTR(UNot)
+
+ COLLECTOR_BEGIN_INSTR(UPlus)
+ COLLECTOR_END_INSTR(UPlus)
+
+ COLLECTOR_BEGIN_INSTR(UMinus)
+ COLLECTOR_END_INSTR(UMinus)
+
+ COLLECTOR_BEGIN_INSTR(UCompl)
+ COLLECTOR_END_INSTR(UCompl)
+
+ COLLECTOR_BEGIN_INSTR(Increment)
+ COLLECTOR_END_INSTR(PreIncrement)
+
+ COLLECTOR_BEGIN_INSTR(Decrement)
+ COLLECTOR_END_INSTR(PreDecrement)
+
+ COLLECTOR_BEGIN_INSTR(Add)
+ COLLECTOR_END_INSTR(Add)
+
+ COLLECTOR_BEGIN_INSTR(BitAnd)
+ COLLECTOR_END_INSTR(BitAnd)
+
+ COLLECTOR_BEGIN_INSTR(BitOr)
+ COLLECTOR_END_INSTR(BitOr)
+
+ COLLECTOR_BEGIN_INSTR(BitXor)
+ COLLECTOR_END_INSTR(BitXor)
+
+ COLLECTOR_BEGIN_INSTR(UShr)
+ COLLECTOR_END_INSTR(UShr)
+
+ COLLECTOR_BEGIN_INSTR(Shr)
+ COLLECTOR_END_INSTR(Shr)
+
+ COLLECTOR_BEGIN_INSTR(Shl)
+ COLLECTOR_END_INSTR(Shl)
+
+ COLLECTOR_BEGIN_INSTR(BitAndConst)
+ COLLECTOR_END_INSTR(BitAndConst)
+
+ COLLECTOR_BEGIN_INSTR(BitOrConst)
+ COLLECTOR_END_INSTR(BitOr)
+
+ COLLECTOR_BEGIN_INSTR(BitXorConst)
+ COLLECTOR_END_INSTR(BitXor)
+
+ COLLECTOR_BEGIN_INSTR(UShrConst)
+ COLLECTOR_END_INSTR(UShrConst)
+
+ COLLECTOR_BEGIN_INSTR(ShrConst)
+ COLLECTOR_END_INSTR(ShrConst)
+
+ COLLECTOR_BEGIN_INSTR(ShlConst)
+ COLLECTOR_END_INSTR(ShlConst)
+
+ COLLECTOR_BEGIN_INSTR(Exp)
+ COLLECTOR_END_INSTR(Exp)
+
+ COLLECTOR_BEGIN_INSTR(Mul)
+ COLLECTOR_END_INSTR(Mul)
+
+ COLLECTOR_BEGIN_INSTR(Div)
+ COLLECTOR_END_INSTR(Div)
+
+ COLLECTOR_BEGIN_INSTR(Mod)
+ COLLECTOR_END_INSTR(Mod)
+
+ COLLECTOR_BEGIN_INSTR(Sub)
+ COLLECTOR_END_INSTR(Sub)
+
+ COLLECTOR_BEGIN_INSTR(Ret)
+ COLLECTOR_END_INSTR(Ret)
+
+#ifndef QT_NO_QML_DEBUGGER
+ COLLECTOR_BEGIN_INSTR(Debug)
+ COLLECTOR_END_INSTR(Debug)
+#endif // QT_NO_QML_DEBUGGER
+
+ COLLECTOR_BEGIN_INSTR(LoadQmlContext)
+ COLLECTOR_END_INSTR(LoadQmlContext)
+
+ COLLECTOR_BEGIN_INSTR(LoadQmlImportedScripts)
+ COLLECTOR_END_INSTR(LoadQmlImportedScripts)
+ }
+
+ return labels;
+}
+
+#undef COLLECTOR_BEGIN_INSTR
+#undef COLLECTOR_END_INSTR
diff --git a/src/qml/compiler/qv4bytecodehandler_p.h b/src/qml/compiler/qv4bytecodehandler_p.h
new file mode 100644
index 0000000000..5f1121306f
--- /dev/null
+++ b/src/qml/compiler/qv4bytecodehandler_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4BYTECODEHANDLER_P_H
+#define QV4BYTECODEHANDLER_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/qv4instr_moth_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace Moth {
+
+#define BYTECODE_HANDLER_DEFINE_ARGS(nargs, ...) \
+ MOTH_EXPAND_FOR_MSVC(BYTECODE_HANDLER_DEFINE_ARGS##nargs(__VA_ARGS__))
+
+#define BYTECODE_HANDLER_DEFINE_ARGS0()
+#define BYTECODE_HANDLER_DEFINE_ARGS1(arg) \
+ int arg
+#define BYTECODE_HANDLER_DEFINE_ARGS2(arg1, arg2) \
+ int arg1, \
+ int arg2
+#define BYTECODE_HANDLER_DEFINE_ARGS3(arg1, arg2, arg3) \
+ int arg1, \
+ int arg2, \
+ int arg3
+#define BYTECODE_HANDLER_DEFINE_ARGS4(arg1, arg2, arg3, arg4) \
+ int arg1, \
+ int arg2, \
+ int arg3, \
+ int arg4
+
+#define BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER_INSTRUCTION(name, nargs, ...) \
+ virtual void generate_##name( \
+ BYTECODE_HANDLER_DEFINE_ARGS(nargs, __VA_ARGS__) \
+ ) = 0;
+
+#define BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER(instr) \
+ INSTR_##instr(BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER)
+
+class ByteCodeHandler
+{
+public:
+ virtual ~ByteCodeHandler();
+
+ void decode(const char *code, uint len);
+
+ int instructionOffset() const { return _offset; }
+
+ static std::vector<int> collectLabelsInBytecode(const char *code, uint len);
+
+protected:
+ FOR_EACH_MOTH_INSTR(BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER)
+
+ virtual void startInstruction(Moth::Instr::Type instr) = 0;
+ virtual void endInstruction(Moth::Instr::Type instr) = 0;
+
+private:
+ int _offset = 0;
+};
+
+} // Moth namespace
+} // QV4 namespace
+
+QT_END_NAMESPACE
+
+#endif // QV4BYTECODEHANDLER_P_H
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index e831fd48f5..4b766accbd 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -58,6 +58,8 @@
#include <cmath>
#include <iostream>
+static const bool disable_lookups = false;
+
#ifdef CONST
#undef CONST
#endif
@@ -77,8 +79,6 @@ static inline void setJumpOutLocation(QV4::Moth::BytecodeGenerator *bytecodeGene
case Statement::Kind_ForEachStatement:
case Statement::Kind_ForStatement:
case Statement::Kind_IfStatement:
- case Statement::Kind_LocalForEachStatement:
- case Statement::Kind_LocalForStatement:
case Statement::Kind_WhileStatement:
bytecodeGenerator->setLocation(fallback);
break;
@@ -90,7 +90,7 @@ static inline void setJumpOutLocation(QV4::Moth::BytecodeGenerator *bytecodeGene
Codegen::Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict)
: _module(nullptr)
- , _returnAddress(0)
+ , _returnAddress(-1)
, _context(nullptr)
, _labelledStatement(nullptr)
, jsUnitGenerator(jsUnitGenerator)
@@ -106,7 +106,7 @@ void Codegen::generateFromProgram(const QString &fileName,
const QString &sourceCode,
Program *node,
Module *module,
- CompilationMode mode)
+ ContextType contextType)
{
Q_ASSERT(node);
@@ -117,10 +117,13 @@ void Codegen::generateFromProgram(const QString &fileName,
_module->fileName = fileName;
_module->finalUrl = finalUrl;
- ScanFunctions scan(this, sourceCode, mode);
+ ScanFunctions scan(this, sourceCode, contextType);
scan(node);
- defineFunction(QStringLiteral("%entry"), node, nullptr, node->elements);
+ if (hasError)
+ return;
+
+ defineFunction(QStringLiteral("%entry"), node, nullptr, node->statements);
}
void Codegen::enterContext(Node *node)
@@ -132,19 +135,24 @@ void Codegen::enterContext(Node *node)
int Codegen::leaveContext()
{
Q_ASSERT(_context);
- Q_ASSERT(!_context->controlFlow);
int functionIndex = _context->functionIndex;
_context = _context->parent;
return functionIndex;
}
+Context *Codegen::enterBlock(Node *node)
+{
+ enterContext(node);
+ return _context;
+}
+
Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
{
if (hasError)
return _expr.result();
#ifndef V4_BOOTSTRAP
- if (expr.isConst()) {
+ if (expr.isConstant()) {
auto v = Value::fromReturnedValue(expr.constant);
if (v.isNumber()) {
switch (op) {
@@ -267,9 +275,9 @@ void Codegen::statement(Statement *ast)
bytecodeGenerator->setLocation(ast->firstSourceLocation());
VolatileMemoryLocations vLocs = scanVolatileMemoryLocations(ast);
- qSwap(_volataleMemoryLocations, vLocs);
+ qSwap(_volatileMemoryLocations, vLocs);
accept(ast);
- qSwap(_volataleMemoryLocations, vLocs);
+ qSwap(_volatileMemoryLocations, vLocs);
}
void Codegen::statement(ExpressionNode *ast)
@@ -282,11 +290,11 @@ void Codegen::statement(ExpressionNode *ast)
Result r(nx);
qSwap(_expr, r);
VolatileMemoryLocations vLocs = scanVolatileMemoryLocations(ast);
- qSwap(_volataleMemoryLocations, vLocs);
+ qSwap(_volatileMemoryLocations, vLocs);
accept(ast);
- qSwap(_volataleMemoryLocations, vLocs);
+ qSwap(_volatileMemoryLocations, vLocs);
qSwap(_expr, r);
if (hasError)
@@ -337,60 +345,103 @@ Codegen::Reference Codegen::expression(ExpressionNode *ast)
return r.result();
}
-Codegen::Result Codegen::sourceElement(SourceElement *ast)
+void Codegen::program(Program *ast)
{
- Result r(nx);
if (ast) {
- qSwap(_expr, r);
- accept(ast);
- qSwap(_expr, r);
+ statementList(ast->statements);
}
- return r;
}
-void Codegen::functionBody(FunctionBody *ast)
-{
- if (ast)
- sourceElements(ast->elements);
-}
+enum class CompletionState {
+ Empty,
+ EmptyAbrupt,
+ NonEmpty
+};
-void Codegen::program(Program *ast)
-{
- if (ast) {
- sourceElements(ast->elements);
+static CompletionState completionState(StatementList *list)
+{
+ for (StatementList *it = list; it; it = it->next) {
+ if (it->statement->kind == Statement::Kind_BreakStatement ||
+ it->statement->kind == Statement::Kind_ContinueStatement)
+ return CompletionState::EmptyAbrupt;
+ if (it->statement->kind == Statement::Kind_EmptyStatement ||
+ it->statement->kind == Statement::Kind_VariableDeclaration ||
+ it->statement->kind == Statement::Kind_FunctionDeclaration)
+ continue;
+ if (it->statement->kind == Statement::Kind_Block) {
+ CompletionState subState = completionState(static_cast<Block *>(it->statement)->statements);
+ if (subState != CompletionState::Empty)
+ return subState;
+ continue;
+ }
+ return CompletionState::NonEmpty;
}
+ return CompletionState::Empty;
}
-void Codegen::sourceElements(SourceElements *ast)
+static Node *completionStatement(StatementList *list)
{
- bool _requiresReturnValue = false;
- qSwap(_requiresReturnValue, requiresReturnValue);
- for (SourceElements *it = ast; it; it = it->next) {
- if (!it->next)
- qSwap(_requiresReturnValue, requiresReturnValue);
- sourceElement(it->element);
- if (hasError)
- return;
- if (StatementSourceElement *sse = AST::cast<StatementSourceElement *>(it->element)) {
- if (AST::cast<ThrowStatement *>(sse->statement) ||
- AST::cast<ReturnStatement *>(sse->statement))
- return;
+ Node *completionStatement = nullptr;
+ for (StatementList *it = list; it; it = it->next) {
+ if (it->statement->kind == Statement::Kind_BreakStatement ||
+ it->statement->kind == Statement::Kind_ContinueStatement)
+ return completionStatement;
+ if (it->statement->kind == Statement::Kind_ThrowStatement ||
+ it->statement->kind == Statement::Kind_ReturnStatement)
+ return it->statement;
+ if (it->statement->kind == Statement::Kind_EmptyStatement ||
+ it->statement->kind == Statement::Kind_VariableStatement ||
+ it->statement->kind == Statement::Kind_FunctionDeclaration)
+ continue;
+ if (it->statement->kind == Statement::Kind_Block) {
+ CompletionState state = completionState(static_cast<Block *>(it->statement)->statements);
+ switch (state) {
+ case CompletionState::Empty:
+ continue;
+ case CompletionState::EmptyAbrupt:
+ return it->statement;
+ case CompletionState::NonEmpty:
+ break;
+ }
}
+ completionStatement = it->statement;
}
+ return completionStatement;
}
void Codegen::statementList(StatementList *ast)
{
+ if (!ast)
+ return;
+
bool _requiresReturnValue = requiresReturnValue;
- requiresReturnValue = false;
- for (StatementList *it = ast; it; it = it->next) {
- if (!it->next ||
- it->next->statement->kind == Statement::Kind_BreakStatement ||
- it->next->statement->kind == Statement::Kind_ContinueStatement ||
- it->next->statement->kind == Statement::Kind_ReturnStatement)
- requiresReturnValue = _requiresReturnValue;
- statement(it->statement);
+ // ### the next line is pessimizing a bit too much, as there are many cases, where the complietion from the break
+ // statement will not be used, but it's at least spec compliant
+ if (!controlFlow || !controlFlow->hasLoop())
requiresReturnValue = false;
+
+ Node *needsCompletion = nullptr;
+
+ if (_requiresReturnValue && !requiresReturnValue)
+ needsCompletion = completionStatement(ast);
+
+ if (requiresReturnValue && !needsCompletion && !insideSwitch) {
+ // break or continue is the first real statement, set the return value to undefined
+ Reference::fromConst(this, Encode::undefined()).storeOnStack(_returnAddress);
+ }
+
+ bool _insideSwitch = insideSwitch;
+ insideSwitch = false;
+
+ for (StatementList *it = ast; it; it = it->next) {
+ if (it->statement == needsCompletion)
+ requiresReturnValue = true;
+ if (Statement *s = it->statement->statementCast())
+ statement(s);
+ else
+ statement(static_cast<ExpressionNode *>(it->statement));
+ if (it->statement == needsCompletion)
+ requiresReturnValue = false;
if (it->statement->kind == Statement::Kind_ThrowStatement ||
it->statement->kind == Statement::Kind_BreakStatement ||
it->statement->kind == Statement::Kind_ContinueStatement ||
@@ -399,22 +450,16 @@ void Codegen::statementList(StatementList *ast)
break;
}
requiresReturnValue = _requiresReturnValue;
+ insideSwitch = _insideSwitch;
}
-void Codegen::variableDeclaration(VariableDeclaration *ast)
+void Codegen::variableDeclaration(PatternElement *ast)
{
RegisterScope scope(this);
- if (!ast->expression)
+ if (!ast->initializer)
return;
- Reference rhs = expression(ast->expression);
- if (hasError)
- return;
-
- Reference lhs = referenceForName(ast->name.toString(), true);
- //### if lhs is a temp, this won't generate a temp-to-temp move. Same for when rhs is a const
- rhs.loadInAccumulator();
- lhs.storeConsumeAccumulator();
+ initializeAndDestructureBindingElement(ast, Reference(), /*isDefinition*/ true);
}
void Codegen::variableDeclarationList(VariableDeclarationList *ast)
@@ -424,6 +469,200 @@ void Codegen::variableDeclarationList(VariableDeclarationList *ast)
}
}
+Codegen::Reference Codegen::targetForPatternElement(AST::PatternElement *p)
+{
+ if (!p->bindingIdentifier.isNull())
+ return referenceForName(p->bindingIdentifier.toString(), true);
+ if (!p->bindingTarget || p->destructuringPattern())
+ return Codegen::Reference::fromStackSlot(this);
+ Reference lhs = expression(p->bindingTarget);
+ if (hasError)
+ return lhs;
+ lhs = lhs.asLValue();
+ return lhs;
+}
+
+void Codegen::initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &base, bool isDefinition)
+{
+ Q_ASSERT(e->type == AST::PatternElement::Binding || e->type == AST::PatternElement::RestElement);
+ RegisterScope scope(this);
+ Reference baseRef = (base.isAccumulator()) ? base.storeOnStack() : base;
+ Reference varToStore = targetForPatternElement(e);
+ if (isDefinition)
+ varToStore.isReferenceToConst = false;
+ if (hasError)
+ return;
+
+ if (e->initializer) {
+ if (!baseRef.isValid()) {
+ // assignment
+ Reference expr = expression(e->initializer);
+ if (hasError)
+ return;
+ expr.loadInAccumulator();
+ varToStore.storeConsumeAccumulator();
+ } else if (baseRef == varToStore) {
+ baseRef.loadInAccumulator();
+ BytecodeGenerator::Jump jump = bytecodeGenerator->jumpNotUndefined();
+ Reference expr = expression(e->initializer);
+ if (hasError) {
+ jump.link();
+ return;
+ }
+ expr.loadInAccumulator();
+ varToStore.storeConsumeAccumulator();
+ jump.link();
+ } else {
+ baseRef.loadInAccumulator();
+ BytecodeGenerator::Jump jump = bytecodeGenerator->jumpNotUndefined();
+ Reference expr = expression(e->initializer);
+ if (hasError) {
+ jump.link();
+ return;
+ }
+ expr.loadInAccumulator();
+ jump.link();
+ varToStore.storeConsumeAccumulator();
+ }
+ } else if (baseRef != varToStore && baseRef.isValid()) {
+ baseRef.loadInAccumulator();
+ varToStore.storeConsumeAccumulator();
+ }
+ Pattern *p = e->destructuringPattern();
+ if (!p)
+ return;
+
+ if (!varToStore.isStackSlot())
+ varToStore = varToStore.storeOnStack();
+ if (PatternElementList *l = e->elementList()) {
+ destructureElementList(varToStore, l, isDefinition);
+ } else if (PatternPropertyList *p = e->propertyList()) {
+ destructurePropertyList(varToStore, p, isDefinition);
+ } else if (e->bindingTarget) {
+ // empty binding pattern. For spec compatibility, try to coerce the argument to an object
+ varToStore.loadInAccumulator();
+ Instruction::ToObject toObject;
+ bytecodeGenerator->addInstruction(toObject);
+ return;
+ }
+}
+
+Codegen::Reference Codegen::referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name)
+{
+ AST::ComputedPropertyName *cname = AST::cast<AST::ComputedPropertyName *>(name);
+ Reference property;
+ if (cname) {
+ Reference computedName = expression(cname->expression);
+ if (hasError)
+ return Reference();
+ computedName = computedName.storeOnStack();
+ property = Reference::fromSubscript(object, computedName).asLValue();
+ } else {
+ QString propertyName = name->asString();
+ property = Reference::fromMember(object, propertyName);
+ }
+ return property;
+}
+
+void Codegen::destructurePropertyList(const Codegen::Reference &object, PatternPropertyList *bindingList, bool isDefinition)
+{
+ RegisterScope scope(this);
+
+ for (PatternPropertyList *it = bindingList; it; it = it->next) {
+ PatternProperty *p = it->property;
+ RegisterScope scope(this);
+ Reference property = referenceForPropertyName(object, p->name);
+ if (hasError)
+ return;
+ initializeAndDestructureBindingElement(p, property, isDefinition);
+ if (hasError)
+ return;
+ }
+}
+
+void Codegen::destructureElementList(const Codegen::Reference &array, PatternElementList *bindingList, bool isDefinition)
+{
+ RegisterScope scope(this);
+
+ Reference iterator = Reference::fromStackSlot(this);
+ Reference iteratorValue = Reference::fromStackSlot(this);
+ Reference iteratorDone = Reference::fromStackSlot(this);
+
+ array.loadInAccumulator();
+ Instruction::GetIterator iteratorObjInstr;
+ iteratorObjInstr.iterator = 1; // ForEachType::Of
+ bytecodeGenerator->addInstruction(iteratorObjInstr);
+ iterator.storeConsumeAccumulator();
+
+ bool hadNext = false;
+ bool hasRest = false;
+
+ BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
+
+ for (PatternElementList *p = bindingList; p; p = p->next) {
+ PatternElement *e = p->element;
+ for (Elision *elision = p->elision; elision; elision = elision->next) {
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.value = iteratorValue.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ hadNext = true;
+ bool last = !elision->next && !e && !p->next;
+ if (last)
+ iteratorDone.storeConsumeAccumulator();
+ }
+
+ if (!e)
+ continue;
+
+ hadNext = true;
+ RegisterScope scope(this);
+ iterator.loadInAccumulator();
+
+ if (e->type == PatternElement::RestElement) {
+ bytecodeGenerator->addInstruction(Instruction::DestructureRestElement());
+ initializeAndDestructureBindingElement(e, Reference::fromAccumulator(this), isDefinition);
+ hasRest = true;
+ } else {
+ Instruction::IteratorNext next;
+ next.value = iteratorValue.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ bool last = !p->next || (!p->next->elision && !p->next->element);
+ if (last)
+ iteratorDone.storeConsumeAccumulator();
+ initializeAndDestructureBindingElement(e, iteratorValue, isDefinition);
+ if (hasError) {
+ end.link();
+ return;
+ }
+ }
+ }
+
+ if (!hadNext) {
+ Reference::storeConstOnStack(this, Encode(false), iteratorDone.stackSlot());
+ }
+
+ if (!hasRest) {
+ iterator.loadInAccumulator();
+ Instruction::IteratorClose close;
+ close.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(close);
+ }
+
+ end.link();
+}
+
+void Codegen::destructurePattern(Pattern *p, const Reference &rhs)
+{
+ RegisterScope scope(this);
+ if (auto *o = AST::cast<ObjectPattern *>(p))
+ destructurePropertyList(rhs, o->properties);
+ else if (auto *a = AST::cast<ArrayPattern *>(p))
+ destructureElementList(rhs, a->elements);
+ else
+ Q_UNREACHABLE();
+}
+
bool Codegen::visit(ArgumentList *)
{
@@ -461,12 +700,6 @@ bool Codegen::visit(DefaultClause *)
return false;
}
-bool Codegen::visit(ElementList *)
-{
- Q_UNREACHABLE();
- return false;
-}
-
bool Codegen::visit(Elision *)
{
Q_UNREACHABLE();
@@ -485,37 +718,31 @@ bool Codegen::visit(FormalParameterList *)
return false;
}
-bool Codegen::visit(FunctionBody *)
-{
- Q_UNREACHABLE();
- return false;
-}
-
bool Codegen::visit(Program *)
{
Q_UNREACHABLE();
return false;
}
-bool Codegen::visit(PropertyAssignmentList *)
+bool Codegen::visit(PatternElement *)
{
Q_UNREACHABLE();
return false;
}
-bool Codegen::visit(PropertyNameAndValue *)
+bool Codegen::visit(PatternElementList *)
{
Q_UNREACHABLE();
return false;
}
-bool Codegen::visit(PropertyGetterSetter *)
+bool Codegen::visit(PatternProperty *)
{
Q_UNREACHABLE();
return false;
}
-bool Codegen::visit(SourceElements *)
+bool Codegen::visit(PatternPropertyList *)
{
Q_UNREACHABLE();
return false;
@@ -587,15 +814,121 @@ bool Codegen::visit(UiQualifiedPragmaId *)
return false;
}
-bool Codegen::visit(VariableDeclaration *)
+bool Codegen::visit(VariableDeclarationList *)
{
Q_UNREACHABLE();
return false;
}
-bool Codegen::visit(VariableDeclarationList *)
+bool Codegen::visit(ClassExpression *ast)
{
- Q_UNREACHABLE();
+ Compiler::Class jsClass;
+ jsClass.nameIndex = registerString(ast->name.toString());
+
+ ClassElementList *constructor = nullptr;
+ int nComputedNames = 0;
+ int nStaticComputedNames = 0;
+
+ RegisterScope scope(this);
+ ControlFlowBlock controlFlow(this, ast);
+
+ for (auto *member = ast->elements; member; member = member->next) {
+ PatternProperty *p = member->property;
+ FunctionExpression *f = p->initializer->asFunctionDefinition();
+ Q_ASSERT(f);
+ AST::ComputedPropertyName *cname = AST::cast<ComputedPropertyName *>(p->name);
+ if (cname) {
+ ++nComputedNames;
+ if (member->isStatic)
+ ++nStaticComputedNames;
+ }
+ QString name = p->name->asString();
+ uint nameIndex = cname ? UINT_MAX : registerString(name);
+ Compiler::Class::Method::Type type = Compiler::Class::Method::Regular;
+ if (p->type == PatternProperty::Getter)
+ type = Compiler::Class::Method::Getter;
+ else if (p->type == PatternProperty::Setter)
+ type = Compiler::Class::Method::Setter;
+ Compiler::Class::Method m{ nameIndex, type, static_cast<uint>(defineFunction(name, f, f->formals, f->body)) };
+
+ if (member->isStatic) {
+ if (name == QStringLiteral("prototype")) {
+ throwSyntaxError(ast->firstSourceLocation(), QLatin1String("Cannot declare a static method named 'prototype'."));
+ return false;
+ }
+ jsClass.staticMethods << m;
+ } else {
+ if (name == QStringLiteral("constructor")) {
+ if (constructor) {
+ throwSyntaxError(ast->firstSourceLocation(), QLatin1String("Cannot declare a multiple constructors in a class."));
+ return false;
+ }
+ if (m.type != Compiler::Class::Method::Regular) {
+ throwSyntaxError(ast->firstSourceLocation(), QLatin1String("Cannot declare a getter or setter named 'constructor'."));
+ return false;
+ }
+ constructor = member;
+ jsClass.constructorIndex = m.functionIndex;
+ continue;
+ }
+
+ jsClass.methods << m;
+ }
+ }
+
+ int classIndex = _module->classes.size();
+ _module->classes.append(jsClass);
+
+ Reference heritage = Reference::fromStackSlot(this);
+ if (ast->heritage) {
+ bytecodeGenerator->setLocation(ast->heritage->firstSourceLocation());
+ Reference r = expression(ast->heritage);
+ if (hasError)
+ return false;
+ r.storeOnStack(heritage.stackSlot());
+ } else {
+ Reference::fromConst(this, Primitive::emptyValue().asReturnedValue()).loadInAccumulator();
+ heritage.storeConsumeAccumulator();
+ }
+
+ int computedNames = nComputedNames ? bytecodeGenerator->newRegisterArray(nComputedNames) : 0;
+ int currentStaticName = computedNames;
+ int currentNonStaticName = computedNames + nStaticComputedNames;
+
+ for (auto *member = ast->elements; member; member = member->next) {
+ AST::ComputedPropertyName *cname = AST::cast<AST::ComputedPropertyName *>(member->property->name);
+ if (!cname)
+ continue;
+ RegisterScope scope(this);
+ bytecodeGenerator->setLocation(cname->firstSourceLocation());
+ Reference computedName = expression(cname->expression);
+ if (hasError)
+ return false;
+ computedName.storeOnStack(member->isStatic ? currentStaticName++ : currentNonStaticName++);
+ }
+
+ Instruction::CreateClass createClass;
+ createClass.classIndex = classIndex;
+ createClass.heritage = heritage.stackSlot();
+ createClass.computedNames = computedNames;
+
+ bytecodeGenerator->addInstruction(createClass);
+
+ if (!ast->name.isEmpty()) {
+ Reference ctor = referenceForName(ast->name.toString(), true);
+ ctor.isReferenceToConst = false; // this is the definition
+ (void) ctor.storeRetainAccumulator();
+ }
+
+ _expr.setResult(Reference::fromAccumulator(this));
+ return false;
+}
+
+bool Codegen::visit(ClassDeclaration *ast)
+{
+ Reference outerVar = referenceForName(ast->name.toString(), true);
+ visit(static_cast<ClassExpression *>(ast));
+ (void) outerVar.storeRetainAccumulator();
return false;
}
@@ -609,50 +942,160 @@ bool Codegen::visit(Expression *ast)
return false;
}
-bool Codegen::visit(ArrayLiteral *ast)
+bool Codegen::visit(ArrayPattern *ast)
{
if (hasError)
return false;
- RegisterScope scope(this);
+ PatternElementList *it = ast->elements;
int argc = 0;
- int args = -1;
- auto push = [this, &argc, &args](AST::ExpressionNode *arg) {
- int temp = bytecodeGenerator->newRegister();
- if (args == -1)
- args = temp;
- if (!arg) {
- auto c = Reference::fromConst(this, Primitive::emptyValue().asReturnedValue());
- (void) c.storeOnStack(temp);
- } else {
- RegisterScope scope(this);
- (void) expression(arg).storeOnStack(temp);
+ {
+ RegisterScope scope(this);
+
+ int args = -1;
+ auto push = [this, &argc, &args](AST::ExpressionNode *arg) {
+ int temp = bytecodeGenerator->newRegister();
+ if (args == -1)
+ args = temp;
+ if (!arg) {
+ auto c = Reference::fromConst(this, Primitive::emptyValue().asReturnedValue());
+ (void) c.storeOnStack(temp);
+ } else {
+ RegisterScope scope(this);
+ Reference r = expression(arg);
+ if (hasError)
+ return;
+ (void) r.storeOnStack(temp);
+ }
+ ++argc;
+ };
+
+ for (; it; it = it->next) {
+ PatternElement *e = it->element;
+ if (e && e->type == PatternElement::SpreadElement)
+ break;
+ for (Elision *elision = it->elision; elision; elision = elision->next)
+ push(nullptr);
+
+ if (!e)
+ continue;
+
+ push(e->initializer);
+ if (hasError)
+ return false;
}
- ++argc;
- };
- for (ElementList *it = ast->elements; it; it = it->next) {
+ if (args == -1) {
+ Q_ASSERT(argc == 0);
+ args = 0;
+ }
- for (Elision *elision = it->elision; elision; elision = elision->next)
- push(nullptr);
+ Instruction::DefineArray call;
+ call.argc = argc;
+ call.args = Moth::StackSlot::createRegister(args);
+ bytecodeGenerator->addInstruction(call);
+ }
- push(it->expression);
- if (hasError)
- return false;
+ if (!it) {
+ _expr.setResult(Reference::fromAccumulator(this));
+ return false;
}
- for (Elision *elision = ast->elision; elision; elision = elision->next)
- push(nullptr);
+ Q_ASSERT(it->element && it->element->type == PatternElement::SpreadElement);
- if (args == -1) {
- Q_ASSERT(argc == 0);
- args = 0;
+ RegisterScope scope(this);
+ Reference array = Reference::fromStackSlot(this);
+ array.storeConsumeAccumulator();
+ Reference index = Reference::storeConstOnStack(this, Encode(argc));
+
+ auto pushAccumulator = [&]() {
+ Reference slot = Reference::fromSubscript(array, index);
+ slot.storeConsumeAccumulator();
+
+ index.loadInAccumulator();
+ Instruction::Increment inc;
+ bytecodeGenerator->addInstruction(inc);
+ index.storeConsumeAccumulator();
+ };
+
+ while (it) {
+ for (Elision *elision = it->elision; elision; elision = elision->next) {
+ Reference::fromConst(this, Primitive::emptyValue().asReturnedValue()).loadInAccumulator();
+ pushAccumulator();
+ }
+
+ if (!it->element) {
+ it = it->next;
+ continue;
+ }
+
+ // handle spread element
+ if (it->element->type == PatternElement::SpreadElement) {
+ RegisterScope scope(this);
+
+ Reference iterator = Reference::fromStackSlot(this);
+ Reference lhsValue = Reference::fromStackSlot(this);
+
+ // There should be a temporal block, so that variables declared in lhs shadow outside vars.
+ // This block should define a temporal dead zone for those variables, which is not yet implemented.
+ {
+ RegisterScope innerScope(this);
+ Reference expr = expression(it->element->initializer);
+ if (hasError)
+ return false;
+
+ expr.loadInAccumulator();
+ Instruction::GetIterator iteratorObjInstr;
+ iteratorObjInstr.iterator = /*ForEachType::Of*/ 1;
+ bytecodeGenerator->addInstruction(iteratorObjInstr);
+ iterator.storeConsumeAccumulator();
+ }
+
+ BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
+ BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
+ BytecodeGenerator::Label done = bytecodeGenerator->newLabel();
+
+ {
+ ControlFlowLoop flow(this, &end, &in, /*requiresUnwind*/ true);
+ bytecodeGenerator->jump().link(in);
+
+ BytecodeGenerator::Label body = bytecodeGenerator->label();
+
+ lhsValue.loadInAccumulator();
+ pushAccumulator();
+
+ in.link();
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.value = lhsValue.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
+ bytecodeGenerator->jump().link(done);
+ }
+
+ end.link();
+
+ Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack();
+ iterator.loadInAccumulator();
+ Instruction::IteratorClose close;
+ close.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(close);
+
+ done.link();
+ } else {
+ RegisterScope innerScope(this);
+ Reference expr = expression(it->element->initializer);
+ if (hasError)
+ return false;
+
+ expr.loadInAccumulator();
+ pushAccumulator();
+ }
+
+ it = it->next;
}
- Instruction::DefineArray call;
- call.argc = argc;
- call.args = Moth::StackSlot::createRegister(args);
- bytecodeGenerator->addInstruction(call);
+ array.loadInAccumulator();
_expr.setResult(Reference::fromAccumulator(this));
return false;
@@ -666,7 +1109,14 @@ bool Codegen::visit(ArrayMemberExpression *ast)
Reference base = expression(ast->base);
if (hasError)
return false;
+ if (base.isSuper()) {
+ Reference index = expression(ast->expression).storeOnStack();
+ _expr.setResult(Reference::fromSuperProperty(index));
+ return false;
+ }
base = base.storeOnStack();
+ if (hasError)
+ return false;
if (AST::StringLiteral *str = AST::cast<AST::StringLiteral *>(ast->expression)) {
QString s = str->value.toString();
uint arrayIndex = QV4::String::toArrayIndex(s);
@@ -692,6 +1142,7 @@ static QSOperator::Op baseOp(int op)
case QSOperator::InplaceAdd: return QSOperator::Add;
case QSOperator::InplaceLeftShift: return QSOperator::LShift;
case QSOperator::InplaceMod: return QSOperator::Mod;
+ case QSOperator::InplaceExp: return QSOperator::Exp;
case QSOperator::InplaceMul: return QSOperator::Mul;
case QSOperator::InplaceOr: return QSOperator::BitOr;
case QSOperator::InplaceRightShift: return QSOperator::RShift;
@@ -764,19 +1215,21 @@ bool Codegen::visit(BinaryExpression *ast)
_expr.setResult(Reference::fromAccumulator(this));
}
return false;
- }
-
- Reference left = expression(ast->left);
- if (hasError)
- return false;
-
- switch (ast->op) {
- case QSOperator::Or:
- case QSOperator::And:
- Q_UNREACHABLE(); // handled separately above
- break;
+ } else if (ast->op == QSOperator::Assign) {
+ if (AST::Pattern *p = ast->left->patternCast()) {
+ RegisterScope scope(this);
+ Reference right = expression(ast->right).storeOnStack();
+ destructurePattern(p, right);
+ if (!_expr.accept(nx)) {
+ right.loadInAccumulator();
+ _expr.setResult(Reference::fromAccumulator(this));
+ }
+ return false;
+ }
+ Reference left = expression(ast->left);
+ if (hasError)
+ return false;
- case QSOperator::Assign: {
if (!left.isLValue()) {
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
return false;
@@ -792,15 +1245,27 @@ bool Codegen::visit(BinaryExpression *ast)
_expr.setResult(left.storeConsumeAccumulator());
else
_expr.setResult(left.storeRetainAccumulator());
- break;
+ return false;
}
+ Reference left = expression(ast->left);
+ if (hasError)
+ return false;
+
+ switch (ast->op) {
+ case QSOperator::Or:
+ case QSOperator::And:
+ case QSOperator::Assign:
+ Q_UNREACHABLE(); // handled separately above
+ break;
+
case QSOperator::InplaceAnd:
case QSOperator::InplaceSub:
case QSOperator::InplaceDiv:
case QSOperator::InplaceAdd:
case QSOperator::InplaceLeftShift:
case QSOperator::InplaceMod:
+ case QSOperator::InplaceExp:
case QSOperator::InplaceMul:
case QSOperator::InplaceOr:
case QSOperator::InplaceRightShift:
@@ -830,7 +1295,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::BitAnd:
case QSOperator::BitOr:
case QSOperator::BitXor:
- if (left.isConst()) {
+ if (left.isConstant()) {
Reference right = expression(ast->right);
if (hasError)
return false;
@@ -850,6 +1315,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::StrictNotEqual:
case QSOperator::Add:
case QSOperator::Div:
+ case QSOperator::Exp:
case QSOperator::Mod:
case QSOperator::Mul:
case QSOperator::Sub:
@@ -890,7 +1356,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::Sub: {
- if (right.isConst() && right.constant == Encode(int(1))) {
+ if (right.isConstant() && right.constant == Encode(int(1))) {
left.loadInAccumulator();
bytecodeGenerator->addInstruction(Instruction::Decrement());
} else {
@@ -902,6 +1368,14 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
}
break;
}
+ case QSOperator::Exp: {
+ left = left.storeOnStack();
+ right.loadInAccumulator();
+ Instruction::Exp exp;
+ exp.lhs = left.stackSlot();
+ bytecodeGenerator->addInstruction(exp);
+ break;
+ }
case QSOperator::Mul: {
left = left.storeOnStack();
right.loadInAccumulator();
@@ -927,9 +1401,9 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::BitAnd:
- if (right.isConst()) {
+ if (right.isConstant()) {
int rightAsInt = Primitive::fromReturnedValue(right.constant).toInt32();
- if (left.isConst()) {
+ if (left.isConstant()) {
int result = Primitive::fromReturnedValue(left.constant).toInt32() & rightAsInt;
return Reference::fromConst(this, Encode(result));
}
@@ -945,9 +1419,9 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
}
break;
case QSOperator::BitOr:
- if (right.isConst()) {
+ if (right.isConstant()) {
int rightAsInt = Primitive::fromReturnedValue(right.constant).toInt32();
- if (left.isConst()) {
+ if (left.isConstant()) {
int result = Primitive::fromReturnedValue(left.constant).toInt32() | rightAsInt;
return Reference::fromConst(this, Encode(result));
}
@@ -963,9 +1437,9 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
}
break;
case QSOperator::BitXor:
- if (right.isConst()) {
+ if (right.isConstant()) {
int rightAsInt = Primitive::fromReturnedValue(right.constant).toInt32();
- if (left.isConst()) {
+ if (left.isConstant()) {
int result = Primitive::fromReturnedValue(left.constant).toInt32() ^ rightAsInt;
return Reference::fromConst(this, Encode(result));
}
@@ -981,7 +1455,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
}
break;
case QSOperator::URShift:
- if (right.isConst()) {
+ if (right.isConstant()) {
left.loadInAccumulator();
Instruction::UShrConst ushr;
ushr.rhs = Primitive::fromReturnedValue(right.constant).toInt32() & 0x1f;
@@ -994,7 +1468,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
}
break;
case QSOperator::RShift:
- if (right.isConst()) {
+ if (right.isConstant()) {
left.loadInAccumulator();
Instruction::ShrConst shr;
shr.rhs = Primitive::fromReturnedValue(right.constant).toInt32() & 0x1f;
@@ -1007,7 +1481,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
}
break;
case QSOperator::LShift:
- if (right.isConst()) {
+ if (right.isConstant()) {
left.loadInAccumulator();
Instruction::ShlConst shl;
shl.rhs = Primitive::fromReturnedValue(right.constant).toInt32() & 0x1f;
@@ -1146,12 +1620,12 @@ static QSOperator::Op operatorForSwappedOperands(QSOperator::Op oper)
Codegen::Reference Codegen::jumpBinop(QSOperator::Op oper, Reference &left, Reference &right)
{
- if (left.isConst()) {
+ if (left.isConstant()) {
oper = operatorForSwappedOperands(oper);
qSwap(left, right);
}
- if (right.isConst() && (oper == QSOperator::Equal || oper == QSOperator::NotEqual)) {
+ if (right.isConstant() && (oper == QSOperator::Equal || oper == QSOperator::NotEqual)) {
Value c = Primitive::fromReturnedValue(right.constant);
if (c.isNull() || c.isUndefined()) {
left.loadInAccumulator();
@@ -1259,6 +1733,7 @@ bool Codegen::visit(CallExpression *ast)
RegisterScope scope(this);
Reference base = expression(ast->base);
+
if (hasError)
return false;
switch (base.type) {
@@ -1270,15 +1745,50 @@ bool Codegen::visit(CallExpression *ast)
break;
case Reference::Name:
break;
+ case Reference::Super:
+ handleConstruct(base, ast->arguments);
+ return false;
default:
base = base.storeOnStack();
break;
}
+ int thisObject = bytecodeGenerator->newRegister();
+ int functionObject = bytecodeGenerator->newRegister();
+
auto calldata = pushArgs(ast->arguments);
if (hasError)
return false;
+ if (calldata.hasSpread) {
+ Reference baseObject = base.baseObject();
+ if (!baseObject.isStackSlot()) {
+ baseObject.storeOnStack(thisObject);
+ baseObject = Reference::fromStackSlot(this, thisObject);
+ }
+ if (!base.isStackSlot()) {
+ base.storeOnStack(functionObject);
+ base = Reference::fromStackSlot(this, functionObject);
+ }
+
+ Instruction::CallWithSpread call;
+ call.func = base.stackSlot();
+ call.thisObject = baseObject.stackSlot();
+ call.argc = calldata.argc;
+ call.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(call);
+
+ _expr.setResult(Reference::fromAccumulator(this));
+ return false;
+
+ }
+
+ handleCall(base, calldata);
+ return false;
+}
+
+void Codegen::handleCall(Reference &base, Arguments calldata)
+{
//### Do we really need all these call instructions? can's we load the callee in a temp?
if (base.type == Reference::QmlScopeObject) {
Instruction::CallScopeObjectProperty call;
@@ -1295,7 +1805,7 @@ bool Codegen::visit(CallExpression *ast)
call.argv = calldata.argv;
bytecodeGenerator->addInstruction(call);
} else if (base.type == Reference::Member) {
- if (useFastLookups) {
+ if (!disable_lookups && useFastLookups) {
Instruction::CallPropertyLookup call;
call.base = base.propertyBase.stackSlot();
call.lookupIndex = registerGetterLookup(base.propertyNameIndex);
@@ -1323,7 +1833,7 @@ bool Codegen::visit(CallExpression *ast)
call.argc = calldata.argc;
call.argv = calldata.argv;
bytecodeGenerator->addInstruction(call);
- } else if (useFastLookups && base.global) {
+ } else if (!disable_lookups && useFastLookups && base.global) {
Instruction::CallGlobalLookup call;
call.index = registerGlobalGetterLookup(base.nameAsIndex());
call.argc = calldata.argc;
@@ -1346,36 +1856,69 @@ bool Codegen::visit(CallExpression *ast)
}
_expr.setResult(Reference::fromAccumulator(this));
- return false;
}
Codegen::Arguments Codegen::pushArgs(ArgumentList *args)
{
+ bool hasSpread = false;
int argc = 0;
- for (ArgumentList *it = args; it; it = it->next)
+ for (ArgumentList *it = args; it; it = it->next) {
+ if (it->isSpreadElement) {
+ hasSpread = true;
+ ++argc;
+ }
++argc;
+ }
if (!argc)
- return { 0, 0 };
+ return { 0, 0, false };
int calldata = bytecodeGenerator->newRegisterArray(argc);
argc = 0;
for (ArgumentList *it = args; it; it = it->next) {
+ if (it->isSpreadElement) {
+ Reference::fromConst(this, Primitive::emptyValue().asReturnedValue()).storeOnStack(calldata + argc);
+ ++argc;
+ }
RegisterScope scope(this);
Reference e = expression(it->expression);
if (hasError)
break;
- if (!argc && !it->next) {
+ if (!argc && !it->next && !hasSpread) {
// avoid copy for functions taking a single argument
if (e.isStackSlot())
- return { 1, e.stackSlot() };
+ return { 1, e.stackSlot(), hasSpread };
}
(void) e.storeOnStack(calldata + argc);
++argc;
}
- return { argc, calldata };
+ return { argc, calldata, hasSpread };
+}
+
+Codegen::Arguments Codegen::pushTemplateArgs(TemplateLiteral *args)
+{
+ int argc = 0;
+ for (TemplateLiteral *it = args; it; it = it->next)
+ ++argc;
+
+ if (!argc)
+ return { 0, 0, false };
+
+ int calldata = bytecodeGenerator->newRegisterArray(argc);
+
+ argc = 0;
+ for (TemplateLiteral *it = args; it && it->expression; it = it->next) {
+ RegisterScope scope(this);
+ Reference e = expression(it->expression);
+ if (hasError)
+ break;
+ (void) e.storeOnStack(calldata + argc);
+ ++argc;
+ }
+
+ return { argc, calldata, false };
}
bool Codegen::visit(ConditionalExpression *ast)
@@ -1413,11 +1956,15 @@ bool Codegen::visit(DeleteExpression *ast)
if (hasError)
return false;
+ RegisterScope scope(this);
Reference expr = expression(ast->expression);
if (hasError)
return false;
switch (expr.type) {
+ case Reference::SuperProperty:
+ // ### this should throw a reference error at runtime.
+ return false;
case Reference::StackSlot:
if (!expr.stackSlotIsLocalOrArgument)
break;
@@ -1444,9 +1991,14 @@ bool Codegen::visit(DeleteExpression *ast)
case Reference::Member: {
//### maybe add a variant where the base can be in the accumulator?
expr = expr.asLValue();
- Instruction::DeleteMember del;
+ Instruction::LoadRuntimeString instr;
+ instr.stringId = expr.propertyNameIndex;
+ bytecodeGenerator->addInstruction(instr);
+ Reference index = Reference::fromStackSlot(this);
+ index.storeConsumeAccumulator();
+ Instruction::DeleteProperty del;
del.base = expr.propertyBase.stackSlot();
- del.member = expr.propertyNameIndex;
+ del.index = index.stackSlot();
bytecodeGenerator->addInstruction(del);
_expr.setResult(Reference::fromAccumulator(this));
return false;
@@ -1454,7 +2006,7 @@ bool Codegen::visit(DeleteExpression *ast)
case Reference::Subscript: {
//### maybe add a variant where the index can be in the accumulator?
expr = expr.asLValue();
- Instruction::DeleteSubscript del;
+ Instruction::DeleteProperty del;
del.base = expr.elementBase;
del.index = expr.elementSubscript.stackSlot();
bytecodeGenerator->addInstruction(del);
@@ -1478,109 +2030,169 @@ bool Codegen::visit(FalseLiteral *)
return false;
}
+bool Codegen::visit(SuperLiteral *)
+{
+ if (hasError)
+ return false;
+
+ _expr.setResult(Reference::fromSuper(this));
+ return false;
+}
+
bool Codegen::visit(FieldMemberExpression *ast)
{
if (hasError)
return false;
+ if (AST::IdentifierExpression *id = AST::cast<AST::IdentifierExpression *>(ast->base)) {
+ if (id->name == QLatin1String("new")) {
+ // new.target
+ if (ast->name != QLatin1String("target")) {
+ throwSyntaxError(ast->identifierToken, QLatin1String("Expected 'target' after 'new.'."));
+ return false;
+ }
+ Reference r = Reference::fromStackSlot(this, CallData::NewTarget);
+ _expr.setResult(r);
+ return false;
+ }
+ }
+
Reference base = expression(ast->base);
if (hasError)
return false;
+ if (base.isSuper()) {
+ Instruction::LoadRuntimeString load;
+ load.stringId = registerString(ast->name.toString());
+ bytecodeGenerator->addInstruction(load);
+ Reference property = Reference::fromAccumulator(this).storeOnStack();
+ _expr.setResult(Reference::fromSuperProperty(property));
+ return false;
+ }
_expr.setResult(Reference::fromMember(base, ast->name.toString()));
return false;
}
-bool Codegen::visit(FunctionExpression *ast)
+bool Codegen::visit(TaggedTemplate *ast)
{
if (hasError)
return false;
RegisterScope scope(this);
- int function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : nullptr);
- loadClosure(function);
- _expr.setResult(Reference::fromAccumulator(this));
+ Reference base = expression(ast->base);
+ if (hasError)
+ return false;
+ switch (base.type) {
+ case Reference::Member:
+ case Reference::Subscript:
+ base = base.asLValue();
+ break;
+ case Reference::Name:
+ break;
+ default:
+ base = base.storeOnStack();
+ break;
+ }
+
+ int arrayTemp = createTemplateArray(ast->templateLiteral);
+ Q_UNUSED(arrayTemp);
+ auto calldata = pushTemplateArgs(ast->templateLiteral);
+ if (hasError)
+ return false;
+ ++calldata.argc;
+ Q_ASSERT(calldata.argv == arrayTemp + 1);
+ --calldata.argv;
+
+ handleCall(base, calldata);
+ return false;
+
+
return false;
}
-Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
+int Codegen::createTemplateArray(TemplateLiteral *t)
{
- int scope = 0;
- Context *c = _context;
-
- // skip the innermost context if it's simple (as the runtime won't
- // create a context for it
- if (c->canUseSimpleCall()) {
- Context::Member m = c->findMember(name);
- if (m.type != Context::UndefinedMember) {
- Q_ASSERT((!m.canEscape));
- Reference r = Reference::fromStackSlot(this, m.index, true /*isLocal*/);
- if (name == QLatin1String("arguments") || name == QLatin1String("eval")) {
- r.isArgOrEval = true;
- if (isLhs && c->isStrict)
- // ### add correct source location
- throwSyntaxError(SourceLocation(), QStringLiteral("Variable name may not be eval or arguments in strict mode"));
- }
- return r;
- }
- const int argIdx = c->findArgument(name);
- if (argIdx != -1) {
- Q_ASSERT(!c->argumentsCanEscape && (c->usesArgumentsObject != Context::ArgumentsObjectUsed || c->isStrict));
- return Reference::fromArgument(this, argIdx, _volataleMemoryLocations.isVolatile(name));
- }
- c = c->parent;
- }
+ int arrayTemp = bytecodeGenerator->newRegister();
- while (c->parent) {
- if (c->forceLookupByName())
- goto loadByName;
+ RegisterScope scope(this);
- Context::Member m = c->findMember(name);
- if (m.type != Context::UndefinedMember) {
- Reference r = m.canEscape ? Reference::fromScopedLocal(this, m.index, scope)
- : Reference::fromStackSlot(this, m.index, true /*isLocal*/);
- if (name == QLatin1String("arguments") || name == QLatin1String("eval")) {
- r.isArgOrEval = true;
- if (isLhs && c->isStrict)
- // ### add correct source location
- throwSyntaxError(SourceLocation(), QStringLiteral("Variable name may not be eval or arguments in strict mode"));
- }
- return r;
- }
- const int argIdx = c->findArgument(name);
- if (argIdx != -1) {
- if (c->argumentsCanEscape || c->usesArgumentsObject == Context::ArgumentsObjectUsed) {
- int idx = argIdx + c->locals.size();
- return Reference::fromScopedLocal(this, idx, scope);
- } else {
- Q_ASSERT(scope == 0);
- return Reference::fromArgument(this, argIdx, _volataleMemoryLocations.isVolatile(name));
- }
- }
+ int argc = 0;
+ int args = -1;
+ auto push = [this, &argc, &args](const QStringRef &arg) {
+ int temp = bytecodeGenerator->newRegister();
+ if (args == -1)
+ args = temp;
+ Instruction::LoadRuntimeString instr;
+ instr.stringId = registerString(arg.toString());
+ bytecodeGenerator->addInstruction(instr);
+ Instruction::StoreReg store;
+ store.reg = temp;
+ bytecodeGenerator->addInstruction(store);
- if (!c->isStrict && c->hasDirectEval)
- goto loadByName;
+ ++argc;
+ };
- ++scope;
- c = c->parent;
- }
+ for (TemplateLiteral *it = t; it; it = it->next)
+ push(it->value);
- {
- // This hook allows implementing QML lookup semantics
- Reference fallback = fallbackNameLookup(name);
- if (fallback.type != Reference::Invalid)
- return fallback;
+ if (args == -1) {
+ Q_ASSERT(argc == 0);
+ args = 0;
}
- if (!c->parent && !c->forceLookupByName() && _context->compilationMode != EvalCode && c->compilationMode != QmlBinding) {
- Reference r = Reference::fromName(this, name);
- r.global = true;
+ Instruction::DefineArray call;
+ call.argc = argc;
+ call.args = Moth::StackSlot::createRegister(args);
+ bytecodeGenerator->addInstruction(call);
+
+ Instruction::StoreReg store;
+ store.reg = arrayTemp;
+ bytecodeGenerator->addInstruction(store);
+
+ return arrayTemp;
+}
+
+bool Codegen::visit(FunctionExpression *ast)
+{
+ if (hasError)
+ return false;
+
+ RegisterScope scope(this);
+
+ int function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body);
+ if (hasError)
+ return false;
+ loadClosure(function);
+ _expr.setResult(Reference::fromAccumulator(this));
+ return false;
+}
+
+Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
+{
+ Context::ResolvedName resolved = _context->resolveName(name);
+
+ if (resolved.type == Context::ResolvedName::Local || resolved.type == Context::ResolvedName::Stack) {
+ if (resolved.isArgOrEval && isLhs)
+ // ### add correct source location
+ throwSyntaxError(SourceLocation(), QStringLiteral("Variable name may not be eval or arguments in strict mode"));
+ Reference r = (resolved.type == Context::ResolvedName::Local) ?
+ Reference::fromScopedLocal(this, resolved.index, resolved.scope) :
+ Reference::fromStackSlot(this, resolved.index, true /*isLocal*/);
+ if (r.isStackSlot() && _volatileMemoryLocations.isVolatile(name))
+ r.isVolatile = true;
+ r.isArgOrEval = resolved.isArgOrEval;
+ r.isReferenceToConst = resolved.isConst;
return r;
}
- // global context or with. Lookup by name
- loadByName:
- return Reference::fromName(this, name);
+ // This hook allows implementing QML lookup semantics
+ Reference fallback = fallbackNameLookup(name);
+ if (fallback.type != Reference::Invalid)
+ return fallback;
+
+ Reference r = Reference::fromName(this, name);
+ r.global = (resolved.type == Context::ResolvedName::Global);
+ return r;
}
void Codegen::loadClosure(int closureId)
@@ -1618,6 +2230,47 @@ bool Codegen::visit(NestedExpression *ast)
return false;
}
+void Codegen::handleConstruct(const Reference &base, ArgumentList *arguments)
+{
+ Reference constructor;
+ if (base.isSuper()) {
+ Instruction::LoadSuperConstructor super;
+ bytecodeGenerator->addInstruction(super);
+ constructor = Reference::fromAccumulator(this).storeOnStack();
+ } else {
+ constructor = base.storeOnStack();
+ }
+
+ auto calldata = pushArgs(arguments);
+ if (hasError)
+ return;
+
+ if (base.isSuper()) {
+ Reference::fromStackSlot(this, CallData::Function).loadInAccumulator();
+ } else {
+ constructor.loadInAccumulator();
+ }
+
+ if (calldata.hasSpread) {
+ Instruction::ConstructWithSpread create;
+ create.func = constructor.stackSlot();
+ create.argc = calldata.argc;
+ create.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(create);
+ } else {
+ Instruction::Construct create;
+ create.func = constructor.stackSlot();
+ create.argc = calldata.argc;
+ create.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(create);
+ }
+ if (base.isSuper())
+ // set the result up as the thisObject
+ Reference::fromAccumulator(this).storeOnStack(CallData::This);
+
+ _expr.setResult(Reference::fromAccumulator(this));
+}
+
bool Codegen::visit(NewExpression *ast)
{
if (hasError)
@@ -1628,15 +2281,12 @@ bool Codegen::visit(NewExpression *ast)
Reference base = expression(ast->expression);
if (hasError)
return false;
- //### Maybe create a ConstructA that takes an accumulator?
- base = base.storeOnStack();
+ if (base.isSuper()) {
+ throwSyntaxError(ast->expression->firstSourceLocation(), QStringLiteral("Cannot use new with super."));
+ return false;
+ }
- Instruction::Construct create;
- create.func = base.stackSlot();
- create.argc = 0;
- create.argv = 0;
- bytecodeGenerator->addInstruction(create);
- _expr.setResult(Reference::fromAccumulator(this));
+ handleConstruct(base, nullptr);
return false;
}
@@ -1650,18 +2300,12 @@ bool Codegen::visit(NewMemberExpression *ast)
Reference base = expression(ast->base);
if (hasError)
return false;
- base = base.storeOnStack();
-
- auto calldata = pushArgs(ast->arguments);
- if (hasError)
+ if (base.isSuper()) {
+ throwSyntaxError(ast->base->firstSourceLocation(), QStringLiteral("Cannot use new with super."));
return false;
+ }
- Instruction::Construct create;
- create.func = base.stackSlot();
- create.argc = calldata.argc;
- create.argv = calldata.argv;
- bytecodeGenerator->addInstruction(create);
- _expr.setResult(Reference::fromAccumulator(this));
+ handleConstruct(base, ast->arguments);
return false;
}
@@ -1696,133 +2340,105 @@ bool Codegen::visit(NumericLiteral *ast)
return false;
}
-bool Codegen::visit(ObjectLiteral *ast)
+bool Codegen::visit(ObjectPattern *ast)
{
if (hasError)
return false;
+ QVector<QPair<Reference, ObjectPropertyValue>> computedProperties;
QMap<QString, ObjectPropertyValue> valueMap;
RegisterScope scope(this);
- for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
- QString name = it->assignment->name->asString();
- if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
- Reference value = expression(nv->value);
- if (hasError)
- return false;
-
- ObjectPropertyValue &v = valueMap[name];
- if (v.hasGetter() || v.hasSetter() || (_context->isStrict && v.rvalue.isValid())) {
- throwSyntaxError(nv->lastSourceLocation(),
- QStringLiteral("Illegal duplicate key '%1' in object literal").arg(name));
- return false;
- }
-
- v.rvalue = value.storeOnStack();
- } else if (PropertyGetterSetter *gs = AST::cast<AST::PropertyGetterSetter *>(it->assignment)) {
- const int function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : nullptr);
- ObjectPropertyValue &v = valueMap[name];
- if (v.rvalue.isValid() ||
- (gs->type == PropertyGetterSetter::Getter && v.hasGetter()) ||
- (gs->type == PropertyGetterSetter::Setter && v.hasSetter())) {
- throwSyntaxError(gs->lastSourceLocation(),
- QStringLiteral("Illegal duplicate key '%1' in object literal").arg(name));
- return false;
- }
- if (gs->type == PropertyGetterSetter::Getter)
- v.getter = function;
- else
- v.setter = function;
- } else {
- Q_UNREACHABLE();
- }
- }
+ QStringList members;
- QVector<QString> nonArrayKey, arrayKeyWithValue, arrayKeyWithGetterSetter;
- bool needSparseArray = false; // set to true if any array index is bigger than 16
-
- for (QMap<QString, ObjectPropertyValue>::iterator it = valueMap.begin(), eit = valueMap.end();
- it != eit; ++it) {
- QString name = it.key();
- uint keyAsIndex = QV4::String::toArrayIndex(name);
- if (keyAsIndex != std::numeric_limits<uint>::max()) {
- it->keyAsIndex = keyAsIndex;
- if (keyAsIndex > 16)
- needSparseArray = true;
- if (it->hasSetter() || it->hasGetter())
- arrayKeyWithGetterSetter.append(name);
- else
- arrayKeyWithValue.append(name);
- } else {
- nonArrayKey.append(name);
- }
- }
-
- int args = -1;
- auto push = [this, &args](const Reference &arg) {
+ int argc = 0;
+ int args = 0;
+ auto push = [this, &args, &argc](const Reference &arg) {
int temp = bytecodeGenerator->newRegister();
- if (args == -1)
+ if (argc == 0)
args = temp;
(void) arg.storeOnStack(temp);
+ ++argc;
};
- QVector<QV4::Compiler::JSUnitGenerator::MemberInfo> members;
+ PatternPropertyList *it = ast->properties;
+ for (; it; it = it->next) {
+ PatternProperty *p = it->property;
+ AST::ComputedPropertyName *cname = AST::cast<AST::ComputedPropertyName *>(p->name);
+ if (cname || p->type == PatternProperty::Getter || p->type == PatternProperty::Setter)
+ break;
+ QString name = p->name->asString();
+ uint arrayIndex = QV4::String::toArrayIndex(name);
+ if (arrayIndex != UINT_MAX)
+ break;
+ if (members.contains(name))
+ break;
+ members.append(name);
- Reference acc = Reference::fromAccumulator(this);
- // generate the key/value pairs
- for (const QString &key : qAsConst(nonArrayKey)) {
- const ObjectPropertyValue &prop = valueMap[key];
-
- if (prop.hasGetter() || prop.hasSetter()) {
- Q_ASSERT(!prop.rvalue.isValid());
- loadClosure(prop.getter);
- push(acc);
- loadClosure(prop.setter);
- push(acc);
- members.append({ key, true });
- } else {
- Q_ASSERT(prop.rvalue.isValid());
- push(prop.rvalue);
- members.append({ key, false });
+ {
+ RegisterScope innerScope(this);
+ Reference value = expression(p->initializer);
+ if (hasError)
+ return false;
+ value.loadInAccumulator();
}
- }
-
- // generate array entries with values
- for (const QString &key : qAsConst(arrayKeyWithValue)) {
- const ObjectPropertyValue &prop = valueMap[key];
- Q_ASSERT(!prop.hasGetter() && !prop.hasSetter());
- push(Reference::fromConst(this, Encode(prop.keyAsIndex)));
- push(prop.rvalue);
- }
-
- // generate array entries with both a value and a setter
- for (const QString &key : qAsConst(arrayKeyWithGetterSetter)) {
- const ObjectPropertyValue &prop = valueMap[key];
- Q_ASSERT(!prop.rvalue.isValid());
- push(Reference::fromConst(this, Encode(prop.keyAsIndex)));
- loadClosure(prop.getter);
- push(acc);
- loadClosure(prop.setter);
- push(acc);
+ push(Reference::fromAccumulator(this));
}
int classId = jsUnitGenerator->registerJSClass(members);
- uint arrayGetterSetterCountAndFlags = arrayKeyWithGetterSetter.size();
- arrayGetterSetterCountAndFlags |= needSparseArray << 30;
-
- if (args == -1)
- args = 0;
+ // handle complex property setters
+ for (; it; it = it->next) {
+ PatternProperty *p = it->property;
+ AST::ComputedPropertyName *cname = AST::cast<AST::ComputedPropertyName *>(p->name);
+ ObjectLiteralArgument argType = ObjectLiteralArgument::Value;
+ if (p->type == PatternProperty::Getter)
+ argType = ObjectLiteralArgument::Getter;
+ else if (p->type == PatternProperty::Setter)
+ argType = ObjectLiteralArgument::Setter;
+
+ Reference::fromConst(this, Encode(int(argType))).loadInAccumulator();
+ push(Reference::fromAccumulator(this));
+
+ if (cname) {
+ RegisterScope innerScope(this);
+ Reference name = expression(cname->expression);
+ if (hasError)
+ return false;
+ name.loadInAccumulator();
+ } else {
+ QString name = p->name->asString();
+#if 0
+ uint arrayIndex = QV4::String::toArrayIndex(name);
+ if (arrayIndex != UINT_MAX) {
+ Reference::fromConst(this, Encode(arrayIndex)).loadInAccumulator();
+ } else
+#endif
+ {
+ Instruction::LoadRuntimeString instr;
+ instr.stringId = registerString(name);
+ bytecodeGenerator->addInstruction(instr);
+ }
+ }
+ push(Reference::fromAccumulator(this));
+ {
+ RegisterScope innerScope(this);
+ Reference value = expression(p->initializer);
+ if (hasError)
+ return false;
+ value.loadInAccumulator();
+ }
+ push(Reference::fromAccumulator(this));
+ }
Instruction::DefineObjectLiteral call;
call.internalClassId = classId;
- call.arrayValueCount = arrayKeyWithValue.size();
- call.arrayGetterSetterCountAndFlags = arrayGetterSetterCountAndFlags;
+ call.argc = argc;
call.args = Moth::StackSlot::createRegister(args);
bytecodeGenerator->addInstruction(call);
-
- _expr.setResult(Reference::fromAccumulator(this));
+ Reference result = Reference::fromAccumulator(this);
+ _expr.setResult(result);
return false;
}
@@ -1933,6 +2549,49 @@ bool Codegen::visit(StringLiteral *ast)
return false;
}
+bool Codegen::visit(TemplateLiteral *ast)
+{
+ if (hasError)
+ return false;
+
+ Instruction::LoadRuntimeString instr;
+ instr.stringId = registerString(ast->value.toString());
+ bytecodeGenerator->addInstruction(instr);
+
+ if (ast->expression) {
+ RegisterScope scope(this);
+ int temp = bytecodeGenerator->newRegister();
+ Instruction::StoreReg store;
+ store.reg = temp;
+ bytecodeGenerator->addInstruction(store);
+
+ Reference expr = expression(ast->expression);
+
+ if (ast->next) {
+ int temp2 = bytecodeGenerator->newRegister();
+ expr.storeOnStack(temp2);
+ visit(ast->next);
+
+ Instruction::Add instr;
+ instr.lhs = temp2;
+ bytecodeGenerator->addInstruction(instr);
+ } else {
+ expr.loadInAccumulator();
+ }
+
+ Instruction::Add instr;
+ instr.lhs = temp;
+ bytecodeGenerator->addInstruction(instr);
+ }
+
+ auto r = Reference::fromAccumulator(this);
+ r.isReadonly = true;
+
+ _expr.setResult(r);
+ return false;
+
+}
+
bool Codegen::visit(ThisExpression *)
{
if (hasError)
@@ -2023,13 +2682,40 @@ bool Codegen::visit(FunctionDeclaration * ast)
RegisterScope scope(this);
- if (_context->compilationMode == QmlBinding)
- Reference::fromName(this, ast->name.toString()).loadInAccumulator();
+ if (_functionContext->contextType == ContextType::Binding)
+ referenceForName(ast->name.toString(), true).loadInAccumulator();
_expr.accept(nx);
return false;
}
-static bool endsWithReturn(Node *node)
+bool Codegen::visit(YieldExpression *ast)
+{
+ if (ast->isYieldStar) {
+ throwSyntaxError(ast->firstSourceLocation(), QLatin1String("yield* is not currently supported"));
+ return false;
+ }
+ if (inFormalParameterList) {
+ throwSyntaxError(ast->firstSourceLocation(), QLatin1String("yield is not allowed inside parameter lists"));
+ return false;
+ }
+
+
+ Reference result = ast->expression ? expression(ast->expression) : Reference::fromConst(this, Encode::undefined());
+ if (hasError)
+ return false;
+ result.loadInAccumulator();
+ Instruction::Yield yield;
+ bytecodeGenerator->addInstruction(yield);
+ Instruction::Resume resume;
+ BytecodeGenerator::Jump jump = bytecodeGenerator->addJumpInstruction(resume);
+ Reference acc = Reference::fromAccumulator(this);
+ emitReturn(acc);
+ jump.link();
+ _expr.setResult(acc);
+ return false;
+}
+
+static bool endsWithReturn(Module *module, Node *node)
{
if (!node)
return false;
@@ -2038,32 +2724,29 @@ static bool endsWithReturn(Node *node)
if (AST::cast<ThrowStatement *>(node))
return true;
if (Program *p = AST::cast<Program *>(node))
- return endsWithReturn(p->elements);
- if (SourceElements *se = AST::cast<SourceElements *>(node)) {
- while (se->next)
- se = se->next;
- return endsWithReturn(se->element);
- }
- if (StatementSourceElement *sse = AST::cast<StatementSourceElement *>(node))
- return endsWithReturn(sse->statement);
+ return endsWithReturn(module, p->statements);
if (StatementList *sl = AST::cast<StatementList *>(node)) {
while (sl->next)
sl = sl->next;
- return endsWithReturn(sl->statement);
+ return endsWithReturn(module, sl->statement);
+ }
+ if (Block *b = AST::cast<Block *>(node)) {
+ Context *blockContext = module->contextMap.value(node);
+ if (blockContext->requiresExecutionContext)
+ // we need to emit a return statement here, because of the
+ // unwind handler
+ return false;
+ return endsWithReturn(module, b->statements);
}
- if (Block *b = AST::cast<Block *>(node))
- return endsWithReturn(b->statements);
if (IfStatement *is = AST::cast<IfStatement *>(node))
- return is->ko && endsWithReturn(is->ok) && endsWithReturn(is->ko);
+ return is->ko && endsWithReturn(module, is->ok) && endsWithReturn(module, is->ko);
return false;
}
int Codegen::defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
- AST::SourceElements *body)
+ AST::StatementList *body)
{
- Q_UNUSED(formals);
-
enterContext(ast);
if (_context->functionIndex >= 0)
@@ -2074,7 +2757,15 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
_module->functions.append(_context);
_context->functionIndex = _module->functions.count() - 1;
- _context->hasDirectEval |= (_context->compilationMode == EvalCode || _context->compilationMode == GlobalCode || _module->debugMode); // Conditional breakpoints are like eval in the function
+ Context *savedFunctionContext = _functionContext;
+ _functionContext = _context;
+ ControlFlow *savedControlFlow = controlFlow;
+ controlFlow = nullptr;
+
+ if (_context->contextType == ContextType::Global) {
+ _module->blocks.append(_context);
+ _context->blockIndex = _module->blocks.count() - 1;
+ }
if (_module->debugMode) // allow the debugger to see overwritten arguments
_context->argumentsCanEscape = true;
@@ -2084,132 +2775,104 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
// at all, because if the onSignal is a signal handler, the user is actually making it explicit
// that the binding is a function, so we should execute that. However, we don't know that during
// AOT compilation, so mark the surrounding function as only-returning-a-closure.
- _context->returnsClosure = cast<ExpressionStatement *>(ast) && cast<FunctionExpression *>(cast<ExpressionStatement *>(ast)->expression);
+ _context->returnsClosure = body && body->statement && cast<ExpressionStatement *>(body->statement) && cast<FunctionExpression *>(cast<ExpressionStatement *>(body->statement)->expression);
BytecodeGenerator bytecode(_context->line, _module->debugMode);
BytecodeGenerator *savedBytecodeGenerator;
savedBytecodeGenerator = bytecodeGenerator;
bytecodeGenerator = &bytecode;
bytecodeGenerator->setLocation(ast->firstSourceLocation());
+ BytecodeGenerator::Label *savedReturnLabel = _returnLabel;
+ _returnLabel = nullptr;
+
+ bool savedFunctionEndsWithReturn = functionEndsWithReturn;
+ functionEndsWithReturn = endsWithReturn(_module, body);
// reserve the js stack frame (Context & js Function & accumulator)
bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + _context->arguments.size());
+ bool _inFormalParameterList = false;
+ qSwap(_inFormalParameterList, inFormalParameterList);
+
int returnAddress = -1;
- bool _requiresReturnValue = (_context->compilationMode == QmlBinding || _context->compilationMode == EvalCode || _context->compilationMode == GlobalCode);
+ bool _requiresReturnValue = _context->requiresImplicitReturnValue();
qSwap(requiresReturnValue, _requiresReturnValue);
- if (requiresReturnValue)
- returnAddress = bytecodeGenerator->newRegister();
- if (!_context->parent || _context->usesArgumentsObject == Context::ArgumentsObjectUnknown)
- _context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
- if (_context->usesArgumentsObject == Context::ArgumentsObjectUsed)
- _context->addLocalVar(QStringLiteral("arguments"), Context::VariableDeclaration, AST::VariableDeclaration::FunctionScope);
-
- bool allVarsEscape = _context->hasWith || _context->hasTry || _context->hasDirectEval;
- bool needsCallContext = false;
- const QLatin1String exprForOn("expression for on");
- if (!_context->canUseSimpleCall() && _context->compilationMode != GlobalCode && (_context->compilationMode != EvalCode || _context->isStrict))
- needsCallContext = true;
- else if (_context->compilationMode == QmlBinding && name.length() > exprForOn.size() && name.startsWith(exprForOn) && name.at(exprForOn.size()).isUpper())
- // we don't really need this for bindings, but we do for signal handlers, and we don't know if the code is a signal handler or not.
- needsCallContext = true;
- if (needsCallContext) {
- Instruction::CreateCallContext createContext;
- bytecodeGenerator->addInstruction(createContext);
- }
-
- // variables in global code are properties of the global context object, not locals as with other functions.
- if (_context->compilationMode == FunctionCode || _context->compilationMode == QmlBinding) {
- for (Context::MemberMap::iterator it = _context->members.begin(), end = _context->members.end(); it != end; ++it) {
- const QString &local = it.key();
- if (allVarsEscape)
- it->canEscape = true;
- if (it->canEscape) {
- it->index = _context->locals.size();
- _context->locals.append(local);
- if (it->type == Context::ThisFunctionName) {
- // move the name from the stack to the call context
- Instruction::LoadReg load;
- load.reg = CallData::Function;
- bytecodeGenerator->addInstruction(load);
- Instruction::StoreLocal store;
- store.index = it->index;
- bytecodeGenerator->addInstruction(store);
- }
- } else {
- if (it->type == Context::ThisFunctionName)
- it->index = CallData::Function;
- else
- it->index = bytecodeGenerator->newRegister();
- }
- }
- } else {
- for (Context::MemberMap::const_iterator it = _context->members.constBegin(), cend = _context->members.constEnd(); it != cend; ++it) {
- const QString &local = it.key();
+ returnAddress = bytecodeGenerator->newRegister();
+ qSwap(_returnAddress, returnAddress);
- Instruction::DeclareVar declareVar;
- declareVar.isDeletable = false;
- declareVar.varName = registerString(local);
- bytecodeGenerator->addInstruction(declareVar);
- }
+ // register the lexical scope for global code
+ if (!_context->parent && _context->requiresExecutionContext) {
+ _module->blocks.append(_context);
+ _context->blockIndex = _module->blocks.count() - 1;
}
- qSwap(_returnAddress, returnAddress);
- for (const Context::Member &member : qAsConst(_context->members)) {
- if (member.function) {
- const int function = defineFunction(member.function->name.toString(), member.function, member.function->formals,
- member.function->body ? member.function->body->elements : nullptr);
- loadClosure(function);
- if (! _context->parent) {
- Reference::fromName(this, member.function->name.toString()).storeConsumeAccumulator();
- } else {
- Q_ASSERT(member.index >= 0);
- Reference local = member.canEscape ? Reference::fromScopedLocal(this, member.index, 0)
- : Reference::fromStackSlot(this, member.index, true);
- local.storeConsumeAccumulator();
- }
+ RegisterScope registerScope(this);
+ _context->emitBlockHeader(this);
+
+ inFormalParameterList = true;
+ int argc = 0;
+ while (formals) {
+ PatternElement *e = formals->element;
+ if (!e) {
+ if (!formals->next)
+ // trailing comma
+ break;
+ Q_UNREACHABLE();
}
- }
- if (_context->usesArgumentsObject == Context::ArgumentsObjectUsed) {
- if (_context->isStrict) {
- Instruction::CreateUnmappedArgumentsObject setup;
- bytecodeGenerator->addInstruction(setup);
+
+ Reference arg = referenceForName(e->bindingIdentifier.toString(), true);
+ if (e->type == PatternElement::RestElement) {
+ Q_ASSERT(!formals->next);
+ Instruction::CreateRestParameter rest;
+ rest.argIndex = argc;
+ bytecodeGenerator->addInstruction(rest);
+ arg.storeConsumeAccumulator();
} else {
- Instruction::CreateMappedArgumentsObject setup;
- bytecodeGenerator->addInstruction(setup);
+ if (e->bindingTarget || e->initializer) {
+ initializeAndDestructureBindingElement(e, arg);
+ if (hasError)
+ break;
+ }
}
- referenceForName(QStringLiteral("arguments"), false).storeConsumeAccumulator();
+ formals = formals->next;
+ ++argc;
}
- if (_context->usesThis && !_context->isStrict) {
- // make sure we convert this to an object
- Instruction::ConvertThisToObject convert;
- bytecodeGenerator->addInstruction(convert);
+ inFormalParameterList = false;
+
+ if (_context->isGenerator) {
+ Instruction::Yield yield;
+ bytecodeGenerator->addInstruction(yield);
}
beginFunctionBodyHook();
- sourceElements(body);
+ statementList(body);
- if (hasError || !endsWithReturn(body)) {
- bytecodeGenerator->setLocation(ast->lastSourceLocation());
- if (requiresReturnValue) {
- if (_returnAddress >= 0) {
- Instruction::LoadReg load;
- load.reg = Moth::StackSlot::createRegister(_returnAddress);
- bytecodeGenerator->addInstruction(load);
- }
+ bytecodeGenerator->setLocation(ast->lastSourceLocation());
+ _context->emitBlockFooter(this);
+
+ if (_returnLabel || hasError || !functionEndsWithReturn) {
+ if (_returnLabel)
+ _returnLabel->link();
+
+ if (_returnLabel || requiresReturnValue) {
+ Instruction::LoadReg load;
+ load.reg = Moth::StackSlot::createRegister(_returnAddress);
+ bytecodeGenerator->addInstruction(load);
} else {
Reference::fromConst(this, Encode::undefined()).loadInAccumulator();
}
+
bytecodeGenerator->addInstruction(Instruction::Ret());
}
+ Q_ASSERT(_context == _functionContext);
bytecodeGenerator->finalize(_context);
- _context->registerCount = bytecodeGenerator->registerCount();
+ _context->registerCountInFunction = bytecodeGenerator->registerCount();
static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
if (showCode) {
qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict
- << "register count" << _context->registerCount;
+ << "register count" << _context->registerCountInFunction << "implicit return" << requiresReturnValue;
QV4::Moth::dumpBytecode(_context->code, _context->locals.size(), _context->arguments.size(),
_context->line, _context->lineNumberMapping);
qDebug();
@@ -2217,29 +2880,17 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
qSwap(_returnAddress, returnAddress);
qSwap(requiresReturnValue, _requiresReturnValue);
+ qSwap(_inFormalParameterList, inFormalParameterList);
bytecodeGenerator = savedBytecodeGenerator;
+ delete _returnLabel;
+ _returnLabel = savedReturnLabel;
+ controlFlow = savedControlFlow;
+ functionEndsWithReturn = savedFunctionEndsWithReturn;
+ _functionContext = savedFunctionContext;
return leaveContext();
}
-bool Codegen::visit(FunctionSourceElement *ast)
-{
- if (hasError)
- return false;
-
- statement(ast->declaration);
- return false;
-}
-
-bool Codegen::visit(StatementSourceElement *ast)
-{
- if (hasError)
- return false;
-
- statement(ast->statement);
- return false;
-}
-
bool Codegen::visit(Block *ast)
{
if (hasError)
@@ -2247,6 +2898,7 @@ bool Codegen::visit(Block *ast)
RegisterScope scope(this);
+ ControlFlowBlock controlFlow(this, ast);
statementList(ast->statements);
return false;
}
@@ -2256,13 +2908,13 @@ bool Codegen::visit(BreakStatement *ast)
if (hasError)
return false;
- if (!_context->controlFlow) {
+ if (!controlFlow) {
throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Break outside of loop"));
return false;
}
- ControlFlow::Handler h = _context->controlFlow->getHandler(ControlFlow::Break, ast->label.toString());
- if (h.type == ControlFlow::Invalid) {
+ ControlFlow::UnwindTarget target = controlFlow->unwindTarget(ControlFlow::Break, ast->label.toString());
+ if (!target.linkLabel.isValid()) {
if (ast->label.isEmpty())
throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Break outside of loop"));
else
@@ -2270,7 +2922,7 @@ bool Codegen::visit(BreakStatement *ast)
return false;
}
- _context->controlFlow->jumpToHandler(h);
+ bytecodeGenerator->unwindToLabel(target.unwindLevel, target.linkLabel);
return false;
}
@@ -2282,13 +2934,13 @@ bool Codegen::visit(ContinueStatement *ast)
RegisterScope scope(this);
- if (!_context->controlFlow) {
+ if (!controlFlow) {
throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Continue outside of loop"));
return false;
}
- ControlFlow::Handler h = _context->controlFlow->getHandler(ControlFlow::Continue, ast->label.toString());
- if (h.type == ControlFlow::Invalid) {
+ ControlFlow::UnwindTarget target = controlFlow->unwindTarget(ControlFlow::Continue, ast->label.toString());
+ if (!target.linkLabel.isValid()) {
if (ast->label.isEmpty())
throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Undefined label '%1'").arg(ast->label.toString()));
else
@@ -2296,7 +2948,7 @@ bool Codegen::visit(ContinueStatement *ast)
return false;
}
- _context->controlFlow->jumpToHandler(h);
+ bytecodeGenerator->unwindToLabel(target.unwindLevel, target.linkLabel);
return false;
}
@@ -2370,45 +3022,86 @@ bool Codegen::visit(ForEachStatement *ast)
RegisterScope scope(this);
- Reference nextIterObj = Reference::fromStackSlot(this);
- Reference iterObj = Reference::fromStackSlot(this);
- Reference expr = expression(ast->expression);
- if (hasError)
- return true;
+ Reference iterator = Reference::fromStackSlot(this);
+ Reference lhsValue = Reference::fromStackSlot(this);
- expr.loadInAccumulator();
- Instruction::ForeachIteratorObject iteratorObjInstr;
- bytecodeGenerator->addInstruction(iteratorObjInstr);
- iterObj.storeConsumeAccumulator();
+ // There should be a temporal block, so that variables declared in lhs shadow outside vars.
+ // This block should define a temporal dead zone for those variables, which is not yet implemented.
+ {
+ RegisterScope innerScope(this);
+ ControlFlowBlock controlFlow(this, ast);
+ Reference expr = expression(ast->expression);
+ if (hasError)
+ return true;
- Reference lhs = expression(ast->initialiser).asLValue();
+ expr.loadInAccumulator();
+ Instruction::GetIterator iteratorObjInstr;
+ iteratorObjInstr.iterator = (ast->type == ForEachType::Of) ? 1 : 0;
+ bytecodeGenerator->addInstruction(iteratorObjInstr);
+ iterator.storeConsumeAccumulator();
+ }
BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
+ BytecodeGenerator::Label done = bytecodeGenerator->newLabel();
- bytecodeGenerator->jump().link(in);
-
- ControlFlowLoop flow(this, &end, &in);
+ {
+ ControlFlowLoop flow(this, &end, &in, /*requiresUnwind*/ true);
+ bytecodeGenerator->jump().link(in);
+
+ BytecodeGenerator::Label body = bytecodeGenerator->label();
+
+ // each iteration gets it's own context, as per spec
+ {
+ RegisterScope innerScope(this);
+ ControlFlowBlock controlFlow(this, ast);
+
+ if (ExpressionNode *e = ast->lhs->expressionCast()) {
+ if (AST::Pattern *p = e->patternCast()) {
+ RegisterScope scope(this);
+ destructurePattern(p, lhsValue);
+ } else {
+ Reference lhs = expression(e);
+ if (hasError)
+ goto error;
+ lhs = lhs.asLValue();
+ lhsValue.loadInAccumulator();
+ lhs.storeConsumeAccumulator();
+ }
+ } else if (PatternElement *p = AST::cast<PatternElement *>(ast->lhs)) {
+ initializeAndDestructureBindingElement(p, lhsValue, /*isDefinition =*/ true);
+ if (hasError)
+ goto error;
+ } else {
+ Q_UNREACHABLE();
+ }
- BytecodeGenerator::Label body = bytecodeGenerator->label();
+ statement(ast->statement);
+ setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
- nextIterObj.loadInAccumulator();
- lhs.storeConsumeAccumulator();
+ }
- statement(ast->statement);
- setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
+ error:
+ in.link();
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.value = lhsValue.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
+ bytecodeGenerator->jump().link(done);
+ }
- in.link();
+ end.link();
- iterObj.loadInAccumulator();
- Instruction::ForeachNextPropertyName nextPropInstr;
- bytecodeGenerator->addInstruction(nextPropInstr);
- nextIterObj.storeConsumeAccumulator();
+ if (ast->type == ForEachType::Of) {
+ Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack();
+ iterator.loadInAccumulator();
+ Instruction::IteratorClose close;
+ close.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(close);
+ }
- Reference::fromConst(this, QV4::Encode::null()).loadInAccumulator();
- bytecodeGenerator->jumpStrictNotEqual(nextIterObj.stackSlot(), body);
-
- end.link();
+ done.link();
return false;
}
@@ -2420,7 +3113,12 @@ bool Codegen::visit(ForStatement *ast)
RegisterScope scope(this);
- statement(ast->initialiser);
+ ControlFlowBlock controlFlow(this, ast);
+
+ if (ast->initialiser)
+ statement(ast->initialiser);
+ else if (ast->declarations)
+ variableDeclarationList(ast->declarations);
BytecodeGenerator::Label cond = bytecodeGenerator->label();
BytecodeGenerator::Label body = bytecodeGenerator->newLabel();
@@ -2436,6 +3134,10 @@ bool Codegen::visit(ForStatement *ast)
setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
step.link();
+ if (_context->requiresExecutionContext) {
+ Instruction::CloneBlockContext clone;
+ bytecodeGenerator->addInstruction(clone);
+ }
statement(ast->expression);
bytecodeGenerator->jump().link(cond);
@@ -2458,7 +3160,7 @@ bool Codegen::visit(IfStatement *ast)
trueLabel.link();
statement(ast->ok);
if (ast->ko) {
- if (endsWithReturn(ast)) {
+ if (endsWithReturn(_module, ast)) {
falseLabel.link();
statement(ast->ko);
} else {
@@ -2482,7 +3184,7 @@ bool Codegen::visit(LabelledStatement *ast)
RegisterScope scope(this);
// check that no outer loop contains the label
- ControlFlow *l = _context->controlFlow;
+ ControlFlow *l = controlFlow;
while (l) {
if (l->label() == ast->label) {
QString error = QString(QStringLiteral("Label '%1' has already been declared")).arg(ast->label.toString());
@@ -2497,9 +3199,7 @@ bool Codegen::visit(LabelledStatement *ast)
AST::cast<AST::WhileStatement *>(ast->statement) ||
AST::cast<AST::DoWhileStatement *>(ast->statement) ||
AST::cast<AST::ForStatement *>(ast->statement) ||
- AST::cast<AST::ForEachStatement *>(ast->statement) ||
- AST::cast<AST::LocalForStatement *>(ast->statement) ||
- AST::cast<AST::LocalForEachStatement *>(ast->statement)) {
+ AST::cast<AST::ForEachStatement *>(ast->statement)) {
statement(ast->statement); // labelledStatement will be associated with the ast->statement's loop.
} else {
BytecodeGenerator::Label breakLabel = bytecodeGenerator->newLabel();
@@ -2511,85 +3211,17 @@ bool Codegen::visit(LabelledStatement *ast)
return false;
}
-bool Codegen::visit(LocalForEachStatement *ast)
+void Codegen::emitReturn(const Reference &expr)
{
- if (hasError)
- return true;
-
- RegisterScope scope(this);
-
- Reference nextIterObj = Reference::fromStackSlot(this);
- Reference iterObj = Reference::fromStackSlot(this);
- Reference expr = expression(ast->expression);
- if (hasError)
- return true;
-
- variableDeclaration(ast->declaration);
-
- expr.loadInAccumulator();
- Instruction::ForeachIteratorObject iteratorObjInstr;
- bytecodeGenerator->addInstruction(iteratorObjInstr);
- iterObj.storeConsumeAccumulator();
-
- BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
- BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
-
- bytecodeGenerator->jump().link(in);
- ControlFlowLoop flow(this, &end, &in);
-
- BytecodeGenerator::Label body = bytecodeGenerator->label();
-
- Reference it = referenceForName(ast->declaration->name.toString(), true).asLValue();
-
- nextIterObj.loadInAccumulator();
- it.storeConsumeAccumulator();
-
- statement(ast->statement);
- setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
-
- in.link();
-
- iterObj.loadInAccumulator();
- Instruction::ForeachNextPropertyName nextPropInstr;
- bytecodeGenerator->addInstruction(nextPropInstr);
- nextIterObj.storeConsumeAccumulator();
-
- Reference::fromConst(this, QV4::Encode::null()).loadInAccumulator();
- bytecodeGenerator->jumpStrictNotEqual(nextIterObj.stackSlot(), body);
-
- end.link();
-
- return false;
-}
-
-bool Codegen::visit(LocalForStatement *ast)
-{
- if (hasError)
- return true;
-
- RegisterScope scope(this);
-
- variableDeclarationList(ast->declarations);
-
- BytecodeGenerator::Label cond = bytecodeGenerator->label();
- BytecodeGenerator::Label body = bytecodeGenerator->newLabel();
- BytecodeGenerator::Label step = bytecodeGenerator->newLabel();
- BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
-
- ControlFlowLoop flow(this, &end, &step);
-
- condition(ast->condition, &body, &end, true);
-
- body.link();
- statement(ast->statement);
- setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
-
- step.link();
- statement(ast->expression);
- bytecodeGenerator->jump().link(cond);
- end.link();
-
- return false;
+ ControlFlow::UnwindTarget target = controlFlow ? controlFlow->unwindTarget(ControlFlow::Return) : ControlFlow::UnwindTarget();
+ if (target.linkLabel.isValid() && target.unwindLevel) {
+ Q_ASSERT(_returnAddress >= 0);
+ (void) expr.storeOnStack(_returnAddress);
+ bytecodeGenerator->unwindToLabel(target.unwindLevel, target.linkLabel);
+ } else {
+ expr.loadInAccumulator();
+ bytecodeGenerator->addInstruction(Instruction::Ret());
+ }
}
bool Codegen::visit(ReturnStatement *ast)
@@ -2597,7 +3229,7 @@ bool Codegen::visit(ReturnStatement *ast)
if (hasError)
return true;
- if (_context->compilationMode != FunctionCode && _context->compilationMode != QmlBinding) {
+ if (_functionContext->contextType != ContextType::Function && _functionContext->contextType != ContextType::Binding) {
throwSyntaxError(ast->returnToken, QStringLiteral("Return statement outside of function"));
return false;
}
@@ -2610,17 +3242,8 @@ bool Codegen::visit(ReturnStatement *ast)
expr = Reference::fromConst(this, Encode::undefined());
}
- if (_context->controlFlow && _context->controlFlow->returnRequiresUnwind()) {
- if (_returnAddress >= 0)
- (void) expr.storeOnStack(_returnAddress);
- else
- expr.loadInAccumulator();
- ControlFlow::Handler h = _context->controlFlow->getHandler(ControlFlow::Return);
- _context->controlFlow->jumpToHandler(h);
- } else {
- expr.loadInAccumulator();
- bytecodeGenerator->addInstruction(Instruction::Ret());
- }
+ emitReturn(expr);
+
return false;
}
@@ -2629,9 +3252,14 @@ bool Codegen::visit(SwitchStatement *ast)
if (hasError)
return true;
+ if (requiresReturnValue)
+ Reference::fromConst(this, Encode::undefined()).storeOnStack(_returnAddress);
+
RegisterScope scope(this);
if (ast->block) {
+ ControlFlowBlock controlFlow(this, ast->block);
+
BytecodeGenerator::Label switchEnd = bytecodeGenerator->newLabel();
Reference lhs = expression(ast->expression);
@@ -2674,6 +3302,7 @@ bool Codegen::visit(SwitchStatement *ast)
ControlFlowLoop flow(this, &switchEnd);
+ insideSwitch = true;
for (CaseClauses *it = ast->block->clauses; it; it = it->next) {
CaseClause *clause = it->clause;
blockMap[clause].link();
@@ -2694,6 +3323,7 @@ bool Codegen::visit(SwitchStatement *ast)
statementList(clause->statements);
}
+ insideSwitch = false;
switchEnd.link();
@@ -2713,25 +3343,15 @@ bool Codegen::visit(ThrowStatement *ast)
if (hasError)
return false;
- if (_context->controlFlow) {
- _context->controlFlow->handleThrow(expr);
- } else {
- expr.loadInAccumulator();
- Instruction::ThrowException instr;
- bytecodeGenerator->addInstruction(instr);
- }
+ expr.loadInAccumulator();
+ Instruction::ThrowException instr;
+ bytecodeGenerator->addInstruction(instr);
return false;
}
void Codegen::handleTryCatch(TryStatement *ast)
{
Q_ASSERT(ast);
- if (_context->isStrict &&
- (ast->catchExpression->name == QLatin1String("eval") || ast->catchExpression->name == QLatin1String("arguments"))) {
- throwSyntaxError(ast->catchExpression->identifierToken, QStringLiteral("Catch variable name may not be eval or arguments in strict mode"));
- return;
- }
-
RegisterScope scope(this);
BytecodeGenerator::Label noException = bytecodeGenerator->newLabel();
{
@@ -2761,8 +3381,6 @@ bool Codegen::visit(TryStatement *ast)
if (hasError)
return true;
- Q_ASSERT(_context->hasTry);
-
RegisterScope scope(this);
if (ast->finallyExpression && ast->finallyExpression->statement) {
@@ -2817,17 +3435,18 @@ bool Codegen::visit(WithStatement *ast)
RegisterScope scope(this);
- _context->hasWith = true;
-
Reference src = expression(ast->expression);
if (hasError)
return false;
src = src.storeOnStack(); // trigger load before we setup the exception handler, so exceptions here go to the right place
src.loadInAccumulator();
- ControlFlowWith flow(this);
-
- statement(ast->statement);
+ enterContext(ast);
+ {
+ ControlFlowWith flow(this);
+ statement(ast->statement);
+ }
+ leaveContext();
return false;
}
@@ -3080,6 +3699,22 @@ Codegen::RValue Codegen::RValue::storeOnStack() const
}
}
+void Codegen::RValue::loadInAccumulator() const
+{
+ switch (type) {
+ case Accumulator:
+ // nothing to do
+ return;
+ case StackSlot:
+ return Reference::fromStackSlot(codegen, theStackSlot).loadInAccumulator();
+ case Const:
+ return Reference::fromConst(codegen, constant).loadInAccumulator();
+ default:
+ Q_UNREACHABLE();
+ }
+
+}
+
Codegen::Reference::Reference(const Codegen::Reference &other)
{
*this = other;
@@ -3093,6 +3728,11 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
case Invalid:
case Accumulator:
break;
+ case Super:
+ break;
+ case SuperProperty:
+ property = other.property;
+ break;
case StackSlot:
theStackSlot = other.theStackSlot;
break;
@@ -3127,6 +3767,7 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
isArgOrEval = other.isArgOrEval;
codegen = other.codegen;
isReadonly = other.isReadonly;
+ isReferenceToConst = other.isReferenceToConst;
stackSlotIsLocalOrArgument = other.stackSlotIsLocalOrArgument;
isVolatile = other.isVolatile;
global = other.global;
@@ -3141,6 +3782,10 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const
case Invalid:
case Accumulator:
break;
+ case Super:
+ return true;
+ case SuperProperty:
+ return property == other.property;
case StackSlot:
return theStackSlot == other.theStackSlot;
case ScopedLocal:
@@ -3184,6 +3829,9 @@ Codegen::Reference Codegen::Reference::asLValue() const
case Invalid:
case Accumulator:
Q_UNREACHABLE();
+ case Super:
+ codegen->throwSyntaxError(AST::SourceLocation(), QStringLiteral("Super lvalues not implemented."));
+ return *this;
case Member:
if (!propertyBase.isStackSlot()) {
Reference r = *this;
@@ -3209,6 +3857,28 @@ Codegen::Reference Codegen::Reference::storeConsumeAccumulator() const
return Reference();
}
+Codegen::Reference Codegen::Reference::baseObject() const
+{
+ if (type == Reference::QmlScopeObject || type == Reference::QmlContextObject) {
+ return Reference::fromStackSlot(codegen, qmlBase.stackSlot());
+ } else if (type == Reference::Member) {
+ RValue rval = propertyBase;
+ if (!rval.isValid())
+ return Reference::fromConst(codegen, Encode::undefined());
+ if (rval.isAccumulator())
+ return Reference::fromAccumulator(codegen);
+ if (rval.isStackSlot())
+ Reference::fromStackSlot(codegen, rval.stackSlot());
+ if (rval.isConst())
+ return Reference::fromConst(codegen, rval.constantValue());
+ Q_UNREACHABLE();
+ } else if (type == Reference::Subscript) {
+ return Reference::fromStackSlot(codegen, elementBase.stackSlot());
+ } else {
+ return Reference::fromConst(codegen, Encode::undefined());
+ }
+}
+
Codegen::Reference Codegen::Reference::storeOnStack() const
{ return doStoreOnStack(-1); }
@@ -3230,7 +3900,7 @@ Codegen::Reference Codegen::Reference::doStoreOnStack(int slotIndex) const
}
Reference slot = Reference::fromStackSlot(codegen, slotIndex);
- if (isConst()) {
+ if (isConstant()) {
Instruction::MoveConst move;
move.constIndex = codegen->registerConstant(constant);
move.destTemp = slot.stackSlot();
@@ -3280,7 +3950,29 @@ bool Codegen::Reference::storeWipesAccumulator() const
void Codegen::Reference::storeAccumulator() const
{
+ if (isReferenceToConst) {
+ // throw a type error
+ RegisterScope scope(codegen);
+ Reference r = codegen->referenceForName(QStringLiteral("TypeError"), false);
+ r = r.storeOnStack();
+ Instruction::Construct construct;
+ construct.func = r.stackSlot();
+ construct.argc = 0;
+ construct.argv = 0;
+ codegen->bytecodeGenerator->addInstruction(construct);
+ Instruction::ThrowException throwException;
+ codegen->bytecodeGenerator->addInstruction(throwException);
+ return;
+ }
switch (type) {
+ case Super:
+ Q_UNREACHABLE();
+ return;
+ case SuperProperty:
+ Instruction::StoreSuperProperty store;
+ store.property = property.stackSlot();
+ codegen->bytecodeGenerator->addInstruction(store);
+ return;
case StackSlot: {
Instruction::StoreReg store;
store.reg = theStackSlot;
@@ -3313,7 +4005,7 @@ void Codegen::Reference::storeAccumulator() const
}
} return;
case Member:
- if (codegen->useFastLookups) {
+ if (!disable_lookups && codegen->useFastLookups) {
Instruction::SetLookup store;
store.base = propertyBase.stackSlot();
store.index = codegen->registerSetterLookup(propertyNameIndex);
@@ -3358,6 +4050,14 @@ void Codegen::Reference::loadInAccumulator() const
switch (type) {
case Accumulator:
return;
+ case Super:
+ Q_UNREACHABLE();
+ return;
+ case SuperProperty:
+ Instruction::LoadSuperProperty load;
+ load.property = property.stackSlot();
+ codegen->bytecodeGenerator->addInstruction(load);
+ return;
case Const: {
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // the loads below are empty structs.
@@ -3429,7 +4129,7 @@ QT_WARNING_POP
return;
}
}
- if (codegen->useFastLookups && global) {
+ if (!disable_lookups && codegen->useFastLookups && global) {
Instruction::LoadGlobalLookup load;
load.index = codegen->registerGlobalGetterLookup(nameAsIndex());
codegen->bytecodeGenerator->addInstruction(load);
@@ -3440,46 +4140,23 @@ QT_WARNING_POP
}
return;
case Member:
- if (codegen->useFastLookups) {
- if (propertyBase.isAccumulator()) {
- Instruction::GetLookupA load;
- load.index = codegen->registerGetterLookup(propertyNameIndex);
- codegen->bytecodeGenerator->addInstruction(load);
- } else {
- Instruction::GetLookup load;
- load.base = propertyBase.storeOnStack().stackSlot();
- load.index = codegen->registerGetterLookup(propertyNameIndex);
- codegen->bytecodeGenerator->addInstruction(load);
- }
- } else {
- if (propertyBase.isAccumulator()) {
- Instruction::LoadPropertyA load;
- load.name = propertyNameIndex;
- codegen->bytecodeGenerator->addInstruction(load);
- } else {
- Instruction::LoadProperty load;
- load.base = propertyBase.storeOnStack().stackSlot();
- load.name = propertyNameIndex;
- codegen->bytecodeGenerator->addInstruction(load);
- }
- }
- return;
- case Subscript: {
- if (elementSubscript.isAccumulator()) {
- Instruction::LoadElementA load;
- load.base = elementBase;
- codegen->bytecodeGenerator->addInstruction(load);
- } else if (elementSubscript.isConst()) {
- Reference::fromConst(codegen, elementSubscript.constantValue()).loadInAccumulator();
- Instruction::LoadElementA load;
- load.base = elementBase;
+ if (!disable_lookups && codegen->useFastLookups) {
+ propertyBase.loadInAccumulator();
+ Instruction::GetLookup load;
+ load.index = codegen->registerGetterLookup(propertyNameIndex);
codegen->bytecodeGenerator->addInstruction(load);
} else {
- Instruction::LoadElement load;
- load.base = elementBase;
- load.index = elementSubscript.storeOnStack().stackSlot();
+ propertyBase.loadInAccumulator();
+ Instruction::LoadProperty load;
+ load.name = propertyNameIndex;
codegen->bytecodeGenerator->addInstruction(load);
}
+ return;
+ case Subscript: {
+ elementSubscript.loadInAccumulator();
+ Instruction::LoadElement load;
+ load.base = elementBase;
+ codegen->bytecodeGenerator->addInstruction(load);
} return;
case QmlScopeObject: {
Instruction::LoadScopeObjectProperty load;
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index d51dc29517..337c4dbfe3 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -66,6 +66,7 @@
#endif
#include <private/qv4util_p.h>
#include <private/qv4bytecodegenerator_p.h>
+#include <private/qv4stackframe_p.h>
QT_BEGIN_NAMESPACE
@@ -101,7 +102,7 @@ public:
const QString &sourceCode,
AST::Program *ast,
Module *module,
- CompilationMode mode = GlobalCode);
+ ContextType contextType = ContextType::Global);
public:
class VolatileMemoryLocationScanner;
@@ -172,11 +173,14 @@ public:
}
Q_REQUIRED_RESULT RValue storeOnStack() const;
+ void loadInAccumulator() const;
};
struct Reference {
enum Type {
Invalid,
Accumulator,
+ Super,
+ SuperProperty,
StackSlot,
ScopedLocal,
Name,
@@ -197,6 +201,8 @@ public:
Reference &operator =(const Reference &other);
bool operator==(const Reference &other) const;
+ bool operator!=(const Reference &other) const
+ { return !(*this == other); }
bool isValid() const { return type != Invalid; }
bool loadTriggersSideEffect() const {
@@ -209,8 +215,10 @@ public:
return false;
}
}
- bool isConst() const { return type == Const; }
+ bool isConstant() const { return type == Const; }
bool isAccumulator() const { return type == Accumulator; }
+ bool isSuper() const { return type == Super; }
+ bool isSuperProperty() const { return type == SuperProperty; }
bool isStackSlot() const { return type == StackSlot; }
bool isRegister() const {
return isStackSlot();
@@ -241,6 +249,9 @@ public:
static Reference fromAccumulator(Codegen *cg) {
return Reference(cg, Accumulator);
}
+ static Reference fromSuper(Codegen *cg) {
+ return Reference(cg, Super);
+ }
static Reference fromStackSlot(Codegen *cg, int tempIndex = -1, bool isLocal = false) {
Reference r(cg, StackSlot);
if (tempIndex == -1)
@@ -273,6 +284,12 @@ public:
r.propertyNameIndex = r.codegen->registerString(name);
return r;
}
+ static Reference fromSuperProperty(const Reference &property) {
+ Q_ASSERT(property.isStackSlot());
+ Reference r(property.codegen, SuperProperty);
+ r.property = property.stackSlot();
+ return r;
+ }
static Reference fromSubscript(const Reference &baseRef, const Reference &subscript) {
Q_ASSERT(baseRef.isStackSlot());
Reference r(baseRef.codegen, Subscript);
@@ -322,6 +339,8 @@ public:
Q_REQUIRED_RESULT Reference storeRetainAccumulator() const;
Reference storeConsumeAccumulator() const;
+ Q_REQUIRED_RESULT Reference baseObject() const;
+
bool storeWipesAccumulator() const;
void loadInAccumulator() const;
@@ -357,10 +376,12 @@ public:
qint16 qmlNotifyIndex;
PropertyCapturePolicy capturePolicy;
};
+ Moth::StackSlot property; // super property
};
QString name;
mutable bool isArgOrEval = false;
bool isReadonly = false;
+ bool isReferenceToConst = false;
bool stackSlotIsLocalOrArgument = false;
bool isVolatile = false;
bool global = false;
@@ -464,7 +485,10 @@ protected:
void enterContext(AST::Node *node);
int leaveContext();
-
+public:
+ Context *enterBlock(AST::Node *node);
+ int leaveBlock() { return leaveContext(); }
+protected:
void leaveLoop();
enum UnaryOperation {
@@ -482,6 +506,7 @@ protected:
void addCJump();
+public:
int registerString(const QString &name) {
return jsUnitGenerator->registerString(name);
}
@@ -493,33 +518,37 @@ protected:
// Returns index in _module->functions
virtual int defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
- AST::SourceElements *body);
+ AST::StatementList *body);
+protected:
void statement(AST::Statement *ast);
void statement(AST::ExpressionNode *ast);
void condition(AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue,
const BytecodeGenerator::Label *iffalse,
bool trueBlockFollowsCondition);
Reference expression(AST::ExpressionNode *ast);
- Result sourceElement(AST::SourceElement *ast);
void accept(AST::Node *node);
- void functionBody(AST::FunctionBody *ast);
void program(AST::Program *ast);
- void sourceElements(AST::SourceElements *ast);
void statementList(AST::StatementList *ast);
- void variableDeclaration(AST::VariableDeclaration *ast);
+ void variableDeclaration(AST::PatternElement *ast);
void variableDeclarationList(AST::VariableDeclarationList *ast);
- Reference referenceForName(const QString &name, bool lhs);
+ Reference targetForPatternElement(AST::PatternElement *p);
+ void initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false);
+ void destructurePropertyList(const Reference &object, AST::PatternPropertyList *bindingList, bool isDefinition = false);
+ void destructureElementList(const Reference &array, AST::PatternElementList *bindingList, bool isDefinition = false);
+ void destructurePattern(AST::Pattern *p, const Reference &rhs);
- void loadClosure(int index);
+ Reference referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name);
// Hook provided to implement QML lookup semantics
virtual Reference fallbackNameLookup(const QString &name);
virtual void beginFunctionBodyHook() {}
+ void emitReturn(const Reference &expr);
+
// nodes
bool visit(AST::ArgumentList *ast) override;
bool visit(AST::CaseBlock *ast) override;
@@ -527,16 +556,10 @@ protected:
bool visit(AST::CaseClauses *ast) override;
bool visit(AST::Catch *ast) override;
bool visit(AST::DefaultClause *ast) override;
- bool visit(AST::ElementList *ast) override;
bool visit(AST::Elision *ast) override;
bool visit(AST::Finally *ast) override;
bool visit(AST::FormalParameterList *ast) override;
- bool visit(AST::FunctionBody *ast) override;
bool visit(AST::Program *ast) override;
- bool visit(AST::PropertyNameAndValue *ast) override;
- bool visit(AST::PropertyAssignmentList *ast) override;
- bool visit(AST::PropertyGetterSetter *ast) override;
- bool visit(AST::SourceElements *ast) override;
bool visit(AST::StatementList *ast) override;
bool visit(AST::UiArrayMemberList *ast) override;
bool visit(AST::UiImport *ast) override;
@@ -548,19 +571,25 @@ protected:
bool visit(AST::UiProgram *ast) override;
bool visit(AST::UiQualifiedId *ast) override;
bool visit(AST::UiQualifiedPragmaId *ast) override;
- bool visit(AST::VariableDeclaration *ast) override;
bool visit(AST::VariableDeclarationList *ast) override;
+ bool visit(AST::PatternElement *ast) override;
+ bool visit(AST::PatternElementList *ast) override;
+ bool visit(AST::PatternProperty *ast) override;
+ bool visit(AST::PatternPropertyList *ast) override;
+
// expressions
bool visit(AST::Expression *ast) override;
- bool visit(AST::ArrayLiteral *ast) override;
+ bool visit(AST::ArrayPattern *ast) override;
bool visit(AST::ArrayMemberExpression *ast) override;
bool visit(AST::BinaryExpression *ast) override;
bool visit(AST::CallExpression *ast) override;
bool visit(AST::ConditionalExpression *ast) override;
bool visit(AST::DeleteExpression *ast) override;
bool visit(AST::FalseLiteral *ast) override;
+ bool visit(AST::SuperLiteral *ast) override;
bool visit(AST::FieldMemberExpression *ast) override;
+ bool visit(AST::TaggedTemplate *ast) override;
bool visit(AST::FunctionExpression *ast) override;
bool visit(AST::IdentifierExpression *ast) override;
bool visit(AST::NestedExpression *ast) override;
@@ -569,13 +598,14 @@ protected:
bool visit(AST::NotExpression *ast) override;
bool visit(AST::NullExpression *ast) override;
bool visit(AST::NumericLiteral *ast) override;
- bool visit(AST::ObjectLiteral *ast) override;
+ bool visit(AST::ObjectPattern *ast) override;
bool visit(AST::PostDecrementExpression *ast) override;
bool visit(AST::PostIncrementExpression *ast) override;
bool visit(AST::PreDecrementExpression *ast) override;
bool visit(AST::PreIncrementExpression *ast) override;
bool visit(AST::RegExpLiteral *ast) override;
bool visit(AST::StringLiteral *ast) override;
+ bool visit(AST::TemplateLiteral *ast) override;
bool visit(AST::ThisExpression *ast) override;
bool visit(AST::TildeExpression *ast) override;
bool visit(AST::TrueLiteral *ast) override;
@@ -584,10 +614,9 @@ protected:
bool visit(AST::UnaryPlusExpression *ast) override;
bool visit(AST::VoidExpression *ast) override;
bool visit(AST::FunctionDeclaration *ast) override;
-
- // source elements
- bool visit(AST::FunctionSourceElement *ast) override;
- bool visit(AST::StatementSourceElement *ast) override;
+ bool visit(AST::YieldExpression *ast) override;
+ bool visit(AST::ClassExpression *ast) override;
+ bool visit(AST::ClassDeclaration *ast) override;
// statements
bool visit(AST::Block *ast) override;
@@ -601,8 +630,6 @@ protected:
bool visit(AST::ForStatement *ast) override;
bool visit(AST::IfStatement *ast) override;
bool visit(AST::LabelledStatement *ast) override;
- bool visit(AST::LocalForEachStatement *ast) override;
- bool visit(AST::LocalForStatement *ast) override;
bool visit(AST::ReturnStatement *ast) override;
bool visit(AST::SwitchStatement *ast) override;
bool visit(AST::ThrowStatement *ast) override;
@@ -631,18 +658,36 @@ public:
Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right);
Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
- struct Arguments { int argc; int argv; };
+ struct Arguments { int argc; int argv; bool hasSpread; };
Arguments pushArgs(AST::ArgumentList *args);
+ void handleCall(Reference &base, Arguments calldata);
+
+ Arguments pushTemplateArgs(AST::TemplateLiteral *args);
+ int createTemplateArray(AST::TemplateLiteral *t);
void setUseFastLookups(bool b) { useFastLookups = b; }
void handleTryCatch(AST::TryStatement *ast);
void handleTryFinally(AST::TryStatement *ast);
+
+ Reference referenceForName(const QString &name, bool lhs);
+
QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(bool generateUnitData = true);
static QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading();
Context *currentContext() const { return _context; }
+ BytecodeGenerator *generator() const { return bytecodeGenerator; }
+
+ void loadClosure(int index);
+
+ Module *module() const { return _module; }
+
+ BytecodeGenerator::Label returnLabel() {
+ if (!_returnLabel)
+ _returnLabel = new BytecodeGenerator::Label(bytecodeGenerator->newLabel());
+ return *_returnLabel;
+ }
protected:
friend class ScanFunctions;
@@ -650,16 +695,22 @@ protected:
friend struct ControlFlowCatch;
friend struct ControlFlowFinally;
Result _expr;
- VolatileMemoryLocations _volataleMemoryLocations;
+ VolatileMemoryLocations _volatileMemoryLocations;
Module *_module;
int _returnAddress;
Context *_context;
+ Context *_functionContext = nullptr;
AST::LabelledStatement *_labelledStatement;
QV4::Compiler::JSUnitGenerator *jsUnitGenerator;
BytecodeGenerator *bytecodeGenerator = nullptr;
+ Moth::BytecodeGenerator::Label *_returnLabel = nullptr;
bool _strictMode;
bool useFastLookups = true;
bool requiresReturnValue = false;
+ bool insideSwitch = false;
+ bool inFormalParameterList = false;
+ bool functionEndsWithReturn = false;
+ ControlFlow *controlFlow = nullptr;
bool _fileNameIsUrl;
bool hasError;
@@ -667,6 +718,7 @@ protected:
private:
VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast) const;
+ void handleConstruct(const Reference &base, AST::ArgumentList *args);
};
}
diff --git a/src/qml/compiler/qv4compilationunitmapper_unix.cpp b/src/qml/compiler/qv4compilationunitmapper_unix.cpp
index 8348613888..1fef4d38f4 100644
--- a/src/qml/compiler/qv4compilationunitmapper_unix.cpp
+++ b/src/qml/compiler/qv4compilationunitmapper_unix.cpp
@@ -92,8 +92,16 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
void CompilationUnitMapper::close()
{
- if (dataPtr != nullptr)
- munmap(dataPtr, length);
+ // Do not unmap the data here.
+ if (dataPtr != nullptr) {
+ // Do not unmap cache files that are built with the StaticData flag. That's the majority of
+ // them and it's necessary to benefit from the QString literal optimization. There might
+ // still be QString instances around that point into that memory area. The memory is backed
+ // on the disk, so the kernel is free to release the pages and all that remains is the
+ // address space allocation.
+ if (!(reinterpret_cast<CompiledData::Unit*>(dataPtr)->flags & CompiledData::Unit::StaticData))
+ munmap(dataPtr, length);
+ }
dataPtr = nullptr;
}
diff --git a/src/qml/compiler/qv4compilationunitmapper_win.cpp b/src/qml/compiler/qv4compilationunitmapper_win.cpp
index 8b000021f8..3e44d045fc 100644
--- a/src/qml/compiler/qv4compilationunitmapper_win.cpp
+++ b/src/qml/compiler/qv4compilationunitmapper_win.cpp
@@ -90,14 +90,9 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
if (!header.verifyHeader(sourceTimeStamp, errorString))
return nullptr;
- const uint mappingFlags = header.flags & QV4::CompiledData::Unit::ContainsMachineCode
- ? PAGE_EXECUTE_READ : PAGE_READONLY;
- const uint viewFlags = header.flags & QV4::CompiledData::Unit::ContainsMachineCode
- ? (FILE_MAP_READ | FILE_MAP_EXECUTE) : FILE_MAP_READ;
-
// Data structure and qt version matched, so now we can access the rest of the file safely.
- HANDLE fileMappingHandle = CreateFileMapping(handle, 0, mappingFlags, 0, 0, 0);
+ HANDLE fileMappingHandle = CreateFileMapping(handle, 0, PAGE_READONLY, 0, 0, 0);
if (!fileMappingHandle) {
*errorString = qt_error_string(GetLastError());
return nullptr;
@@ -107,7 +102,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
CloseHandle(fileMappingHandle);
});
- dataPtr = MapViewOfFile(fileMappingHandle, viewFlags, 0, 0, 0);
+ dataPtr = MapViewOfFile(fileMappingHandle, FILE_MAP_READ, 0, 0, 0);
if (!dataPtr) {
*errorString = qt_error_string(GetLastError());
return nullptr;
@@ -118,8 +113,15 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
void CompilationUnitMapper::close()
{
- if (dataPtr != nullptr)
- UnmapViewOfFile(dataPtr);
+ if (dataPtr != nullptr) {
+ // Do not unmap cache files that are built with the StaticData flag. That's the majority of
+ // them and it's necessary to benefit from the QString literal optimization. There might
+ // still be QString instances around that point into that memory area. The memory is backed
+ // on the disk, so the kernel is free to release the pages and all that remains is the
+ // address space allocation.
+ if (!(reinterpret_cast<CompiledData::Unit*>(dataPtr)->flags & CompiledData::Unit::StaticData))
+ UnmapViewOfFile(dataPtr);
+ }
dataPtr = nullptr;
}
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 8dcc068a06..02aee47eea 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -78,26 +78,10 @@ namespace CompiledData {
static_assert(sizeof(Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1, "Compile hash length exceeds reserved size in data structure. Please adjust and bump the format version");
-#if !defined(V4_BOOTSTRAP)
-static QString cacheFilePath(const QUrl &url)
+CompilationUnit::CompilationUnit(const Unit *unitData)
{
- const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- const QString localCachePath = localSourcePath + QLatin1Char('c');
-#ifndef Q_OS_ANDROID
- if (QFile::exists(localCachePath) || QFileInfo(QFileInfo(localSourcePath).dir().absolutePath()).isWritable())
- return localCachePath;
-#endif
- QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
- fileNameHash.addData(localSourcePath.toUtf8());
- QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
- QDir::root().mkpath(directory);
- return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + QFileInfo(localCachePath).completeSuffix();
+ data = unitData;
}
-#endif
-
-CompilationUnit::CompilationUnit(const Unit *unitData)
- : data(unitData)
-{}
#ifndef V4_BOOTSTRAP
CompilationUnit::~CompilationUnit()
@@ -108,6 +92,17 @@ CompilationUnit::~CompilationUnit()
data = nullptr;
}
+QString CompilationUnit::localCacheFilePath(const QUrl &url)
+{
+ const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
+ const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix();
+ QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
+ fileNameHash.addData(localSourcePath.toUtf8());
+ QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
+ QDir::root().mkpath(directory);
+ return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix;
+}
+
QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
{
this->engine = engine;
@@ -157,15 +152,15 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
}
if (data->jsClassTableSize) {
- runtimeClasses = (QV4::InternalClass**)malloc(data->jsClassTableSize * sizeof(QV4::InternalClass*));
+ runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
+ // memset the regexps to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
for (uint i = 0; i < data->jsClassTableSize; ++i) {
int memberCount = 0;
const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
- QV4::InternalClass *klass = engine->internalClasses[QV4::ExecutionEngine::Class_Object];
+ runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
for (int j = 0; j < memberCount; ++j, ++member)
- klass = klass->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
-
- runtimeClasses[i] = klass;
+ runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
}
}
@@ -215,8 +210,6 @@ void CompilationUnit::unlink()
propertyCaches.clear();
- for (int ii = 0; ii < dependentScripts.count(); ++ii)
- dependentScripts.at(ii)->release();
dependentScripts.clear();
typeNameCache = nullptr;
@@ -244,29 +237,43 @@ void CompilationUnit::unlink()
void CompilationUnit::markObjects(QV4::MarkStack *markStack)
{
- for (uint i = 0; i < data->stringTableSize; ++i)
- if (runtimeStrings[i])
- runtimeStrings[i]->mark(markStack);
+ if (runtimeStrings) {
+ for (uint i = 0; i < data->stringTableSize; ++i)
+ if (runtimeStrings[i])
+ runtimeStrings[i]->mark(markStack);
+ }
if (runtimeRegularExpressions) {
for (uint i = 0; i < data->regexpTableSize; ++i)
runtimeRegularExpressions[i].mark(markStack);
}
+ if (runtimeClasses) {
+ for (uint i = 0; i < data->jsClassTableSize; ++i)
+ if (runtimeClasses[i])
+ runtimeClasses[i]->mark(markStack);
+ }
+ for (QV4::Function *f : qAsConst(runtimeFunctions))
+ if (f && f->internalClass)
+ f->internalClass->mark(markStack);
+ for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks))
+ if (c)
+ c->mark(markStack);
+
+ if (runtimeLookups) {
+ for (uint i = 0; i < data->lookupTableSize; ++i)
+ runtimeLookups[i].markObjects(markStack);
+ }
}
-IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
+IdentifierHash CompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
{
- auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
- if (it == namedObjectsPerComponentCache.end()) {
- IdentifierHash namedObjectCache(engine);
- const CompiledData::Object *component = data->objectAt(componentObjectIndex);
- const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
- for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
- const CompiledData::Object *namedObject = data->objectAt(*namedObjectIndexPtr);
- namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
- }
- it = namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
- }
- return *it;
+ IdentifierHash namedObjectCache(engine);
+ const CompiledData::Object *component = data->objectAt(componentObjectIndex);
+ const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
+ for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
+ const CompiledData::Object *namedObject = data->objectAt(*namedObjectIndexPtr);
+ namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
+ }
+ return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
}
void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
@@ -344,7 +351,11 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeS
const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
- CompiledData::Unit *mappedUnit = cacheFile->open(cacheFilePath(url), sourceTimeStamp, errorString);
+ QString cachePath = sourcePath + QLatin1Char('c');
+ if (!QFile::exists(cachePath))
+ cachePath = localCacheFilePath(url);
+
+ CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
if (!mappedUnit)
return false;
@@ -367,7 +378,22 @@ void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
runtimeFunctions.resize(data->functionTableSize);
for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
- runtimeFunctions[i] = new QV4::Function(engine, this, compiledFunction, &Moth::VME::exec);
+ runtimeFunctions[i] = new QV4::Function(engine, this, compiledFunction);
+ }
+
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope);
+
+ runtimeBlocks.resize(data->blockTableSize);
+ for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
+ const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
+ ic = engine->internalClasses(EngineBase::Class_CallContext);
+
+ // first locals
+ const quint32_le *localsIndices = compiledBlock->localsTable();
+ for (quint32 i = 0; i < compiledBlock->nLocals; ++i)
+ ic = ic->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
+ runtimeBlocks[i] = ic->d();
}
}
@@ -391,7 +417,7 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
- const QString outputFileName = cacheFilePath(unitUrl);
+ const QString outputFileName = localCacheFilePath(unitUrl);
#endif
#if QT_CONFIG(temporaryfile)
@@ -476,8 +502,11 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
QQmlJS::AST::FormalParameterList *parameters = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node)->formals;
changedSignalParameters << parameters;
- for (; parameters; parameters = parameters->next)
- stringTable.registerString(parameters->name.toString());
+ if (parameters) {
+ const QStringList formals = parameters->formals();
+ for (const QString &arg : formals)
+ stringTable.registerString(arg);
+ }
}
}
@@ -500,14 +529,14 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
function->formalsOffset = signalParameterNameTableOffset - jsUnit->functionOffsetTable()[functionIndex];
- for (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i);
- parameters; parameters = parameters->next) {
- signalParameterNameTable.append(stringTable.getStringId(parameters->name.toString()));
- function->nFormals = function->nFormals + 1;
- }
+ if (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i)) {
+ const QStringList formals = parameters->formals();
+ for (const QString &arg : formals)
+ signalParameterNameTable.append(stringTable.getStringId(arg));
- // Hack to ensure an activation is created.
- function->flags |= QV4::CompiledData::Function::HasCatchOrWith | QV4::CompiledData::Function::HasDirectEval;
+ function->nFormals = formals.size();
+ }
+ function->length = function->nFormals;
signalParameterNameTableOffset += function->nFormals * sizeof(quint32);
}
@@ -626,7 +655,7 @@ QString Binding::valueAsScriptString(const Unit *unit) const
/*!
Returns the property cache, if one alread exists. The cache is not referenced.
*/
-QQmlPropertyCache *ResolvedTypeReference::propertyCache() const
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
{
if (type.isValid())
return typePropertyCache;
@@ -637,7 +666,7 @@ QQmlPropertyCache *ResolvedTypeReference::propertyCache() const
/*!
Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
*/
-QQmlPropertyCache *ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
{
if (typePropertyCache) {
return typePropertyCache;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 1df9d6794f..c1be00ea27 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -186,32 +186,72 @@ struct JSClass
};
static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+// This data structure is intended to be binary compatible with QStringData/QStaticStringData on
+// 64-bit and 32-bit little-endian architectures, in all directions. So the same structure mapped
+// from a file must be castable to a QStringData regardless of the pointer size. With the first
+// few fields that's easy, they're always 32-bit. However the offset field of QArrayData is a
+// ptrdiff_t and thus variable in size.
+// On 64-bit systems compilers enforce an 8-byte alignment and thus place it at offset 16, while
+// on 32-bit systems offset 12 is sufficient. Therefore the two values don't overlap and contain
+// the same value.
struct String
{
+ qint32_le refcount; // -1
qint32_le size;
+ quint32_le allocAndCapacityReservedFlag; // 0
+ quint32_le offsetOn32Bit;
+ quint64_le offsetOn64Bit;
// uint16 strdata[]
static int calculateSize(const QString &str) {
- return (sizeof(String) + str.length() * sizeof(quint16) + 7) & ~0x7;
+ return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7;
}
};
-static_assert(sizeof(String) == 4, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(String) == 24, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+
+// Ensure compatibility with QString
+static_assert(offsetof(QArrayData, ref) == offsetof(String, refcount), "refcount must be at the same location");
+static_assert(offsetof(QArrayData, size) == offsetof(String, size), "size must be at the same location");
+static_assert(offsetof(String, offsetOn64Bit) == 16, "offset must be at 8-byte aligned location");
+static_assert(offsetof(String, offsetOn32Bit) == 12, "offset must be at 4-byte aligned location");
+#if QT_POINTER_SIZE == 8
+static_assert(offsetof(QArrayData, offset) == offsetof(String, offsetOn64Bit), "offset must be at the same location");
+#else
+static_assert(offsetof(QArrayData, offset) == offsetof(String, offsetOn32Bit), "offset must be at the same location");
+#endif
struct CodeOffsetToLine {
quint32_le codeOffset;
quint32_le line;
};
+struct Block
+{
+ quint32_le nLocals;
+ quint32_le localsOffset;
+
+ const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
+
+ static int calculateSize(int nLocals) {
+ int trailingData = nLocals*sizeof (quint32);
+ size_t size = align(align(sizeof(Block)) + size_t(trailingData));
+ Q_ASSERT(size < INT_MAX);
+ return int(size);
+ }
+
+ static size_t align(size_t a) {
+ return (a + 7) & ~size_t(7);
+ }
+};
+
// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
// for unaligned access. The ordering of the fields is also from largest to smallest.
struct Function
{
enum Flags : unsigned int {
IsStrict = 0x1,
- HasDirectEval = 0x2,
- UsesArgumentsObject = 0x4,
-// Unused = 0x8,
- HasCatchOrWith = 0x10
+ IsArrowFunction = 0x2,
+ IsGenerator = 0x4
};
// Absolute offset into file where the code for this function is located.
@@ -219,6 +259,7 @@ struct Function
quint32_le codeSize;
quint32_le nameIndex;
+ quint32_le length;
quint32_le nFormals;
quint32_le formalsOffset;
quint32_le nLocals;
@@ -238,16 +279,14 @@ struct Function
quint32_le dependingScopePropertiesOffset; // Array of int pairs (property index and notify index)
// Qml Extensions End
-// quint32 formalsIndex[nFormals]
-// quint32 localsIndex[nLocals]
-// quint32 offsetForInnerFunctions[nInnerFunctions]
-// Function[nInnerFunctions]
-
// Keep all unaligned data at the end
quint8 flags;
quint8 padding1;
quint16_le padding2;
+ // quint32 formalsIndex[nFormals]
+ // quint32 localsIndex[nLocals]
+
const quint32_le *formalsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); }
const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
const CodeOffsetToLine *lineNumberTable() const { return reinterpret_cast<const CodeOffsetToLine *>(reinterpret_cast<const char *>(this) + lineNumberOffset); }
@@ -260,7 +299,7 @@ struct Function
const quint32_le *formalsEnd() const { return formalsTable() + nFormals; }
// ---
- const uchar *code() const { return reinterpret_cast<const uchar *>(this) + codeOffset; }
+ const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; }
@@ -276,7 +315,44 @@ struct Function
return (a + 7) & ~size_t(7);
}
};
-static_assert(sizeof(Function) == 76, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Function) == 80, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+
+struct Method {
+ enum Type {
+ Regular,
+ Getter,
+ Setter
+ };
+
+ quint32_le name;
+ quint32_le type;
+ quint32_le function;
+};
+
+struct Class
+{
+ quint32_le nameIndex;
+ quint32_le scopeIndex;
+ quint32_le constructorFunction;
+ quint32_le nStaticMethods;
+ quint32_le nMethods;
+ quint32_le methodTableOffset;
+
+ const Method *methodTable() const { return reinterpret_cast<const Method *>(reinterpret_cast<const char *>(this) + methodTableOffset); }
+
+ static int calculateSize(int nStaticMethods, int nMethods) {
+ int trailingData = (nStaticMethods + nMethods) * sizeof(Method);
+ size_t size = align(sizeof(Class) + trailingData);
+ Q_ASSERT(size < INT_MAX);
+ return int(size);
+ }
+
+ static size_t align(size_t a) {
+ return (a + 7) & ~size_t(7);
+ }
+};
+static_assert(sizeof(Class) == 24, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+
// Qml data structures
@@ -385,8 +461,8 @@ struct Q_QML_PRIVATE_EXPORT Binding
static QString escapedString(const QString &string);
- bool containsTranslations() const { return type == Type_Translation || type == Type_TranslationById; }
- bool evaluatesToString() const { return type == Type_String || containsTranslations(); }
+ bool isTranslationBinding() const { return type == Type_Translation || type == Type_TranslationById; }
+ bool evaluatesToString() const { return type == Type_String || isTranslationBinding(); }
QString valueAsString(const Unit *unit) const;
QString valueAsScriptString(const Unit *unit) const;
@@ -701,14 +777,17 @@ struct Unit
StaticData = 0x4, // Unit data persistent in memory?
IsSingleton = 0x8,
IsSharedLibrary = 0x10, // .pragma shared?
- ContainsMachineCode = 0x20, // used to determine if we need to mmap with execute permissions
- PendingTypeCompilation = 0x40 // the QML data structures present are incomplete and require type compilation
+ PendingTypeCompilation = 0x20 // the QML data structures present are incomplete and require type compilation
};
quint32_le flags;
quint32_le stringTableSize;
quint32_le offsetToStringTable;
quint32_le functionTableSize;
quint32_le offsetToFunctionTable;
+ quint32_le classTableSize;
+ quint32_le offsetToClassTable;
+ quint32_le blockTableSize;
+ quint32_le offsetToBlockTable;
quint32_le lookupTableSize;
quint32_le offsetToLookupTable;
quint32_le regexpTableSize;
@@ -753,11 +832,11 @@ struct Unit
if (str->size == 0)
return QString();
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (flags & StaticData) {
+ const QStringDataPtr holder = { const_cast<QStringData *>(reinterpret_cast<const QStringData*>(str)) };
+ return QString(holder);
+ }
const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
- // Too risky to do this while we unmap disk backed compilation but keep pointers to string
- // data in the identifier tables.
- // if (flags & StaticData)
- // return QString::fromRawData(characters, str->size);
return QString(characters, str->size);
#else
const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
@@ -770,6 +849,8 @@ struct Unit
}
const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
+ const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
+ const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
const Function *functionAt(int idx) const {
const quint32_le *offsetTable = functionOffsetTable();
@@ -777,6 +858,18 @@ struct Unit
return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
}
+ const Class *classAt(int idx) const {
+ const quint32_le *offsetTable = classOffsetTable();
+ const quint32_le offset = offsetTable[idx];
+ return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
+ }
+
+ const Block *blockAt(int idx) const {
+ const quint32_le *offsetTable = blockOffsetTable();
+ const quint32_le offset = offsetTable[idx];
+ return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
+ }
+
const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
const RegExp *regexpAt(int index) const {
return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
@@ -795,7 +888,7 @@ struct Unit
}
};
-static_assert(sizeof(Unit) == 192, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Unit) == 208, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct TypeReference
{
@@ -832,9 +925,7 @@ struct TypeReferenceMap : QHash<int, TypeReference>
auto propEnd = obj->propertiesEnd();
for ( ; prop != propEnd; ++prop) {
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.
- TypeReference &r = this->add(prop->customTypeNameIndex, obj->location);
+ TypeReference &r = this->add(prop->customTypeNameIndex, prop->location);
r.errorWhenNotFound = true;
}
}
@@ -881,6 +972,8 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnitBase
QV4::Heap::String **runtimeStrings = nullptr; // Array
const Value* constants = nullptr;
QV4::Value *runtimeRegularExpressions = nullptr;
+ const Unit *data = nullptr;
+ QV4::Heap::InternalClass **runtimeClasses = nullptr;
};
Q_STATIC_ASSERT(std::is_standard_layout<CompilationUnitBase>::value);
@@ -915,8 +1008,6 @@ public:
return refCount.load();
}
- const Unit *data = nullptr;
-
// Called only when building QML, when we build the header for JS first and append QML data
QV4::CompiledData::Unit *createUnitData(QmlIR::Document *irDocument);
@@ -943,14 +1034,14 @@ public:
}
QV4::Lookup *runtimeLookups = nullptr;
- QV4::InternalClass **runtimeClasses = nullptr;
QVector<QV4::Function *> runtimeFunctions;
+ QVector<QV4::Heap::InternalClass *> runtimeBlocks;
mutable QQmlNullableValue<QUrl> m_url;
mutable QQmlNullableValue<QUrl> m_finalUrl;
// QML specific fields
QQmlPropertyCacheVector propertyCaches;
- QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
+ QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
@@ -962,7 +1053,7 @@ public:
// mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
// this is initialized on-demand by QQmlContextData
QHash<int, IdentifierHash> namedObjectsPerComponentCache;
- IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
+ inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
void finalizeCompositeType(QQmlEnginePrivate *qmlEngine);
@@ -970,7 +1061,7 @@ public:
int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses
int totalObjectCount = 0; // Number of objects explicitly instantiated
- QVector<QQmlScriptData *> dependentScripts;
+ QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
ResolvedTypeReferenceMap resolvedTypes;
bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const;
@@ -1010,6 +1101,8 @@ public:
bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
+ static QString localCacheFilePath(const QUrl &url);
+
protected:
void linkBackendToEngine(QV4::ExecutionEngine *engine);
#endif // V4_BOOTSTRAP
@@ -1019,6 +1112,8 @@ private:
QAtomicInt refCount = 1;
+ Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex);
+
public:
#if defined(V4_BOOTSTRAP)
bool saveToDisk(const QString &outputFileName, QString *errorString);
@@ -1046,17 +1141,24 @@ struct ResolvedTypeReference
// therefore cannot have a property cache installed when instantiated.
bool isFullyDynamicType;
- QQmlPropertyCache *propertyCache() const;
- QQmlPropertyCache *createPropertyCache(QQmlEngine *);
+ QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
+ QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
void doDynamicTypeCheck();
};
-#endif
+IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
+{
+ auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
+ if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end()))
+ return createNamedObjectsPerComponent(componentObjectIndex);
+ return *it;
}
+#endif // V4_BOOTSTRAP
-}
+} // CompiledData namespace
+} // QV4 namespace
Q_DECLARE_TYPEINFO(QV4::CompiledData::JSClassMember, Q_PRIMITIVE_TYPE);
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index c9e535c93f..f1afad4965 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -90,7 +90,11 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit)
const QString &qstr = strings.at(i);
QV4::CompiledData::String *s = reinterpret_cast<QV4::CompiledData::String *>(stringData);
+ s->refcount = -1;
s->size = qstr.length();
+ s->allocAndCapacityReservedFlag = 0;
+ s->offsetOn32Bit = sizeof(QV4::CompiledData::String);
+ s->offsetOn64Bit = sizeof(QV4::CompiledData::String);
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
memcpy(s + 1, qstr.constData(), qstr.length()*sizeof(ushort));
#else
@@ -98,6 +102,7 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit)
for (int i = 0; i < qstr.length(); ++i)
uc[i] = qToLittleEndian<ushort>(qstr.at(i).unicode());
#endif
+ reinterpret_cast<ushort *>(s + 1)[s->size] = 0;
stringData += QV4::CompiledData::String::calculateSize(qstr);
}
@@ -183,7 +188,7 @@ QV4::ReturnedValue QV4::Compiler::JSUnitGenerator::constant(int idx)
return constants.at(idx);
}
-int QV4::Compiler::JSUnitGenerator::registerJSClass(const QVector<MemberInfo> &members)
+int QV4::Compiler::JSUnitGenerator::registerJSClass(const QStringList &members)
{
// ### re-use existing class definitions.
@@ -197,31 +202,15 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(const QVector<MemberInfo> &m
jsClass->nMembers = members.size();
CompiledData::JSClassMember *member = reinterpret_cast<CompiledData::JSClassMember*>(jsClass + 1);
- for (const MemberInfo &memberInfo : members) {
- member->nameOffset = registerString(memberInfo.name);
- member->isAccessor = memberInfo.isAccessor;
+ for (const auto &name : members) {
+ member->nameOffset = registerString(name);
+ member->isAccessor = false;
++member;
}
return jsClassOffsets.size() - 1;
}
-int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, CompiledData::JSClassMember *members)
-{
- const int size = CompiledData::JSClass::calculateSize(count);
- jsClassOffsets.append(jsClassData.size());
- const int oldSize = jsClassData.size();
- jsClassData.resize(jsClassData.size() + size);
- memset(jsClassData.data() + oldSize, 0, size);
-
- CompiledData::JSClass *jsClass = reinterpret_cast<CompiledData::JSClass*>(jsClassData.data() + oldSize);
- jsClass->nMembers = count;
- CompiledData::JSClassMember *jsClassMembers = reinterpret_cast<CompiledData::JSClassMember*>(jsClass + 1);
- memcpy(jsClassMembers, members, sizeof(CompiledData::JSClassMember)*count);
-
- return jsClassOffsets.size() - 1;
-}
-
QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorOption option)
{
registerString(module->fileName);
@@ -233,28 +222,46 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
for (int i = 0; i < f->locals.size(); ++i)
registerString(f->locals.at(i));
}
+ for (Context *c : qAsConst(module->blocks)) {
+ for (int i = 0; i < c->locals.size(); ++i)
+ registerString(c->locals.at(i));
+ }
- Q_ALLOCA_VAR(quint32_le, functionOffsets, module->functions.size() * sizeof(quint32_le));
+ Q_ALLOCA_VAR(quint32_le, blockClassAndFunctionOffsets, (module->functions.size() + module->classes.size() + module->blocks.size()) * sizeof(quint32_le));
uint jsClassDataOffset = 0;
char *dataPtr;
CompiledData::Unit *unit;
{
- QV4::CompiledData::Unit tempHeader = generateHeader(option, functionOffsets, &jsClassDataOffset);
+ QV4::CompiledData::Unit tempHeader = generateHeader(option, blockClassAndFunctionOffsets, &jsClassDataOffset);
dataPtr = reinterpret_cast<char *>(malloc(tempHeader.unitSize));
memset(dataPtr, 0, tempHeader.unitSize);
memcpy(&unit, &dataPtr, sizeof(CompiledData::Unit*));
memcpy(unit, &tempHeader, sizeof(tempHeader));
}
- memcpy(dataPtr + unit->offsetToFunctionTable, functionOffsets, unit->functionTableSize * sizeof(quint32_le));
+ memcpy(dataPtr + unit->offsetToFunctionTable, blockClassAndFunctionOffsets, unit->functionTableSize * sizeof(quint32_le));
+ memcpy(dataPtr + unit->offsetToClassTable, blockClassAndFunctionOffsets + unit->functionTableSize, unit->classTableSize * sizeof(quint32_le));
+ memcpy(dataPtr + unit->offsetToBlockTable, blockClassAndFunctionOffsets + unit->functionTableSize + unit->classTableSize, unit->blockTableSize * sizeof(quint32_le));
for (int i = 0; i < module->functions.size(); ++i) {
Context *function = module->functions.at(i);
if (function == module->rootContext)
unit->indexOfRootFunction = i;
- writeFunction(dataPtr + functionOffsets[i], function);
+ writeFunction(dataPtr + blockClassAndFunctionOffsets[i], function);
+ }
+
+ for (int i = 0; i < module->classes.size(); ++i) {
+ const Class &c = module->classes.at(i);
+
+ writeClass(dataPtr + blockClassAndFunctionOffsets[i + module->functions.size()], c);
+ }
+
+ for (int i = 0; i < module->blocks.size(); ++i) {
+ Context *block = module->blocks.at(i);
+
+ writeBlock(dataPtr + blockClassAndFunctionOffsets[i + module->classes.size() + module->functions.size()], block);
}
CompiledData::Lookup *lookupsToWrite = reinterpret_cast<CompiledData::Lookup*>(dataPtr + unit->offsetToLookupTable);
@@ -300,17 +307,16 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
function->nameIndex = getStringId(irFunction->name);
function->flags = 0;
- if (irFunction->hasDirectEval)
- function->flags |= CompiledData::Function::HasDirectEval;
- if (irFunction->usesArgumentsObject)
- function->flags |= CompiledData::Function::UsesArgumentsObject;
if (irFunction->isStrict)
function->flags |= CompiledData::Function::IsStrict;
- if (irFunction->hasTry || irFunction->hasWith)
- function->flags |= CompiledData::Function::HasCatchOrWith;
+ if (irFunction->isArrowFunction)
+ function->flags |= CompiledData::Function::IsArrowFunction;
+ if (irFunction->isGenerator)
+ function->flags |= CompiledData::Function::IsGenerator;
function->nestedFunctionIndex =
irFunction->returnsClosure ? quint32(module->functions.indexOf(irFunction->nestedContexts.first()))
: std::numeric_limits<uint32_t>::max();
+ function->length = irFunction->formals ? irFunction->formals->length() : 0;
function->nFormals = irFunction->arguments.size();
function->formalsOffset = currentOffset;
currentOffset += function->nFormals * sizeof(quint32);
@@ -324,7 +330,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
currentOffset += function->nLineNumbers * sizeof(CompiledData::CodeOffsetToLine);
- function->nRegisters = irFunction->registerCount;
+ function->nRegisters = irFunction->registerCountInFunction;
function->nDependingIdObjects = 0;
function->nDependingContextProperties = 0;
@@ -390,7 +396,84 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
memcpy(f + function->codeOffset, irFunction->code.constData(), irFunction->code.size());
}
-QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, quint32_le *functionOffsets, uint *jsClassDataOffset)
+static_assert(int(QV4::Compiler::Class::Method::Regular) == int(QV4::CompiledData::Method::Regular), "Incompatible layout");
+static_assert(int(QV4::Compiler::Class::Method::Getter) == int(QV4::CompiledData::Method::Getter), "Incompatible layout");
+static_assert(int(QV4::Compiler::Class::Method::Setter) == int(QV4::CompiledData::Method::Setter), "Incompatible layout");
+
+void QV4::Compiler::JSUnitGenerator::writeClass(char *b, const QV4::Compiler::Class &c)
+{
+ QV4::CompiledData::Class *cls = reinterpret_cast<QV4::CompiledData::Class *>(b);
+
+ quint32 currentOffset = sizeof(QV4::CompiledData::Class);
+
+ QVector<Class::Method> allMethods = c.staticMethods;
+ allMethods += c.methods;
+
+ cls->constructorFunction = c.constructorIndex;
+ cls->nameIndex = c.nameIndex;
+ cls->nMethods = c.methods.size();
+ cls->nStaticMethods = c.staticMethods.size();
+ cls->methodTableOffset = currentOffset;
+ CompiledData::Method *method = reinterpret_cast<CompiledData::Method *>(b + currentOffset);
+
+ // write methods
+ for (int i = 0; i < allMethods.size(); ++i) {
+ method->name = allMethods.at(i).nameIndex;
+ method->type = allMethods.at(i).type;
+ method->function = allMethods.at(i).functionIndex;
+ ++method;
+ }
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
+ if (showCode) {
+ qDebug() << "=== Class " << stringForIndex(cls->nameIndex) << "static methods" << cls->nStaticMethods << "methods" << cls->nMethods;
+ qDebug() << " constructor:" << cls->constructorFunction;
+ const char *staticString = ": static ";
+ for (uint i = 0; i < cls->nStaticMethods + cls->nMethods; ++i) {
+ if (i == cls->nStaticMethods)
+ staticString = ": ";
+ const char *type;
+ switch (cls->methodTable()[i].type) {
+ case CompiledData::Method::Getter:
+ type = "get "; break;
+ case CompiledData::Method::Setter:
+ type = "set "; break;
+ default:
+ type = "";
+
+ }
+ qDebug() << " " << i << staticString << type << stringForIndex(cls->methodTable()[i].name) << cls->methodTable()[i].function;
+ }
+ qDebug();
+ }
+}
+
+void QV4::Compiler::JSUnitGenerator::writeBlock(char *b, QV4::Compiler::Context *irBlock) const
+{
+ QV4::CompiledData::Block *block = reinterpret_cast<QV4::CompiledData::Block *>(b);
+
+ quint32 currentOffset = sizeof(QV4::CompiledData::Block);
+ currentOffset = (currentOffset + 7) & ~quint32(0x7);
+
+ block->nLocals = irBlock->locals.size();
+ block->localsOffset = currentOffset;
+ currentOffset += block->nLocals * sizeof(quint32);
+
+ // write locals
+ quint32_le *locals = (quint32_le *)(b + block->localsOffset);
+ for (int i = 0; i < irBlock->locals.size(); ++i)
+ locals[i] = getStringId(irBlock->locals.at(i));
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
+ if (showCode) {
+ qDebug() << "=== Variables for block" << irBlock->blockIndex;
+ for (int i = 0; i < irBlock->locals.size(); ++i)
+ qDebug() << " " << i << ":" << locals[i];
+ qDebug();
+ }
+}
+
+QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, quint32_le *blockAndFunctionOffsets, uint *jsClassDataOffset)
{
CompiledData::Unit unit;
memset(&unit, 0, sizeof(unit));
@@ -409,6 +492,14 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
unit.offsetToFunctionTable = nextOffset;
nextOffset += unit.functionTableSize * sizeof(uint);
+ unit.classTableSize = module->classes.size();
+ unit.offsetToClassTable = nextOffset;
+ nextOffset += unit.classTableSize * sizeof(uint);
+
+ unit.blockTableSize = module->blocks.size();
+ unit.offsetToBlockTable = nextOffset;
+ nextOffset += unit.blockTableSize * sizeof(uint);
+
unit.lookupTableSize = lookups.count();
unit.offsetToLookupTable = nextOffset;
nextOffset += unit.lookupTableSize * sizeof(CompiledData::Lookup);
@@ -435,13 +526,29 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
for (int i = 0; i < module->functions.size(); ++i) {
Context *f = module->functions.at(i);
- functionOffsets[i] = nextOffset;
+ blockAndFunctionOffsets[i] = nextOffset;
const int qmlIdDepsCount = f->idObjectDependencies.count();
const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count();
nextOffset += QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->lineNumberMapping.size(), f->nestedContexts.size(),
qmlIdDepsCount, qmlPropertyDepsCount, f->code.size());
}
+ blockAndFunctionOffsets += module->functions.size();
+
+ for (int i = 0; i < module->classes.size(); ++i) {
+ const Class &c = module->classes.at(i);
+ blockAndFunctionOffsets[i] = nextOffset;
+
+ nextOffset += QV4::CompiledData::Class::calculateSize(c.staticMethods.size(), c.methods.size());
+ }
+ blockAndFunctionOffsets += module->classes.size();
+
+ for (int i = 0; i < module->blocks.size(); ++i) {
+ Context *c = module->blocks.at(i);
+ blockAndFunctionOffsets[i] = nextOffset;
+
+ nextOffset += QV4::CompiledData::Block::calculateSize(c->locals.size());
+ }
if (option == GenerateWithStringTable) {
unit.stringTableSize = stringTable.stringCount();
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 360af6540f..944c44b1ff 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -72,6 +72,8 @@ struct JSClassMember;
namespace Compiler {
+struct Class;
+
struct Q_QML_PRIVATE_EXPORT StringTableGenerator {
StringTableGenerator();
@@ -116,8 +118,7 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
int registerConstant(ReturnedValue v);
ReturnedValue constant(int idx);
- int registerJSClass(const QVector<MemberInfo> &members);
- int registerJSClass(int count, CompiledData::JSClassMember *members);
+ int registerJSClass(const QStringList &members);
enum GeneratorOption {
GenerateWithStringTable,
@@ -125,8 +126,9 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
};
QV4::CompiledData::Unit *generateUnit(GeneratorOption option = GenerateWithStringTable);
- // Returns bytes written
void writeFunction(char *f, Context *irFunction) const;
+ void writeClass(char *f, const Class &c);
+ void writeBlock(char *f, Context *irBlock) const;
StringTableGenerator stringTable;
QString codeGeneratorName;
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 0a9d3d8efe..9dfe3be7e0 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -39,6 +39,7 @@
#include "qv4compilercontext_p.h"
#include "qv4compilercontrolflow_p.h"
+#include "qv4bytecodegenerator_p.h"
QT_USE_NAMESPACE
using namespace QV4;
@@ -47,11 +48,11 @@ using namespace QQmlJS::AST;
QT_BEGIN_NAMESPACE
-Context *Module::newContext(Node *node, Context *parent, CompilationMode compilationMode)
+Context *Module::newContext(Node *node, Context *parent, ContextType contextType)
{
Q_ASSERT(!contextMap.contains(node));
- Context *c = new Context(parent, compilationMode);
+ Context *c = new Context(parent, contextType);
if (node) {
SourceLocation loc = node->firstSourceLocation();
c->line = loc.startLine;
@@ -70,15 +71,252 @@ Context *Module::newContext(Node *node, Context *parent, CompilationMode compila
return c;
}
-bool Context::forceLookupByName()
+bool Context::addLocalVar(const QString &name, Context::MemberType type, VariableScope scope, FunctionExpression *function)
{
- ControlFlow *flow = controlFlow;
- while (flow) {
- if (flow->needsLookupByName)
+ // ### can this happen?
+ if (name.isEmpty())
+ return true;
+
+ if (type != FunctionDefinition) {
+ if (formals && formals->containsName(name))
+ return (scope == VariableScope::Var);
+ }
+ if (!isCatchBlock || name != caughtVariable) {
+ MemberMap::iterator it = members.find(name);
+ if (it != members.end()) {
+ if (scope != VariableScope::Var || (*it).scope != VariableScope::Var)
+ return false;
+ if ((*it).type <= type) {
+ (*it).type = type;
+ (*it).function = function;
+ }
return true;
- flow = flow->parent;
+ }
+ }
+
+ // hoist var declarations to the function level
+ if (contextType == ContextType::Block && (scope == VariableScope::Var && type != MemberType::FunctionDefinition))
+ return parent->addLocalVar(name, type, scope, function);
+
+ Member m;
+ m.type = type;
+ m.function = function;
+ m.scope = scope;
+ members.insert(name, m);
+ return true;
+}
+
+Context::ResolvedName Context::resolveName(const QString &name)
+{
+ int scope = 0;
+ Context *c = this;
+
+ ResolvedName result;
+
+ while (c) {
+ if (c->isWithBlock)
+ return result;
+
+ Context::Member m = c->findMember(name);
+ if (!c->parent && m.index < 0)
+ break;
+
+ if (m.type != Context::UndefinedMember) {
+ result.type = m.canEscape ? ResolvedName::Local : ResolvedName::Stack;
+ result.scope = scope;
+ result.index = m.index;
+ result.isConst = (m.scope == VariableScope::Const);
+ if (c->isStrict && (name == QLatin1String("arguments") || name == QLatin1String("eval")))
+ result.isArgOrEval = true;
+ return result;
+ }
+ const int argIdx = c->findArgument(name);
+ if (argIdx != -1) {
+ if (c->argumentsCanEscape) {
+ result.index = argIdx + c->locals.size();
+ result.scope = scope;
+ result.type = ResolvedName::Local;
+ result.isConst = false;
+ return result;
+ } else {
+ result.index = argIdx + sizeof(CallData)/sizeof(Value) - 1;
+ result.scope = 0;
+ result.type = ResolvedName::Stack;
+ result.isConst = false;
+ return result;
+ }
+ }
+ if (c->hasDirectEval) {
+ Q_ASSERT(!c->isStrict && c->contextType != ContextType::Block);
+ return result;
+ }
+
+ if (c->requiresExecutionContext)
+ ++scope;
+ c = c->parent;
+ }
+
+ // ### can we relax the restrictions here?
+ if (contextType == ContextType::Eval || c->contextType == ContextType::Binding)
+ return result;
+
+ result.type = ResolvedName::Global;
+ return result;
+}
+
+void Context::emitBlockHeader(Codegen *codegen)
+{
+ using Instruction = Moth::Instruction;
+ Moth::BytecodeGenerator *bytecodeGenerator = codegen->generator();
+
+ setupFunctionIndices(bytecodeGenerator);
+
+ if (requiresExecutionContext) {
+ if (blockIndex < 0) {
+ codegen->module()->blocks.append(this);
+ blockIndex = codegen->module()->blocks.count() - 1;
+ }
+
+ if (contextType == ContextType::Global) {
+ Instruction::PushScriptContext scriptContext;
+ scriptContext.index = blockIndex;
+ bytecodeGenerator->addInstruction(scriptContext);
+ } else if (contextType == ContextType::Block || (contextType == ContextType::Eval && !isStrict)) {
+ if (isCatchBlock) {
+ Instruction::PushCatchContext catchContext;
+ catchContext.index = blockIndex;
+ catchContext.name = codegen->registerString(caughtVariable);
+ bytecodeGenerator->addInstruction(catchContext);
+ } else {
+ Instruction::PushBlockContext blockContext;
+ blockContext.index = blockIndex;
+ bytecodeGenerator->addInstruction(blockContext);
+ }
+ } else {
+ Instruction::CreateCallContext createContext;
+ bytecodeGenerator->addInstruction(createContext);
+ }
+ }
+
+ if (usesThis) {
+ Q_ASSERT(!isStrict);
+ // make sure we convert this to an object
+ Instruction::ConvertThisToObject convert;
+ bytecodeGenerator->addInstruction(convert);
+ }
+
+ if (contextType == ContextType::Global || (contextType == ContextType::Eval && !isStrict)) {
+ // variables in global code are properties of the global context object, not locals as with other functions.
+ for (Context::MemberMap::const_iterator it = members.constBegin(), cend = members.constEnd(); it != cend; ++it) {
+ if (it->isLexicallyScoped())
+ continue;
+ const QString &local = it.key();
+
+ Instruction::DeclareVar declareVar;
+ declareVar.isDeletable = (contextType == ContextType::Eval);
+ declareVar.varName = codegen->registerString(local);
+ bytecodeGenerator->addInstruction(declareVar);
+ }
+ }
+
+ if (contextType == ContextType::Function || contextType == ContextType::Binding) {
+ for (Context::MemberMap::iterator it = members.begin(), end = members.end(); it != end; ++it) {
+ if (it->canEscape && it->type == Context::ThisFunctionName) {
+ // move the function from the stack to the call context
+ Instruction::LoadReg load;
+ load.reg = CallData::Function;
+ bytecodeGenerator->addInstruction(load);
+ Instruction::StoreLocal store;
+ store.index = it->index;
+ bytecodeGenerator->addInstruction(store);
+ }
+ }
+ }
+
+ if (usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ Q_ASSERT(contextType != ContextType::Block);
+ if (isStrict || (formals && !formals->isSimpleParameterList())) {
+ Instruction::CreateUnmappedArgumentsObject setup;
+ bytecodeGenerator->addInstruction(setup);
+ } else {
+ Instruction::CreateMappedArgumentsObject setup;
+ bytecodeGenerator->addInstruction(setup);
+ }
+ codegen->referenceForName(QStringLiteral("arguments"), false).storeConsumeAccumulator();
+ }
+
+ for (const Context::Member &member : qAsConst(members)) {
+ if (member.function) {
+ const int function = codegen->defineFunction(member.function->name.toString(), member.function, member.function->formals, member.function->body);
+ codegen->loadClosure(function);
+ Codegen::Reference r = codegen->referenceForName(member.function->name.toString(), true);
+ r.storeConsumeAccumulator();
+ }
+ }
+}
+
+void Context::emitBlockFooter(Codegen *codegen)
+{
+ using Instruction = Moth::Instruction;
+ Moth::BytecodeGenerator *bytecodeGenerator = codegen->generator();
+
+ if (!requiresExecutionContext)
+ return;
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // the loads below are empty structs.
+ if (contextType == ContextType::Global)
+ bytecodeGenerator->addInstruction(Instruction::PopScriptContext());
+ else
+ bytecodeGenerator->addInstruction(Instruction::PopContext());
+QT_WARNING_POP
+}
+
+void Context::setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
+{
+ if (registerOffset != -1) {
+ // already computed, check for consistency
+ Q_ASSERT(registerOffset == bytecodeGenerator->currentRegister());
+ bytecodeGenerator->newRegisterArray(nRegisters);
+ return;
+ }
+ Q_ASSERT(locals.size() == 0);
+ Q_ASSERT(nRegisters == 0);
+ registerOffset = bytecodeGenerator->currentRegister();
+
+ switch (contextType) {
+ case ContextType::Block:
+ case ContextType::Function:
+ case ContextType::Binding: {
+ for (Context::MemberMap::iterator it = members.begin(), end = members.end(); it != end; ++it) {
+ const QString &local = it.key();
+ if (it->canEscape) {
+ it->index = locals.size();
+ locals.append(local);
+ } else {
+ if (it->type == Context::ThisFunctionName)
+ it->index = CallData::Function;
+ else
+ it->index = bytecodeGenerator->newRegister();
+ }
+ }
+ break;
+ }
+ case ContextType::Global:
+ case ContextType::Eval:
+ for (Context::MemberMap::iterator it = members.begin(), end = members.end(); it != end; ++it) {
+ if (!it->isLexicallyScoped() && (contextType == ContextType::Global || !isStrict))
+ continue;
+ if (it->canEscape) {
+ it->index = locals.size();
+ locals.append(it.key());
+ } else {
+ it->index = bytecodeGenerator->newRegister();
+ }
+ }
+ break;
}
- return false;
+ nRegisters = bytecodeGenerator->currentRegister() - registerOffset;
}
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 455a76c729..52c3fc5b05 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -66,18 +66,37 @@ namespace Compiler {
struct ControlFlow;
-enum CompilationMode {
- GlobalCode,
- EvalCode,
- FunctionCode,
- QmlBinding // This is almost the same as EvalCode, except:
+enum class ContextType {
+ Global,
+ Function,
+ Eval,
+ Binding, // This is almost the same as Eval, except:
// * function declarations are moved to the return address when encountered
// * return statements are allowed everywhere (like in FunctionCode)
// * variable declarations are treated as true locals (like in FunctionCode)
+ Block
};
struct Context;
+struct Class {
+ struct Method {
+ enum Type {
+ Regular,
+ Getter,
+ Setter
+ };
+ uint nameIndex;
+ Type type;
+ uint functionIndex;
+ };
+
+ uint nameIndex;
+ uint constructorIndex = UINT_MAX;
+ QVector<Method> staticMethods;
+ QVector<Method> methods;
+};
+
struct Module {
Module(bool debugMode)
: debugMode(debugMode)
@@ -86,10 +105,12 @@ struct Module {
qDeleteAll(contextMap);
}
- Context *newContext(QQmlJS::AST::Node *node, Context *parent, CompilationMode compilationMode);
+ Context *newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode);
QHash<QQmlJS::AST::Node *, Context *> contextMap;
QList<Context *> functions;
+ QList<Context *> blocks;
+ QVector<Class> classes;
Context *rootContext;
QString fileName;
QString finalUrl;
@@ -104,8 +125,9 @@ struct Context {
QString name;
int line = 0;
int column = 0;
- int registerCount = 0;
+ int registerCountInFunction = 0;
int functionIndex = -1;
+ int blockIndex = -1;
enum MemberType {
UndefinedMember,
@@ -118,11 +140,11 @@ struct Context {
struct Member {
MemberType type = UndefinedMember;
int index = -1;
- QQmlJS::AST::VariableDeclaration::VariableScope scope = QQmlJS::AST::VariableDeclaration::FunctionScope;
+ QQmlJS::AST::VariableScope scope = QQmlJS::AST::VariableScope::Var;
mutable bool canEscape = false;
QQmlJS::AST::FunctionExpression *function = nullptr;
- bool isLexicallyScoped() const { return this->scope != QQmlJS::AST::VariableDeclaration::FunctionScope; }
+ bool isLexicallyScoped() const { return this->scope != QQmlJS::AST::VariableScope::Var; }
};
typedef QMap<QString, Member> MemberMap;
@@ -137,15 +159,22 @@ struct Context {
QByteArray code;
QVector<CompiledData::CodeOffsetToLine> lineNumberMapping;
- int maxNumberOfArguments = 0;
+ int nRegisters = 0;
+ int registerOffset = -1;
bool hasDirectEval = false;
+ bool allVarsEscape = false;
bool hasNestedFunctions = false;
bool isStrict = false;
+ bool isArrowFunction = false;
+ bool isGenerator = false;
bool usesThis = false;
bool hasTry = false;
- bool hasWith = false;
bool returnsClosure = false;
mutable bool argumentsCanEscape = false;
+ bool requiresExecutionContext = false;
+ bool isWithBlock = false;
+ bool isCatchBlock = false;
+ QString caughtVariable;
enum UsesArgumentsObject {
ArgumentsObjectUnknown,
@@ -155,7 +184,7 @@ struct Context {
UsesArgumentsObject usesArgumentsObject = ArgumentsObjectUnknown;
- CompilationMode compilationMode;
+ ContextType contextType;
template <typename T>
class SmallSet: public QVarLengthArray<T, 8>
@@ -204,24 +233,14 @@ struct Context {
PropertyDependencyMap contextObjectPropertyDependencies;
PropertyDependencyMap scopeObjectPropertyDependencies;
- Context(Context *parent, CompilationMode mode)
+ Context(Context *parent, ContextType type)
: parent(parent)
- , compilationMode(mode)
+ , contextType(type)
{
if (parent && parent->isStrict)
isStrict = true;
}
- bool forceLookupByName();
-
-
- bool canUseSimpleCall() const {
- return nestedContexts.isEmpty() &&
- locals.isEmpty() &&
- !hasTry && !hasWith &&
- (usesArgumentsObject == ArgumentsObjectNotUsed || isStrict) && !hasDirectEval;
- }
-
int findArgument(const QString &name)
{
// search backwards to handle duplicate argument names correctly
@@ -253,37 +272,37 @@ struct Context {
return true;
}
+ bool requiresImplicitReturnValue() const {
+ return contextType == ContextType::Binding ||
+ contextType == ContextType::Eval ||
+ contextType == ContextType::Global;
+ }
+
void addUsedVariable(const QString &name) {
usedVariables.insert(name);
}
- bool addLocalVar(const QString &name, MemberType type, QQmlJS::AST::VariableDeclaration::VariableScope scope, QQmlJS::AST::FunctionExpression *function = nullptr)
- {
- if (name.isEmpty())
- return true;
+ bool addLocalVar(const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope, QQmlJS::AST::FunctionExpression *function = nullptr);
+
+ struct ResolvedName {
+ enum Type {
+ Unresolved,
+ Global,
+ Local,
+ Stack
+ };
+ Type type = Unresolved;
+ bool isArgOrEval = false;
+ bool isConst = false;
+ int scope = -1;
+ int index = -1;
+ bool isValid() const { return type != Unresolved; }
+ };
+ ResolvedName resolveName(const QString &name);
+ void emitBlockHeader(Compiler::Codegen *codegen);
+ void emitBlockFooter(Compiler::Codegen *codegen);
- if (type != FunctionDefinition) {
- for (QQmlJS::AST::FormalParameterList *it = formals; it; it = it->next)
- if (it->name == name)
- return (scope == QQmlJS::AST::VariableDeclaration::FunctionScope);
- }
- MemberMap::iterator it = members.find(name);
- if (it != members.end()) {
- if (scope != QQmlJS::AST::VariableDeclaration::FunctionScope || (*it).scope != QQmlJS::AST::VariableDeclaration::FunctionScope)
- return false;
- if ((*it).type <= type) {
- (*it).type = type;
- (*it).function = function;
- }
- return true;
- }
- Member m;
- m.type = type;
- m.function = function;
- m.scope = scope;
- members.insert(name, m);
- return true;
- }
+ void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator);
};
diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h
index 9bda20905a..1ef290ea56 100644
--- a/src/qml/compiler/qv4compilercontrolflow_p.h
+++ b/src/qml/compiler/qv4compilercontrolflow_p.h
@@ -53,6 +53,7 @@
#include <private/qv4global_p.h>
#include <private/qv4codegen_p.h>
#include <private/qqmljsast_p.h>
+#include <private/qv4bytecodegenerator_p.h>
QT_BEGIN_NAMESPACE
@@ -68,117 +69,84 @@ struct ControlFlow {
enum Type {
Loop,
With,
+ Block,
Finally,
Catch
};
- enum HandlerType {
- Invalid,
+ enum UnwindType {
Break,
Continue,
- Return,
- Throw
+ Return
};
- struct Handler {
- HandlerType type;
- QString label;
+ struct UnwindTarget {
BytecodeGenerator::Label linkLabel;
- int tempIndex;
- int value;
+ int unwindLevel;
};
Codegen *cg;
ControlFlow *parent;
Type type;
- bool needsLookupByName = false;
ControlFlow(Codegen *cg, Type type)
- : cg(cg), parent(cg->_context->controlFlow), type(type)
+ : cg(cg), parent(cg->controlFlow), type(type)
{
- cg->_context->controlFlow = this;
+ cg->controlFlow = this;
}
virtual ~ControlFlow() {
- cg->_context->controlFlow = parent;
+ cg->controlFlow = parent;
}
- void emitReturnStatement() const {
- if (cg->_returnAddress >= 0) {
- Instruction::LoadReg load;
- load.reg = Moth::StackSlot::createRegister(cg->_returnAddress);
- generator()->addInstruction(load);
+ UnwindTarget unwindTarget(UnwindType type, const QString &label = QString())
+ {
+ Q_ASSERT(type == Break || type == Continue || type == Return);
+ ControlFlow *flow = this;
+ int level = 0;
+ while (flow) {
+ BytecodeGenerator::Label l = flow->getUnwindTarget(type, label);
+ if (l.isValid())
+ return UnwindTarget{l, level};
+ if (flow->requiresUnwind())
+ ++level;
+ flow = flow->parent;
}
- Instruction::Ret ret;
- cg->bytecodeGenerator->addInstruction(ret);
+ if (type == Return)
+ return UnwindTarget{ cg->returnLabel(), level };
+ return UnwindTarget();
}
- void jumpToHandler(const Handler &h) {
- if (h.linkLabel.isReturn()) {
- emitReturnStatement();
- } else {
- if (h.tempIndex >= 0)
- Reference::storeConstOnStack(cg, QV4::Encode(h.value), h.tempIndex);
- cg->bytecodeGenerator->jump().link(h.linkLabel);
- }
- }
+ virtual QString label() const { return QString(); }
- bool returnRequiresUnwind() const {
- const ControlFlow *f = this;
- while (f) {
- if (f->type == Finally)
+ bool hasLoop() const {
+ const ControlFlow *flow = this;
+ while (flow) {
+ if (flow->type == Loop)
return true;
- f = f->parent;
+ flow = flow->parent;
}
return false;
}
- virtual QString label() const { return QString(); }
-
- bool isSimple() const {
- return type == Loop;
+protected:
+ virtual BytecodeGenerator::Label getUnwindTarget(UnwindType, const QString & = QString()) {
+ return BytecodeGenerator::Label();
}
-
- Handler getParentHandler(HandlerType type, const QString &label = QString()) {
- if (parent)
- return parent->getHandler(type, label);
- switch (type) {
- case Break:
- case Continue:
- return { Invalid, QString(), {}, -1, 0 };
- case Return:
- case Throw:
- return { type, QString(), BytecodeGenerator::Label::returnLabel(), -1, 0 };
- case Invalid:
- break;
- }
- Q_ASSERT(false);
- Q_UNREACHABLE();
+ virtual bool requiresUnwind() {
+ return false;
}
- virtual Handler getHandler(HandlerType type, const QString &label = QString()) = 0;
-
- BytecodeGenerator::ExceptionHandler *parentExceptionHandler() {
- return parent ? parent->exceptionHandler() : nullptr;
+public:
+ BytecodeGenerator::ExceptionHandler *parentUnwindHandler() {
+ return parent ? parent->unwindHandler() : nullptr;
}
- virtual BytecodeGenerator::ExceptionHandler *exceptionHandler() {
- return parentExceptionHandler();
+ virtual BytecodeGenerator::ExceptionHandler *unwindHandler() {
+ return parentUnwindHandler();
}
- virtual void handleThrow(const Reference &expr) {
- Reference e = expr;
- Handler h = getHandler(ControlFlow::Throw);
- if (h.tempIndex >= 0) {
- e = e.storeOnStack();
- Reference::storeConstOnStack(cg, QV4::Encode(h.value), h.tempIndex);
- }
- e.loadInAccumulator();
- Instruction::ThrowException instr;
- generator()->addInstruction(instr);
- }
-
protected:
QString loopLabel() const {
QString label;
@@ -193,136 +161,145 @@ protected:
}
};
-struct ControlFlowLoop : public ControlFlow
+struct ControlFlowUnwind : public ControlFlow
{
- QString loopLabel;
- BytecodeGenerator::Label *breakLabel = nullptr;
- BytecodeGenerator::Label *continueLabel = nullptr;
+ BytecodeGenerator::ExceptionHandler unwindLabel;
- ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel = nullptr)
- : ControlFlow(cg, Loop), loopLabel(ControlFlow::loopLabel()), breakLabel(breakLabel), continueLabel(continueLabel)
+ ControlFlowUnwind(Codegen *cg, Type type)
+ : ControlFlow(cg, type)
{
}
- virtual QString label() const { return loopLabel; }
+ void setupUnwindHandler()
+ {
+ unwindLabel = generator()->newExceptionHandler();
+ }
- virtual Handler getHandler(HandlerType type, const QString &label = QString()) {
- switch (type) {
- case Break:
- if (breakLabel && (label.isEmpty() || label == loopLabel))
- return { type, loopLabel, *breakLabel, -1, 0 };
- break;
- case Continue:
- if (continueLabel && (label.isEmpty() || label == loopLabel))
- return { type, loopLabel, *continueLabel, -1, 0 };
- break;
- case Return:
- case Throw:
- break;
- case Invalid:
- Q_ASSERT(false);
- Q_UNREACHABLE();
- }
- return getParentHandler(type, label);
+ void emitUnwindHandler()
+ {
+ Q_ASSERT(requiresUnwind());
+
+ Instruction::UnwindDispatch dispatch;
+ generator()->addInstruction(dispatch);
}
+ virtual BytecodeGenerator::ExceptionHandler *unwindHandler() override {
+ return unwindLabel.isValid() ? &unwindLabel : parentUnwindHandler();
+ }
};
-struct ControlFlowUnwind : public ControlFlow
+struct ControlFlowLoop : public ControlFlowUnwind
{
- BytecodeGenerator::ExceptionHandler unwindLabel;
- int controlFlowTemp;
- QVector<Handler> handlers;
+ QString loopLabel;
+ BytecodeGenerator::Label *breakLabel = nullptr;
+ BytecodeGenerator::Label *continueLabel = nullptr;
+ bool _requiresUnwind;
- ControlFlowUnwind(Codegen *cg, Type type)
- : ControlFlow(cg, type), unwindLabel(generator()->newExceptionHandler())
+ ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel = nullptr, bool requiresUnwind = false)
+ : ControlFlowUnwind(cg, Loop), loopLabel(ControlFlow::loopLabel()), breakLabel(breakLabel), continueLabel(continueLabel), _requiresUnwind(requiresUnwind)
{
- Q_ASSERT(type != Loop);
- controlFlowTemp = static_cast<int>(generator()->newRegister());
- Reference::storeConstOnStack(cg, QV4::Encode::undefined(), controlFlowTemp);
- // we'll need at least a handler for throw
- getHandler(Throw);
+ if (_requiresUnwind) {
+ setupUnwindHandler();
+ generator()->setUnwindHandler(&unwindLabel);
+ }
}
- void emitUnwindHandler()
- {
- Q_ASSERT(!isSimple());
-
- Reference temp = Reference::fromStackSlot(cg, controlFlowTemp);
- for (const auto &h : qAsConst(handlers)) {
- Handler parentHandler = getParentHandler(h.type, h.label);
-
- if (h.type == Throw || parentHandler.tempIndex >= 0) {
- BytecodeGenerator::Label skip = generator()->newLabel();
- generator()->jumpStrictNotEqualStackSlotInt(temp.stackSlot(), h.value).link(skip);
- if (h.type == Throw)
- emitForThrowHandling();
- jumpToHandler(parentHandler);
- skip.link();
- } else {
- if (parentHandler.linkLabel.isReturn()) {
- BytecodeGenerator::Label skip = generator()->newLabel();
- generator()->jumpStrictNotEqualStackSlotInt(temp.stackSlot(), h.value).link(skip);
- emitReturnStatement();
- skip.link();
- } else {
- generator()->jumpStrictEqualStackSlotInt(temp.stackSlot(), h.value).link(parentHandler.linkLabel);
- }
- }
+ ~ControlFlowLoop() {
+ if (_requiresUnwind) {
+ unwindLabel.link();
+ generator()->setUnwindHandler(parentUnwindHandler());
+ emitUnwindHandler();
}
}
- virtual Handler getHandler(HandlerType type, const QString &label = QString()) {
- for (const auto &h : qAsConst(handlers)) {
- if (h.type == type && h.label == label)
- return h;
- }
- Handler h = {
- type,
- label,
- unwindLabel,
- controlFlowTemp,
- handlers.size()
- };
- handlers.append(h);
- return h;
+ bool requiresUnwind() override {
+ return _requiresUnwind;
}
- virtual BytecodeGenerator::ExceptionHandler *exceptionHandler() {
- return &unwindLabel;
+ BytecodeGenerator::Label getUnwindTarget(UnwindType type, const QString &label) override {
+ switch (type) {
+ case Break:
+ if (breakLabel && (label.isEmpty() || label == loopLabel))
+ return *breakLabel;
+ break;
+ case Continue:
+ if (continueLabel && (label.isEmpty() || label == loopLabel))
+ return *continueLabel;
+ break;
+ default:
+ break;
+ }
+ return BytecodeGenerator::Label();
}
- virtual void emitForThrowHandling() { }
+ QString label() const override { return loopLabel; }
};
+
struct ControlFlowWith : public ControlFlowUnwind
{
ControlFlowWith(Codegen *cg)
: ControlFlowUnwind(cg, With)
{
- needsLookupByName = true;
-
- savedContextRegister = Moth::StackSlot::createRegister(generator()->newRegister());
+ setupUnwindHandler();
// assumes the with object is in the accumulator
Instruction::PushWithContext pushScope;
- pushScope.reg = savedContextRegister;
generator()->addInstruction(pushScope);
- generator()->setExceptionHandler(&unwindLabel);
+ generator()->setUnwindHandler(&unwindLabel);
}
- virtual ~ControlFlowWith() {
+ ~ControlFlowWith() {
// emit code for unwinding
unwindLabel.link();
- generator()->setExceptionHandler(parentExceptionHandler());
+ generator()->setUnwindHandler(parentUnwindHandler());
Instruction::PopContext pop;
- pop.reg = savedContextRegister;
generator()->addInstruction(pop);
emitUnwindHandler();
}
- Moth::StackSlot savedContextRegister;
+
+ bool requiresUnwind() override {
+ return true;
+ }
+
+
+};
+
+struct ControlFlowBlock : public ControlFlowUnwind
+{
+ ControlFlowBlock(Codegen *cg, AST::Node *ast)
+ : ControlFlowUnwind(cg, Block)
+ {
+ block = cg->enterBlock(ast);
+ block->emitBlockHeader(cg);
+
+ if (block->requiresExecutionContext) {
+ setupUnwindHandler();
+ generator()->setUnwindHandler(&unwindLabel);
+ }
+ }
+
+ virtual ~ControlFlowBlock() {
+ // emit code for unwinding
+ if (block->requiresExecutionContext) {
+ unwindLabel.link();
+ generator()->setUnwindHandler(parentUnwindHandler());
+ }
+
+ block->emitBlockFooter(cg);
+
+ if (block->requiresExecutionContext )
+ emitUnwindHandler();
+ cg->leaveBlock();
+ }
+
+ virtual bool requiresUnwind() override {
+ return block->requiresExecutionContext;
+ }
+
+ Context *block;
};
struct ControlFlowCatch : public ControlFlowUnwind
@@ -330,71 +307,57 @@ struct ControlFlowCatch : public ControlFlowUnwind
AST::Catch *catchExpression;
bool insideCatch = false;
BytecodeGenerator::ExceptionHandler exceptionLabel;
- BytecodeGenerator::ExceptionHandler catchUnwindLabel;
+ bool oldLookupByName;
ControlFlowCatch(Codegen *cg, AST::Catch *catchExpression)
: ControlFlowUnwind(cg, Catch), catchExpression(catchExpression),
- exceptionLabel(generator()->newExceptionHandler()),
- catchUnwindLabel(generator()->newExceptionHandler())
+ exceptionLabel(generator()->newExceptionHandler())
{
- generator()->setExceptionHandler(&exceptionLabel);
+ generator()->setUnwindHandler(&exceptionLabel);
}
- virtual Handler getHandler(HandlerType type, const QString &label = QString()) {
- Handler h = getParentHandler(type, label);
- if (h.type == Invalid)
- return h;
- h = ControlFlowUnwind::getHandler(type, label);
- if (insideCatch)
- // if we're inside the catch block, we need to jump to the pop scope
- // instruction at the end of the catch block, not the unwind handler
- h.linkLabel = catchUnwindLabel;
- else if (type == Throw)
- // if we're inside the try block, we need to jump to the catch block,
- // not the unwind handler
- h.linkLabel = exceptionLabel;
- return h;
+ virtual bool requiresUnwind() override {
+ return true;
}
- virtual BytecodeGenerator::ExceptionHandler *exceptionHandler() {
- return insideCatch ? &catchUnwindLabel : &exceptionLabel;
+ BytecodeGenerator::ExceptionHandler *unwindHandler() override {
+ return insideCatch ? &unwindLabel : &exceptionLabel;
}
~ControlFlowCatch() {
// emit code for unwinding
-
- needsLookupByName = true;
insideCatch = true;
+ setupUnwindHandler();
Codegen::RegisterScope scope(cg);
// exceptions inside the try block go here
exceptionLabel.link();
- Moth::StackSlot savedContextReg = Moth::StackSlot::createRegister(generator()->newRegister());
- Instruction::PushCatchContext pushCatch;
- pushCatch.name = cg->registerString(catchExpression->name.toString());
- pushCatch.reg = savedContextReg;
- generator()->addInstruction(pushCatch);
- // clear the unwind temp for exceptions, we want to resume normal code flow afterwards
- Reference::storeConstOnStack(cg, QV4::Encode::undefined(), controlFlowTemp);
- generator()->setExceptionHandler(&catchUnwindLabel);
+ BytecodeGenerator::Jump noException = generator()->jumpNoException();
- cg->statement(catchExpression->statement);
+ Context *block = cg->enterBlock(catchExpression);
- insideCatch = false;
- needsLookupByName = false;
+ block->emitBlockHeader(cg);
- // exceptions inside catch and break/return statements go here
- catchUnwindLabel.link();
- Instruction::PopContext pop;
- pop.reg = savedContextReg;
- generator()->addInstruction(pop);
+ generator()->setUnwindHandler(&unwindLabel);
+
+ if (catchExpression->patternElement->bindingIdentifier.isEmpty())
+ // destructuring pattern
+ cg->initializeAndDestructureBindingElement(catchExpression->patternElement, Reference::fromName(cg, QStringLiteral("@caught")));
+ // skip the additional block
+ cg->statementList(catchExpression->statement->statements);
- // break/continue/return statements in try go here
+ // exceptions inside catch and break/return statements go here
unwindLabel.link();
- generator()->setExceptionHandler(parentExceptionHandler());
+ block->emitBlockFooter(cg);
+
+ cg->leaveBlock();
+
+ noException.link();
+ generator()->setUnwindHandler(parentUnwindHandler());
emitUnwindHandler();
+ insideCatch = false;
}
};
@@ -402,25 +365,21 @@ struct ControlFlowFinally : public ControlFlowUnwind
{
AST::Finally *finally;
bool insideFinally = false;
- int exceptionTemp = -1;
ControlFlowFinally(Codegen *cg, AST::Finally *finally)
: ControlFlowUnwind(cg, Finally), finally(finally)
{
Q_ASSERT(finally != nullptr);
- generator()->setExceptionHandler(&unwindLabel);
+ setupUnwindHandler();
+ generator()->setUnwindHandler(&unwindLabel);
}
- virtual Handler getHandler(HandlerType type, const QString &label = QString()) {
- // if we're inside the finally block, any exceptions etc. should
- // go directly to the parent handler
- if (insideFinally)
- return getParentHandler(type, label);
- return ControlFlowUnwind::getHandler(type, label);
+ virtual bool requiresUnwind() override {
+ return !insideFinally;
}
- virtual BytecodeGenerator::ExceptionHandler *exceptionHandler() {
- return insideFinally ? parentExceptionHandler() : ControlFlowUnwind::exceptionHandler();
+ BytecodeGenerator::ExceptionHandler *unwindHandler() override {
+ return insideFinally ? parentUnwindHandler() : ControlFlowUnwind::unwindHandler();
}
~ControlFlowFinally() {
@@ -429,34 +388,35 @@ struct ControlFlowFinally : public ControlFlowUnwind
Codegen::RegisterScope scope(cg);
- Moth::StackSlot retVal = Moth::StackSlot::createRegister(generator()->newRegister());
- Instruction::StoreReg storeRetVal;
- storeRetVal.reg = retVal;
- generator()->addInstruction(storeRetVal);
-
insideFinally = true;
- exceptionTemp = generator()->newRegister();
+ int returnValueTemp = -1;
+ if (cg->requiresReturnValue) {
+ returnValueTemp = generator()->newRegister();
+ Instruction::MoveReg move;
+ move.srcReg = cg->_returnAddress;
+ move.destReg = returnValueTemp;
+ generator()->addInstruction(move);
+ }
+ int exceptionTemp = generator()->newRegister();
Instruction::GetException instr;
generator()->addInstruction(instr);
Reference::fromStackSlot(cg, exceptionTemp).storeConsumeAccumulator();
- generator()->setExceptionHandler(parentExceptionHandler());
+ generator()->setUnwindHandler(parentUnwindHandler());
cg->statement(finally->statement);
insideFinally = false;
- Instruction::LoadReg loadRetVal;
- loadRetVal.reg = retVal;
- generator()->addInstruction(loadRetVal);
-
- emitUnwindHandler();
- }
-
- virtual void emitForThrowHandling() {
- // reset the exception flag, that got cleared before executing the statements in finally
+ if (cg->requiresReturnValue) {
+ Instruction::MoveReg move;
+ move.srcReg = returnValueTemp;
+ move.destReg = cg->_returnAddress;
+ generator()->addInstruction(move);
+ }
Reference::fromStackSlot(cg, exceptionTemp).loadInAccumulator();
Instruction::SetException setException;
- Q_ASSERT(exceptionTemp != -1);
generator()->addInstruction(setException);
+
+ emitUnwindHandler();
}
};
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 84ee452332..9be55c6ad0 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -56,12 +56,12 @@ using namespace QV4;
using namespace QV4::Compiler;
using namespace QQmlJS::AST;
-ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode)
+ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType)
: _cg(cg)
, _sourceCode(sourceCode)
, _context(nullptr)
, _allowFuncDecls(true)
- , defaultProgramMode(defaultProgramMode)
+ , defaultProgramType(defaultProgramType)
{
}
@@ -73,18 +73,19 @@ void ScanFunctions::operator()(Node *node)
calcEscapingVariables();
}
-void ScanFunctions::enterGlobalEnvironment(CompilationMode compilationMode)
+void ScanFunctions::enterGlobalEnvironment(ContextType compilationMode)
{
- enterEnvironment(astNodeForGlobalEnvironment, compilationMode);
+ enterEnvironment(astNodeForGlobalEnvironment, compilationMode, QStringLiteral("%GlobalCode"));
}
-void ScanFunctions::enterEnvironment(Node *node, CompilationMode compilationMode)
+void ScanFunctions::enterEnvironment(Node *node, ContextType compilationMode, const QString &name)
{
Context *c = _cg->_module->contextMap.value(node);
if (!c)
c = _cg->_module->newContext(node, _context, compilationMode);
if (!c->isStrict)
c->isStrict = _cg->_strictMode;
+ c->name = name;
_contextStack.append(c);
_context = c;
}
@@ -92,28 +93,26 @@ void ScanFunctions::enterEnvironment(Node *node, CompilationMode compilationMode
void ScanFunctions::leaveEnvironment()
{
_contextStack.pop();
- _context = _contextStack.isEmpty() ? 0 : _contextStack.top();
-}
-
-void ScanFunctions::checkDirectivePrologue(SourceElements *ast)
-{
- for (SourceElements *it = ast; it; it = it->next) {
- if (StatementSourceElement *stmt = cast<StatementSourceElement *>(it->element)) {
- if (ExpressionStatement *expr = cast<ExpressionStatement *>(stmt->statement)) {
- if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
- // Use the source code, because the StringLiteral's
- // value might have escape sequences in it, which is not
- // allowed.
- if (strLit->literalToken.length < 2)
- continue;
- QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
- if (str == QLatin1String("use strict")) {
- _context->isStrict = true;
- } else {
- // TODO: give a warning.
- }
+ _context = _contextStack.isEmpty() ? nullptr : _contextStack.top();
+}
+
+void ScanFunctions::checkDirectivePrologue(StatementList *ast)
+{
+ for (StatementList *it = ast; it; it = it->next) {
+ if (ExpressionStatement *expr = cast<ExpressionStatement *>(it->statement)) {
+ if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
+ // Use the source code, because the StringLiteral's
+ // value might have escape sequences in it, which is not
+ // allowed.
+ if (strLit->literalToken.length < 2)
continue;
+ QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
+ if (str == QLatin1String("use strict")) {
+ _context->isStrict = true;
+ } else {
+ // TODO: give a warning.
}
+ continue;
}
}
@@ -138,20 +137,10 @@ void ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc)
}
}
-bool ScanFunctions::formalsContainName(AST::FormalParameterList *parameters, const QString &name)
-{
- while (parameters) {
- if (parameters->name == name)
- return true;
- parameters = parameters->next;
- }
- return false;
-}
-
bool ScanFunctions::visit(Program *ast)
{
- enterEnvironment(ast, defaultProgramMode);
- checkDirectivePrologue(ast->elements);
+ enterEnvironment(ast, defaultProgramType, QStringLiteral("%ProgramCode"));
+ checkDirectivePrologue(ast->statements);
return true;
}
@@ -162,7 +151,7 @@ void ScanFunctions::endVisit(Program *)
bool ScanFunctions::visit(CallExpression *ast)
{
- if (! _context->hasDirectEval) {
+ if (!_context->hasDirectEval) {
if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
if (id->name == QLatin1String("eval")) {
if (_context->usesArgumentsObject == Context::ArgumentsObjectUnknown)
@@ -171,53 +160,31 @@ bool ScanFunctions::visit(CallExpression *ast)
}
}
}
- int argc = 0;
- for (ArgumentList *it = ast->arguments; it; it = it->next)
- ++argc;
- _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, argc);
return true;
}
-bool ScanFunctions::visit(NewMemberExpression *ast)
+bool ScanFunctions::visit(PatternElement *ast)
{
- int argc = 0;
- for (ArgumentList *it = ast->arguments; it; it = it->next)
- ++argc;
- _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, argc);
- return true;
-}
+ if (!ast->isVariableDeclaration())
+ return true;
-bool ScanFunctions::visit(ArrayLiteral *ast)
-{
- int index = 0;
- for (ElementList *it = ast->elements; it; it = it->next) {
- for (Elision *elision = it->elision; elision; elision = elision->next)
- ++index;
- ++index;
- }
- if (ast->elision) {
- for (Elision *elision = ast->elision->next; elision; elision = elision->next)
- ++index;
- }
- _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, index);
- return true;
-}
+ QStringList names;
+ ast->boundNames(&names);
-bool ScanFunctions::visit(VariableDeclaration *ast)
-{
- if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
- _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Variable name may not be eval or arguments in strict mode"));
- checkName(ast->name, ast->identifierToken);
- if (ast->name == QLatin1String("arguments"))
- _context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
- if (ast->scope == AST::VariableDeclaration::VariableScope::ReadOnlyBlockScope && !ast->expression) {
- _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration"));
- return false;
- }
- QString name = ast->name.toString();
- if (!_context->addLocalVar(ast->name.toString(), ast->expression ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope)) {
- _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name));
- return false;
+ for (const QString &name : qAsConst(names)) {
+ if (_context->isStrict && (name == QLatin1String("eval") || name == QLatin1String("arguments")))
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Variable name may not be eval or arguments in strict mode"));
+ checkName(QStringRef(&name), ast->identifierToken);
+ if (name == QLatin1String("arguments"))
+ _context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ if (ast->scope == VariableScope::Const && !ast->initializer && !ast->destructuringPattern()) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration"));
+ return false;
+ }
+ if (!_context->addLocalVar(name, ast->initializer ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope)) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name));
+ return false;
+ }
}
return true;
}
@@ -237,7 +204,8 @@ bool ScanFunctions::visit(ExpressionStatement *ast)
if (!_allowFuncDecls)
_cg->throwSyntaxError(expr->functionToken, QStringLiteral("conditional function or closure declaration"));
- enterFunction(expr, /*enterName*/ true);
+ if (!enterFunction(expr, /*enterName*/ true))
+ return false;
Node::accept(expr->formals, this);
Node::accept(expr->body, this);
leaveEnvironment();
@@ -253,79 +221,98 @@ bool ScanFunctions::visit(ExpressionStatement *ast)
bool ScanFunctions::visit(FunctionExpression *ast)
{
- enterFunction(ast, /*enterName*/ false);
+ return enterFunction(ast, /*enterName*/ false);
+}
+
+bool ScanFunctions::visit(ClassExpression *ast)
+{
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%Class"));
+ _context->isStrict = true;
+ _context->hasNestedFunctions = true;
+ if (!ast->name.isEmpty())
+ _context->addLocalVar(ast->name.toString(), Context::VariableDefinition, AST::VariableScope::Const);
return true;
}
-void ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
+void ScanFunctions::endVisit(ClassExpression *)
{
- if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
- _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode"));
- enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr);
+ leaveEnvironment();
}
-void ScanFunctions::endVisit(FunctionExpression *)
+bool ScanFunctions::visit(ClassDeclaration *ast)
+{
+ if (!ast->name.isEmpty())
+ _context->addLocalVar(ast->name.toString(), Context::VariableDeclaration, AST::VariableScope::Let);
+
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%Class"));
+ _context->isStrict = true;
+ _context->hasNestedFunctions = true;
+ if (!ast->name.isEmpty())
+ _context->addLocalVar(ast->name.toString(), Context::VariableDefinition, AST::VariableScope::Const);
+ return true;
+}
+
+void ScanFunctions::endVisit(ClassDeclaration *)
{
leaveEnvironment();
}
-bool ScanFunctions::visit(ObjectLiteral *ast)
+bool ScanFunctions::visit(TemplateLiteral *ast)
{
- int argc = 0;
- for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
- QString key = it->assignment->name->asString();
- if (QV4::String::toArrayIndex(key) != UINT_MAX)
- ++argc;
- ++argc;
- if (AST::cast<AST::PropertyGetterSetter *>(it->assignment))
- ++argc;
+ while (ast) {
+ if (ast->expression)
+ Node::accept(ast->expression, this);
+ ast = ast->next;
}
- _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, argc);
+ return true;
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
- Node::accept(ast->properties, this);
- return false;
}
-bool ScanFunctions::visit(PropertyGetterSetter *ast)
+bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
{
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
- enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr);
- return true;
+ if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode"));
+ return enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName);
}
-void ScanFunctions::endVisit(PropertyGetterSetter *)
+void ScanFunctions::endVisit(FunctionExpression *)
{
leaveEnvironment();
}
-bool ScanFunctions::visit(FunctionDeclaration *ast)
+bool ScanFunctions::visit(ObjectPattern *ast)
{
- enterFunction(ast, /*enterName*/ true);
- return true;
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
+ Node::accept(ast->properties, this);
+ return false;
}
-void ScanFunctions::endVisit(FunctionDeclaration *)
+bool ScanFunctions::visit(PatternProperty *ast)
{
- leaveEnvironment();
+ Q_UNUSED(ast);
+ // ### Shouldn't be required anymore
+// if (ast->type == PatternProperty::Getter || ast->type == PatternProperty::Setter) {
+// TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
+// return enterFunction(ast, QString(), ast->formals, ast->functionBody, /*enterName */ false);
+// }
+ return true;
}
-bool ScanFunctions::visit(TryStatement *)
+void ScanFunctions::endVisit(PatternProperty *)
{
- // ### should limit to catch(), as try{} finally{} should be ok without
- _context->hasTry = true;
- return true;
+ // ###
+// if (ast->type == PatternProperty::Getter || ast->type == PatternProperty::Setter)
+// leaveEnvironment();
}
-bool ScanFunctions::visit(WithStatement *ast)
+bool ScanFunctions::visit(FunctionDeclaration *ast)
{
- if (_context->isStrict) {
- _cg->throwSyntaxError(ast->withToken, QStringLiteral("'with' statement is not allowed in strict mode"));
- return false;
- }
+ return enterFunction(ast, /*enterName*/ true);
+}
- _context->hasWith = true;
- return true;
+void ScanFunctions::endVisit(FunctionDeclaration *)
+{
+ leaveEnvironment();
}
bool ScanFunctions::visit(DoWhileStatement *ast) {
@@ -338,7 +325,9 @@ bool ScanFunctions::visit(DoWhileStatement *ast) {
}
bool ScanFunctions::visit(ForStatement *ast) {
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%For"));
Node::accept(ast->initialiser, this);
+ Node::accept(ast->declarations, this);
Node::accept(ast->condition, this);
Node::accept(ast->expression, this);
@@ -348,9 +337,14 @@ bool ScanFunctions::visit(ForStatement *ast) {
return false;
}
-bool ScanFunctions::visit(LocalForStatement *ast) {
- Node::accept(ast->declarations, this);
- Node::accept(ast->condition, this);
+void ScanFunctions::endVisit(ForStatement *)
+{
+ leaveEnvironment();
+}
+
+bool ScanFunctions::visit(ForEachStatement *ast) {
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%Foreach"));
+ Node::accept(ast->lhs, this);
Node::accept(ast->expression, this);
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
@@ -359,90 +353,154 @@ bool ScanFunctions::visit(LocalForStatement *ast) {
return false;
}
-bool ScanFunctions::visit(ForEachStatement *ast) {
- Node::accept(ast->initialiser, this);
- Node::accept(ast->expression, this);
+void ScanFunctions::endVisit(ForEachStatement *)
+{
+ leaveEnvironment();
+}
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
- Node::accept(ast->statement, this);
+bool ScanFunctions::visit(ThisExpression *)
+{
+ _context->usesThis = true;
+ return false;
+}
+bool ScanFunctions::visit(Block *ast)
+{
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%Block"));
+ Node::accept(ast->statements, this);
return false;
}
-bool ScanFunctions::visit(LocalForEachStatement *ast) {
- Node::accept(ast->declaration, this);
- Node::accept(ast->expression, this);
+void ScanFunctions::endVisit(Block *)
+{
+ leaveEnvironment();
+}
- TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_context->isStrict);
- Node::accept(ast->statement, this);
+bool ScanFunctions::visit(CaseBlock *ast)
+{
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%CaseBlock"));
+ return true;
+}
- return false;
+void ScanFunctions::endVisit(CaseBlock *)
+{
+ leaveEnvironment();
}
-bool ScanFunctions::visit(ThisExpression *)
+bool ScanFunctions::visit(Catch *ast)
{
- _context->usesThis = true;
+ TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%CatchBlock"));
+ _context->isCatchBlock = true;
+ QString caughtVar = ast->patternElement->bindingIdentifier.toString();
+ if (caughtVar.isEmpty())
+ caughtVar = QStringLiteral("@caught");
+ _context->addLocalVar(caughtVar, Context::MemberType::VariableDefinition, VariableScope::Let);
+
+ _context->caughtVariable = caughtVar;
+ if (_context->isStrict &&
+ (caughtVar == QLatin1String("eval") || caughtVar == QLatin1String("arguments"))) {
+ _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Catch variable name may not be eval or arguments in strict mode"));
+ return false;
+ }
+ Node::accept(ast->patternElement, this);
+ // skip the block statement
+ Node::accept(ast->statement->statements, this);
return false;
}
-bool ScanFunctions::visit(Block *ast) {
+void ScanFunctions::endVisit(Catch *)
+{
+ leaveEnvironment();
+}
+
+bool ScanFunctions::visit(WithStatement *ast)
+{
+ Node::accept(ast->expression, this);
+
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
- Node::accept(ast->statements, this);
+ enterEnvironment(ast, ContextType::Block, QStringLiteral("%WithBlock"));
+ _context->isWithBlock = true;
+
+ if (_context->isStrict) {
+ _cg->throwSyntaxError(ast->withToken, QStringLiteral("'with' statement is not allowed in strict mode"));
+ return false;
+ }
+ Node::accept(ast->statement, this);
+
return false;
}
-void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr)
+void ScanFunctions::endVisit(WithStatement *)
+{
+ leaveEnvironment();
+}
+
+bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, bool enterName)
{
Context *outerContext = _context;
- enterEnvironment(ast, FunctionCode);
+ enterEnvironment(ast, ContextType::Function, name);
+ FunctionExpression *expr = AST::cast<FunctionExpression *>(ast);
+ if (!expr)
+ expr = AST::cast<FunctionDeclaration *>(ast);
if (outerContext) {
outerContext->hasNestedFunctions = true;
// The identifier of a function expression cannot be referenced from the enclosing environment.
- if (expr) {
- if (!outerContext->addLocalVar(name, Context::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr)) {
+ if (enterName) {
+ if (!outerContext->addLocalVar(name, Context::FunctionDefinition, VariableScope::Var, expr)) {
_cg->throwSyntaxError(ast->firstSourceLocation(), QStringLiteral("Identifier %1 has already been declared").arg(name));
- return;
+ return false;
}
+ outerContext->addLocalVar(name, Context::FunctionDefinition, VariableScope::Var, expr);
}
if (name == QLatin1String("arguments"))
outerContext->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
- if (formalsContainName(formals, QStringLiteral("arguments")))
+ _context->name = name;
+ if (formals && formals->containsName(QStringLiteral("arguments")))
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ if (expr) {
+ if (expr->isArrowFunction)
+ _context->isArrowFunction = true;
+ else if (expr->isGenerator)
+ _context->isGenerator = true;
+ }
- if (!name.isEmpty() && !formalsContainName(formals, name))
- _context->addLocalVar(name, Context::ThisFunctionName, QQmlJS::AST::VariableDeclaration::FunctionScope);
+ if (!name.isEmpty() && (!formals || !formals->containsName(name)))
+ _context->addLocalVar(name, Context::ThisFunctionName, VariableScope::Var);
_context->formals = formals;
if (body && !_context->isStrict)
- checkDirectivePrologue(body->elements);
-
- for (FormalParameterList *it = formals; it; it = it->next) {
- QString arg = it->name.toString();
- int duplicateIndex = _context->arguments.indexOf(arg);
- if (duplicateIndex != -1) {
- if (_context->isStrict) {
- _cg->throwSyntaxError(it->identifierToken, QStringLiteral("Duplicate parameter name '%1' is not allowed in strict mode").arg(arg));
- return;
- } else {
- // change the name of the earlier argument to enforce the specified lookup semantics
- QString modified = arg;
- while (_context->arguments.contains(modified))
- modified += QString(0xfffe);
- _context->arguments[duplicateIndex] = modified;
+ checkDirectivePrologue(body);
+
+ bool isSimpleParameterList = formals && formals->isSimpleParameterList();
+
+ _context->arguments = formals ? formals->formals() : QStringList();
+
+ const QStringList boundNames = formals ? formals->boundNames() : QStringList();
+ for (int i = 0; i < boundNames.size(); ++i) {
+ const QString &arg = boundNames.at(i);
+ if (_context->isStrict || !isSimpleParameterList) {
+ bool duplicate = (boundNames.indexOf(arg, i + 1) != -1);
+ if (duplicate) {
+ _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("Duplicate parameter name '%1' is not allowed.").arg(arg));
+ return false;
}
}
if (_context->isStrict) {
if (arg == QLatin1String("eval") || arg == QLatin1String("arguments")) {
- _cg->throwSyntaxError(it->identifierToken, QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg));
- return;
+ _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg));
+ return false;
}
}
- _context->arguments += arg;
+ if (!_context->arguments.contains(arg))
+ _context->addLocalVar(arg, Context::VariableDefinition, VariableScope::Var);
}
+ return true;
}
void ScanFunctions::calcEscapingVariables()
@@ -450,27 +508,114 @@ void ScanFunctions::calcEscapingVariables()
Module *m = _cg->_module;
for (Context *inner : qAsConst(m->contextMap)) {
+ if (inner->contextType == ContextType::Block && inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ Context *c = inner->parent;
+ while (c->contextType == ContextType::Block)
+ c = c->parent;
+ c->usesArgumentsObject = Context::ArgumentsObjectUsed;
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ }
+ }
+ for (Context *inner : qAsConst(m->contextMap)) {
+ if (!inner->parent || inner->usesArgumentsObject == Context::ArgumentsObjectUnknown)
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ if (inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ QString arguments = QStringLiteral("arguments");
+ inner->addLocalVar(arguments, Context::VariableDeclaration, AST::VariableScope::Var);
+ if (!inner->isStrict) {
+ inner->argumentsCanEscape = true;
+ inner->requiresExecutionContext = true;
+ }
+ }
+ }
+
+ for (Context *inner : qAsConst(m->contextMap)) {
for (const QString &var : qAsConst(inner->usedVariables)) {
Context *c = inner;
while (c) {
+ Context *current = c;
+ c = c->parent;
+ if (current->isWithBlock || current->contextType != ContextType::Block)
+ break;
+ }
+ Q_ASSERT(c != inner);
+ while (c) {
Context::MemberMap::const_iterator it = c->members.find(var);
if (it != c->members.end()) {
- if (c != inner)
+ if (c->parent || it->isLexicallyScoped()) {
it->canEscape = true;
+ c->requiresExecutionContext = true;
+ }
break;
}
if (c->findArgument(var) != -1) {
- if (c != inner)
- c->argumentsCanEscape = true;
+ c->argumentsCanEscape = true;
+ c->requiresExecutionContext = true;
break;
}
c = c->parent;
}
}
- Context *c = inner->parent;
- while (c) {
- c->hasDirectEval |= inner->hasDirectEval;
- c = c->parent;
+ if (inner->hasDirectEval) {
+ inner->hasDirectEval = false;
+ if (!inner->isStrict) {
+ Context *c = inner;
+ while (c->contextType == ContextType::Block) {
+ c = c->parent;
+ }
+ Q_ASSERT(c);
+ c->hasDirectEval = true;
+ }
+ Context *c = inner;
+ while (c) {
+ c->allVarsEscape = true;
+ c = c->parent;
+ }
+ }
+ if (inner->usesThis) {
+ inner->usesThis = false;
+ if (!inner->isStrict) {
+ Context *c = inner;
+ while (c->contextType == ContextType::Block) {
+ c = c->parent;
+ }
+ Q_ASSERT(c);
+ c->usesThis = true;
+ }
+ }
+ }
+ for (Context *c : qAsConst(m->contextMap)) {
+ if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
+ c->allVarsEscape = false;
+ if (c->contextType == ContextType::Global || (!c->isStrict && c->contextType == ContextType::Eval) || m->debugMode)
+ c->allVarsEscape = true;
+ if (c->allVarsEscape) {
+ if (c->parent) {
+ c->requiresExecutionContext = true;
+ c->argumentsCanEscape = true;
+ } else {
+ for (const auto &m : qAsConst(c->members)) {
+ if (m.isLexicallyScoped()) {
+ c->requiresExecutionContext = true;
+ break;
+ }
+ }
+ }
+ }
+ if (c->contextType == ContextType::Block && c->isCatchBlock) {
+ c->requiresExecutionContext = true;
+ auto m = c->members.find(c->caughtVariable);
+ m->canEscape = true;
+ }
+ const QLatin1String exprForOn("expression for on");
+ if (c->contextType == ContextType::Binding && c->name.length() > exprForOn.size() &&
+ c->name.startsWith(exprForOn) && c->name.at(exprForOn.size()).isUpper())
+ // we don't really need this for bindings, but we do for signal handlers, and in this case,
+ // we don't know if the code is a signal handler or not.
+ c->requiresExecutionContext = true;
+ if (c->allVarsEscape) {
+ for (auto &m : c->members)
+ m.canEscape = true;
}
}
@@ -478,10 +623,12 @@ void ScanFunctions::calcEscapingVariables()
if (showEscapingVars) {
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
- qDebug() << "Context" << c->name << ":";
- qDebug() << " Arguments escape" << c->argumentsCanEscape;
+ qDebug() << "Context" << c << c->name << "requiresExecutionContext" << c->requiresExecutionContext << "isStrict" << c->isStrict;
+ qDebug() << " parent:" << c->parent;
+ if (c->argumentsCanEscape)
+ qDebug() << " Arguments escape";
for (auto it = c->members.constBegin(); it != c->members.constEnd(); ++it) {
- qDebug() << " " << it.key() << it.value().canEscape;
+ qDebug() << " " << it.key() << it.value().index << it.value().canEscape << "isLexicallyScoped:" << it.value().isLexicallyScoped();
}
}
}
diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h
index 87b7210879..4c273600b3 100644
--- a/src/qml/compiler/qv4compilerscanfunctions_p.h
+++ b/src/qml/compiler/qv4compilerscanfunctions_p.h
@@ -58,6 +58,7 @@
#include <private/qv4util_p.h>
#include <QtCore/QStringList>
#include <QStack>
+#include <QScopedValueRollback>
QT_BEGIN_NAMESPACE
@@ -79,13 +80,13 @@ class Codegen;
class ScanFunctions: protected QQmlJS::AST::Visitor
{
- typedef QV4::TemporaryAssignment<bool> TemporaryBoolAssignment;
+ typedef QScopedValueRollback<bool> TemporaryBoolAssignment;
public:
- ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode);
+ ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType);
void operator()(AST::Node *node);
- void enterGlobalEnvironment(CompilationMode compilationMode);
- void enterEnvironment(AST::Node *node, CompilationMode compilationMode);
+ void enterGlobalEnvironment(ContextType compilationMode);
+ void enterEnvironment(AST::Node *node, ContextType compilationMode, const QString &name);
void leaveEnvironment();
void enterQmlFunction(AST::FunctionDeclaration *ast)
@@ -95,48 +96,60 @@ protected:
using Visitor::visit;
using Visitor::endVisit;
- void checkDirectivePrologue(AST::SourceElements *ast);
+ void checkDirectivePrologue(AST::StatementList *ast);
void checkName(const QStringRef &name, const AST::SourceLocation &loc);
- bool formalsContainName(AST::FormalParameterList *parameters, const QString &name);
bool visit(AST::Program *ast) override;
void endVisit(AST::Program *) override;
bool visit(AST::CallExpression *ast) override;
- bool visit(AST::NewMemberExpression *ast) override;
- bool visit(AST::ArrayLiteral *ast) override;
- bool visit(AST::VariableDeclaration *ast) override;
+ bool visit(AST::PatternElement *ast) override;
bool visit(AST::IdentifierExpression *ast) override;
bool visit(AST::ExpressionStatement *ast) override;
bool visit(AST::FunctionExpression *ast) override;
+ bool visit(AST::TemplateLiteral *ast) override;
- void enterFunction(AST::FunctionExpression *ast, bool enterName);
+ bool enterFunction(AST::FunctionExpression *ast, bool enterName);
void endVisit(AST::FunctionExpression *) override;
- bool visit(AST::ObjectLiteral *ast) override;
+ bool visit(AST::ObjectPattern *ast) override;
- bool visit(AST::PropertyGetterSetter *ast) override;
- void endVisit(AST::PropertyGetterSetter *) override;
+ bool visit(AST::PatternProperty *ast) override;
+ void endVisit(AST::PatternProperty *) override;
bool visit(AST::FunctionDeclaration *ast) override;
void endVisit(AST::FunctionDeclaration *) override;
- bool visit(AST::TryStatement *ast) override;
- bool visit(AST::WithStatement *ast) override;
+ bool visit(AST::ClassExpression *ast) override;
+ void endVisit(AST::ClassExpression *) override;
+
+ bool visit(AST::ClassDeclaration *ast) override;
+ void endVisit(AST::ClassDeclaration *) override;
bool visit(AST::DoWhileStatement *ast) override;
bool visit(AST::ForStatement *ast) override;
- bool visit(AST::LocalForStatement *ast) override;
+ void endVisit(AST::ForStatement *) override;
bool visit(AST::ForEachStatement *ast) override;
- bool visit(AST::LocalForEachStatement *ast) override;
+ void endVisit(AST::ForEachStatement *) override;
+
bool visit(AST::ThisExpression *ast) override;
bool visit(AST::Block *ast) override;
+ void endVisit(AST::Block *ast) override;
+
+ bool visit(AST::CaseBlock *ast) override;
+ void endVisit(AST::CaseBlock *ast) override;
+
+ bool visit(AST::Catch *ast) override;
+ void endVisit(AST::Catch *ast) override;
+
+ bool visit(AST::WithStatement *ast) override;
+ void endVisit(AST::WithStatement *ast) override;
protected:
- void enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::FunctionBody *body, AST::FunctionExpression *expr);
+ bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, bool enterName);
void calcEscapingVariables();
// fields:
@@ -146,7 +159,7 @@ protected:
QStack<Context *> _contextStack;
bool _allowFuncDecls;
- CompilationMode defaultProgramMode;
+ ContextType defaultProgramType;
private:
static constexpr AST::Node *astNodeForGlobalEnvironment = nullptr;
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 450fa50528..8e474b3783 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -39,15 +39,16 @@
#include "qv4instr_moth_p.h"
#include <private/qv4compileddata_p.h>
+#include <private/qv4stackframe_p.h>
using namespace QV4;
using namespace QV4::Moth;
int InstrInfo::size(Instr::Type type)
{
-#define MOTH_RETURN_INSTR_SIZE(I) case Instr::Type::I: return InstrMeta<int(Instr::Type::I)>::Size;
+#define MOTH_RETURN_INSTR_SIZE(I) case Instr::Type::I: case Instr::Type::I##_Wide: return InstrMeta<int(Instr::Type::I)>::Size;
switch (type) {
- FOR_EACH_MOTH_INSTR(MOTH_RETURN_INSTR_SIZE)
+ FOR_EACH_MOTH_INSTR_ALL(MOTH_RETURN_INSTR_SIZE)
}
#undef MOTH_RETURN_INSTR_SIZE
Q_UNREACHABLE();
@@ -110,6 +111,8 @@ static QString toString(QV4::ReturnedValue v)
QDebug d = qDebug(); \
d.noquote(); \
d.nospace(); \
+ if (static_cast<int>(Instr::Type::instr) >= 0x100) \
+ --base_ptr; \
d << alignedLineNumber(line) << alignedNumber(codeOffset).constData() << ": " \
<< rawBytes(base_ptr, int(code - base_ptr)) << #instr << " ";
@@ -122,7 +125,7 @@ namespace QV4 {
namespace Moth {
const int InstrInfo::argumentCount[] = {
- FOR_EACH_MOTH_INSTR(MOTH_COLLECT_NARGS)
+ FOR_EACH_MOTH_INSTR_ALL(MOTH_COLLECT_NARGS)
};
@@ -147,6 +150,8 @@ QString dumpRegister(int reg, int nFormals)
return QStringLiteral("(context)");
else if (reg == CallData::Accumulator)
return QStringLiteral("(accumulator)");
+ else if (reg == CallData::NewTarget)
+ return QStringLiteral("(new.target)");
else if (reg == CallData::This)
return QStringLiteral("(this)");
else if (reg == CallData::Argc)
@@ -286,10 +291,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(StoreNameStrict)
MOTH_BEGIN_INSTR(LoadElement)
- d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]";
- MOTH_END_INSTR(LoadElement)
-
- MOTH_BEGIN_INSTR(LoadElementA)
d << dumpRegister(base, nFormals) << "[acc]";
MOTH_END_INSTR(LoadElement)
@@ -298,20 +299,12 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
- d << dumpRegister(base, nFormals) << "[" << name << "]";
- MOTH_END_INSTR(LoadProperty)
-
- MOTH_BEGIN_INSTR(LoadPropertyA)
d << "acc[" << name << "]";
- MOTH_END_INSTR(LoadElementA)
+ MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
- d << dumpRegister(base, nFormals) << "(" << index << ")";
- MOTH_END_INSTR(GetLookup)
-
- MOTH_BEGIN_INSTR(GetLookupA)
d << "acc(" << index << ")";
- MOTH_END_INSTR(GetLookupA)
+ MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
d << dumpRegister(base, nFormals) << "[" << name<< "]";
@@ -321,6 +314,14 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(base, nFormals) << "(" << index << ")";
MOTH_END_INSTR(SetLookup)
+ MOTH_BEGIN_INSTR(LoadSuperProperty)
+ d << dumpRegister(property, nFormals);
+ MOTH_END_INSTR(LoadSuperProperty)
+
+ MOTH_BEGIN_INSTR(StoreSuperProperty)
+ d << dumpRegister(property, nFormals);
+ MOTH_END_INSTR(StoreSuperProperty)
+
MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
d << dumpRegister(base, nFormals) << "[" << propertyIndex << "]";
MOTH_END_INSTR(StoreScopeObjectProperty)
@@ -341,6 +342,13 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(base, nFormals) << "[" << index << "]";
MOTH_END_INSTR(LoadIdObject)
+ MOTH_BEGIN_INSTR(Yield)
+ MOTH_END_INSTR(Yield)
+
+ MOTH_BEGIN_INSTR(Resume)
+ d << ABSOLUTE_OFFSET();
+ MOTH_END_INSTR(Resume)
+
MOTH_BEGIN_INSTR(CallValue)
d << dumpRegister(name, nFormals) << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallValue)
@@ -377,12 +385,31 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallContextObjectProperty)
- MOTH_BEGIN_INSTR(SetExceptionHandler)
+ MOTH_BEGIN_INSTR(CallWithSpread)
+ d << "new" << dumpRegister(func, nFormals) << dumpRegister(thisObject, nFormals) << dumpArguments(argc, argv, nFormals);
+ MOTH_END_INSTR(CallWithSpread)
+
+ MOTH_BEGIN_INSTR(Construct)
+ d << "new" << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
+ MOTH_END_INSTR(Construct)
+
+ MOTH_BEGIN_INSTR(ConstructWithSpread)
+ d << "new" << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
+ MOTH_END_INSTR(ConstructWithSpread)
+
+ MOTH_BEGIN_INSTR(SetUnwindHandler)
if (offset)
d << ABSOLUTE_OFFSET();
else
d << "<null>";
- MOTH_END_INSTR(SetExceptionHandler)
+ MOTH_END_INSTR(SetUnwindHandler)
+
+ MOTH_BEGIN_INSTR(UnwindDispatch)
+ MOTH_END_INSTR(UnwindDispatch)
+
+ MOTH_BEGIN_INSTR(UnwindToLabel)
+ d << "(" << level << ") " << ABSOLUTE_OFFSET();
+ MOTH_END_INSTR(UnwindToLabel)
MOTH_BEGIN_INSTR(ThrowException)
MOTH_END_INSTR(ThrowException)
@@ -397,30 +424,47 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(CreateCallContext)
MOTH_BEGIN_INSTR(PushCatchContext)
- d << dumpRegister(reg, nFormals) << ", " << name;
+ d << index << ", " << name;
MOTH_END_INSTR(PushCatchContext)
MOTH_BEGIN_INSTR(PushWithContext)
- d << dumpRegister(reg, nFormals);
MOTH_END_INSTR(PushWithContext)
+ MOTH_BEGIN_INSTR(PushBlockContext)
+ d << index;
+ MOTH_END_INSTR(PushBlockContext)
+
+ MOTH_BEGIN_INSTR(CloneBlockContext)
+ MOTH_END_INSTR(CloneBlockContext)
+
+ MOTH_BEGIN_INSTR(PushScriptContext)
+ d << index;
+ MOTH_END_INSTR(PushScriptContext)
+
+ MOTH_BEGIN_INSTR(PopScriptContext)
+ MOTH_END_INSTR(PopScriptContext)
+
MOTH_BEGIN_INSTR(PopContext)
- d << dumpRegister(reg, nFormals);
MOTH_END_INSTR(PopContext)
- MOTH_BEGIN_INSTR(ForeachIteratorObject)
- MOTH_END_INSTR(ForeachIteratorObject)
+ MOTH_BEGIN_INSTR(GetIterator)
+ d << iterator;
+ MOTH_END_INSTR(GetIterator)
+
+ MOTH_BEGIN_INSTR(IteratorNext)
+ d << dumpRegister(value, nFormals);
+ MOTH_END_INSTR(IteratorNext)
- MOTH_BEGIN_INSTR(ForeachNextPropertyName)
- MOTH_END_INSTR(ForeachNextPropertyName)
+ MOTH_BEGIN_INSTR(IteratorClose)
+ d << dumpRegister(done, nFormals);
+ MOTH_END_INSTR(IteratorClose)
- MOTH_BEGIN_INSTR(DeleteMember)
- d << dumpRegister(base, nFormals) << "[" << member << "]";
- MOTH_END_INSTR(DeleteMember)
+ MOTH_BEGIN_INSTR(DestructureRestElement)
+ MOTH_END_INSTR(DestructureRestElement)
- MOTH_BEGIN_INSTR(DeleteSubscript)
+ MOTH_BEGIN_INSTR(DeleteProperty)
d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]";
- MOTH_END_INSTR(DeleteSubscript)
+ MOTH_END_INSTR(DeleteProperty)
MOTH_BEGIN_INSTR(DeleteName)
d << name;
@@ -442,24 +486,35 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(DefineArray)
MOTH_BEGIN_INSTR(DefineObjectLiteral)
- d << dumpRegister(args, nFormals)
- << ", " << internalClassId
- << ", " << arrayValueCount
- << ", " << arrayGetterSetterCountAndFlags;
+ d << internalClassId
+ << ", " << argc
+ << ", " << dumpRegister(args, nFormals);
MOTH_END_INSTR(DefineObjectLiteral)
+ MOTH_BEGIN_INSTR(CreateClass)
+ d << classIndex
+ << ", " << dumpRegister(heritage, nFormals)
+ << ", " << dumpRegister(computedNames, nFormals);
+ MOTH_END_INSTR(CreateClass)
+
MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
MOTH_END_INSTR(CreateMappedArgumentsObject)
MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
+ MOTH_BEGIN_INSTR(CreateRestParameter)
+ d << argIndex;
+ MOTH_END_INSTR(CreateRestParameter)
+
MOTH_BEGIN_INSTR(ConvertThisToObject)
MOTH_END_INSTR(ConvertThisToObject)
- MOTH_BEGIN_INSTR(Construct)
- d << "new" << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
- MOTH_END_INSTR(Construct)
+ MOTH_BEGIN_INSTR(LoadSuperConstructor)
+ MOTH_END_INSTR(LoadSuperConstructor)
+
+ MOTH_BEGIN_INSTR(ToObject)
+ MOTH_END_INSTR(ToObject)
MOTH_BEGIN_INSTR(Jump)
d << ABSOLUTE_OFFSET();
@@ -473,6 +528,14 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << ABSOLUTE_OFFSET();
MOTH_END_INSTR(JumpFalse)
+ MOTH_BEGIN_INSTR(JumpNotUndefined)
+ d << ABSOLUTE_OFFSET();
+ MOTH_END_INSTR(JumpNotUndefined)
+
+ MOTH_BEGIN_INSTR(JumpNoException)
+ d << ABSOLUTE_OFFSET();
+ MOTH_END_INSTR(JumpNoException)
+
MOTH_BEGIN_INSTR(CmpEqNull)
MOTH_END_INSTR(CmpEqNull)
@@ -519,14 +582,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(lhs, nFormals);
MOTH_END_INSTR(CmpStrictNotEqual)
- MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
- d << dumpRegister(lhs, nFormals) << ", " << rhs << " " << ABSOLUTE_OFFSET();
- MOTH_END_INSTR(JumpStrictEqualStackSlotInt)
-
- MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
- d << dumpRegister(lhs, nFormals) << ", " << rhs << " " << ABSOLUTE_OFFSET();
- MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
-
MOTH_BEGIN_INSTR(UNot)
MOTH_END_INSTR(UNot)
@@ -597,6 +652,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << "acc, " << rhs;
MOTH_END_INSTR(ShlConst)
+ MOTH_BEGIN_INSTR(Exp)
+ d << dumpRegister(lhs, nFormals) << ", acc";
+ MOTH_END_INSTR(Exp)
+
MOTH_BEGIN_INSTR(Mul)
d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(Mul)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index df9182e924..ce92a31590 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -53,6 +53,8 @@
#include <private/qv4global_p.h>
#include <private/qv4value_p.h>
#include <private/qv4runtime_p.h>
+#include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper
+#include <qendian.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +62,7 @@ QT_BEGIN_NAMESPACE
op##_INSTRUCTION(name, nargs, __VA_ARGS__)
/* for all jump instructions, the offset has to come last, to simplify the job of the bytecode generator */
+#define INSTR_Nop(op) INSTRUCTION(op, Nop, 0)
#define INSTR_Ret(op) INSTRUCTION(op, Ret, 0)
#define INSTR_Debug(op) INSTRUCTION(op, Debug, 0)
#define INSTR_LoadConst(op) INSTRUCTION(op, LoadConst, 1, index)
@@ -84,19 +87,20 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index)
#define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name)
#define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name)
-#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 2, name, base)
-#define INSTR_LoadPropertyA(op) INSTRUCTION(op, LoadPropertyA, 1, name)
-#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 2, index, base)
-#define INSTR_GetLookupA(op) INSTRUCTION(op, GetLookupA, 1, index)
+#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name)
+#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index)
#define INSTR_LoadScopeObjectProperty(op) INSTRUCTION(op, LoadScopeObjectProperty, 3, propertyIndex, base, captureRequired)
#define INSTR_LoadContextObjectProperty(op) INSTRUCTION(op, LoadContextObjectProperty, 3, propertyIndex, base, captureRequired)
#define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base)
+#define INSTR_Yield(op) INSTRUCTION(op, Yield, 0)
+#define INSTR_Resume(op) INSTRUCTION(op, Resume, 1, offset)
#define INSTR_StoreProperty(op) INSTRUCTION(op, StoreProperty, 2, name, base)
#define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base)
+#define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property)
+#define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property)
#define INSTR_StoreScopeObjectProperty(op) INSTRUCTION(op, StoreScopeObjectProperty, 2, base, propertyIndex)
#define INSTR_StoreContextObjectProperty(op) INSTRUCTION(op, StoreContextObjectProperty, 2, base, propertyIndex)
-#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 2, base, index)
-#define INSTR_LoadElementA(op) INSTRUCTION(op, LoadElementA, 1, base)
+#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base)
#define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index)
#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv)
#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv)
@@ -107,32 +111,46 @@ QT_BEGIN_NAMESPACE
#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv)
#define INSTR_CallScopeObjectProperty(op) INSTRUCTION(op, CallScopeObjectProperty, 4, name, base, argc, argv)
#define INSTR_CallContextObjectProperty(op) INSTRUCTION(op, CallContextObjectProperty, 4, name, base, argc, argv)
-#define INSTR_SetExceptionHandler(op) INSTRUCTION(op, SetExceptionHandler, 1, offset)
+#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv)
+#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv)
+#define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv)
+#define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset)
+#define INSTR_UnwindDispatch(op) INSTRUCTION(op, UnwindDispatch, 0)
+#define INSTR_UnwindToLabel(op) INSTRUCTION(op, UnwindToLabel, 2, level, offset)
#define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0)
#define INSTR_GetException(op) INSTRUCTION(op, GetException, 0)
#define INSTR_SetException(op) INSTRUCTION(op, SetException, 0)
#define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0)
-#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, name, reg)
-#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 1, reg)
-#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 1, reg)
-#define INSTR_ForeachIteratorObject(op) INSTRUCTION(op, ForeachIteratorObject, 0)
-#define INSTR_ForeachNextPropertyName(op) INSTRUCTION(op, ForeachNextPropertyName, 0)
-#define INSTR_DeleteMember(op) INSTRUCTION(op, DeleteMember, 2, member, base)
-#define INSTR_DeleteSubscript(op) INSTRUCTION(op, DeleteSubscript, 2, base, index)
+#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, index, name)
+#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 0)
+#define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 1, index)
+#define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0)
+#define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index)
+#define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0)
+#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 0)
+#define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator)
+#define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 1, value)
+#define INSTR_IteratorClose(op) INSTRUCTION(op, IteratorClose, 1, done)
+#define INSTR_DestructureRestElement(op) INSTRUCTION(op, DestructureRestElement, 0)
+#define INSTR_DeleteProperty(op) INSTRUCTION(op, DeleteProperty, 2, base, index)
#define INSTR_DeleteName(op) INSTRUCTION(op, DeleteName, 1, name)
#define INSTR_TypeofName(op) INSTRUCTION(op, TypeofName, 1, name)
#define INSTR_TypeofValue(op) INSTRUCTION(op, TypeofValue, 0)
#define INSTR_DeclareVar(op) INSTRUCTION(op, DeclareVar, 2, varName, isDeletable)
#define INSTR_DefineArray(op) INSTRUCTION(op, DefineArray, 2, argc, args)
-// arrayGetterSetterCountAndFlags contains 30 bits for count, 1 bit for needsSparseArray boolean
-#define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 4, internalClassId, arrayValueCount, arrayGetterSetterCountAndFlags, args)
+#define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 3, internalClassId, argc, args)
+#define INSTR_CreateClass(op) INSTRUCTION(op, CreateClass, 3, classIndex, heritage, computedNames)
#define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0)
#define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0)
+#define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex)
#define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0)
-#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv)
+#define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0)
+#define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0)
#define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset)
#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset)
#define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset)
+#define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset)
+#define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset)
#define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0)
#define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0)
#define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs)
@@ -147,8 +165,6 @@ QT_BEGIN_NAMESPACE
#define INSTR_CmpStrictNotEqual(op) INSTRUCTION(op, CmpStrictNotEqual, 1, lhs)
#define INSTR_CmpIn(op) INSTRUCTION(op, CmpIn, 1, lhs)
#define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs)
-#define INSTR_JumpStrictEqualStackSlotInt(op) INSTRUCTION(op, JumpStrictEqualStackSlotInt, 3, lhs, rhs, offset)
-#define INSTR_JumpStrictNotEqualStackSlotInt(op) INSTRUCTION(op, JumpStrictNotEqualStackSlotInt, 3, lhs, rhs, offset)
#define INSTR_UNot(op) INSTRUCTION(op, UNot, 0)
#define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0)
#define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0)
@@ -168,6 +184,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_UShrConst(op) INSTRUCTION(op, UShrConst, 1, rhs)
#define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs)
#define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs)
+#define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs)
#define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs)
#define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs)
#define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs)
@@ -175,10 +192,12 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result)
#define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result)
+#define FOR_EACH_MOTH_INSTR_ALL(F) \
+ F(Nop) \
+ FOR_EACH_MOTH_INSTR(F)
#define FOR_EACH_MOTH_INSTR(F) \
F(Ret) \
- F(Debug) \
F(LoadConst) \
F(LoadZero) \
F(LoadTrue) \
@@ -186,6 +205,7 @@ QT_BEGIN_NAMESPACE
F(LoadNull) \
F(LoadUndefined) \
F(LoadInt) \
+ F(LoadRuntimeString) \
F(MoveConst) \
F(LoadReg) \
F(StoreReg) \
@@ -194,7 +214,6 @@ QT_BEGIN_NAMESPACE
F(StoreLocal) \
F(LoadScopedLocal) \
F(StoreScopedLocal) \
- F(LoadRuntimeString) \
F(MoveRegExp) \
F(LoadClosure) \
F(LoadName) \
@@ -202,53 +221,25 @@ QT_BEGIN_NAMESPACE
F(StoreNameSloppy) \
F(StoreNameStrict) \
F(LoadElement) \
- F(LoadElementA) \
F(StoreElement) \
F(LoadProperty) \
- F(LoadPropertyA) \
F(GetLookup) \
- F(GetLookupA) \
F(StoreProperty) \
F(SetLookup) \
+ F(LoadSuperProperty) \
+ F(StoreSuperProperty) \
F(StoreScopeObjectProperty) \
F(StoreContextObjectProperty) \
F(LoadScopeObjectProperty) \
F(LoadContextObjectProperty) \
F(LoadIdObject) \
- F(CallValue) \
- F(CallProperty) \
- F(CallPropertyLookup) \
- F(CallElement) \
- F(CallName) \
- F(CallPossiblyDirectEval) \
- F(CallGlobalLookup) \
- F(CallScopeObjectProperty) \
- F(CallContextObjectProperty) \
- F(SetExceptionHandler) \
- F(ThrowException) \
- F(GetException) \
- F(SetException) \
- F(CreateCallContext) \
- F(PushCatchContext) \
- F(PushWithContext) \
- F(PopContext) \
- F(ForeachIteratorObject) \
- F(ForeachNextPropertyName) \
- F(DeleteMember) \
- F(DeleteSubscript) \
- F(DeleteName) \
- F(TypeofName) \
- F(TypeofValue) \
- F(DeclareVar) \
- F(DefineArray) \
- F(DefineObjectLiteral) \
- F(CreateMappedArgumentsObject) \
- F(CreateUnmappedArgumentsObject) \
F(ConvertThisToObject) \
- F(Construct) \
+ F(ToObject) \
F(Jump) \
F(JumpTrue) \
F(JumpFalse) \
+ F(JumpNoException) \
+ F(JumpNotUndefined) \
F(CmpEqNull) \
F(CmpNeNull) \
F(CmpEqInt) \
@@ -263,8 +254,6 @@ QT_BEGIN_NAMESPACE
F(CmpStrictNotEqual) \
F(CmpIn) \
F(CmpInstanceOf) \
- F(JumpStrictEqualStackSlotInt) \
- F(JumpStrictNotEqualStackSlotInt) \
F(UNot) \
F(UPlus) \
F(UMinus) \
@@ -284,13 +273,60 @@ QT_BEGIN_NAMESPACE
F(UShrConst) \
F(ShrConst) \
F(ShlConst) \
+ F(Exp) \
F(Mul) \
F(Div) \
F(Mod) \
F(Sub) \
+ F(CallValue) \
+ F(CallProperty) \
+ F(CallPropertyLookup) \
+ F(CallElement) \
+ F(CallName) \
+ F(CallPossiblyDirectEval) \
+ F(CallGlobalLookup) \
+ F(CallScopeObjectProperty) \
+ F(CallContextObjectProperty) \
+ F(CallWithSpread) \
+ F(Construct) \
+ F(ConstructWithSpread) \
+ F(SetUnwindHandler) \
+ F(UnwindDispatch) \
+ F(UnwindToLabel) \
+ F(ThrowException) \
+ F(GetException) \
+ F(SetException) \
+ F(CreateCallContext) \
+ F(PushCatchContext) \
+ F(PushWithContext) \
+ F(PushBlockContext) \
+ F(CloneBlockContext) \
+ F(PopContext) \
+ F(GetIterator) \
+ F(IteratorNext) \
+ F(IteratorClose) \
+ F(DestructureRestElement) \
+ F(DeleteProperty) \
+ F(DeleteName) \
+ F(TypeofName) \
+ F(TypeofValue) \
+ F(DeclareVar) \
+ F(DefineArray) \
+ F(DefineObjectLiteral) \
+ F(CreateMappedArgumentsObject) \
+ F(CreateUnmappedArgumentsObject) \
+ F(CreateRestParameter) \
F(LoadQmlContext) \
- F(LoadQmlImportedScripts)
-#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::LoadQmlImportedScripts) + 1)
+ F(LoadQmlImportedScripts) \
+ F(Yield) \
+ F(Resume) \
+ F(CreateClass) \
+ F(LoadSuperConstructor) \
+ F(PushScriptContext) \
+ F(PopScriptContext) \
+ F(Debug) \
+
+#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::Debug_Wide) + 1)
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
// icc before version 1200 doesn't support computed goto, and at least up to version 18.0.0 the
@@ -301,7 +337,7 @@ QT_BEGIN_NAMESPACE
#define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1)
-#define MOTH_INSTR_ENUM(I) I,
+#define MOTH_INSTR_ENUM(I) I, I##_Wide,
#define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I))
#define MOTH_EXPAND_FOR_MSVC(x) x
@@ -344,7 +380,7 @@ QT_BEGIN_NAMESPACE
#define MOTH_COLLECT_NARGS(instr) \
INSTR_##instr(MOTH_COLLECT_ARG_COUNT)
#define MOTH_COLLECT_ARG_COUNT_INSTRUCTION(name, nargs, ...) \
- nargs,
+ nargs, nargs,
#define MOTH_DECODE_ARG(arg, type, nargs, offset) \
arg = qFromLittleEndian<type>(qFromUnaligned<type>(reinterpret_cast<const type *>(code) - nargs + offset));
@@ -397,38 +433,53 @@ QT_BEGIN_NAMESPACE
#ifdef MOTH_COMPUTED_GOTO
/* collect jump labels */
#define COLLECT_LABELS(instr) \
- INSTR_##instr(GET_LABEL)
+ INSTR_##instr(GET_LABEL) \
+ INSTR_##instr(GET_LABEL_WIDE)
#define GET_LABEL_INSTRUCTION(name, ...) \
&&op_byte_##name,
-#define COLLECT_LABELS_WIDE(instr) \
- INSTR_##instr(GET_LABEL_WIDE)
#define GET_LABEL_WIDE_INSTRUCTION(name, ...) \
&&op_int_##name,
#define MOTH_JUMP_TABLE \
static const void *jumpTable[] = { \
- FOR_EACH_MOTH_INSTR(COLLECT_LABELS) \
- FOR_EACH_MOTH_INSTR(COLLECT_LABELS_WIDE) \
+ FOR_EACH_MOTH_INSTR_ALL(COLLECT_LABELS) \
};
-#define MOTH_DISPATCH() \
+#define MOTH_DISPATCH_SINGLE() \
goto *jumpTable[*reinterpret_cast<const uchar *>(code)];
+
+#define MOTH_DISPATCH() \
+ MOTH_DISPATCH_SINGLE() \
+ op_byte_Nop: \
+ ++code; \
+ MOTH_DISPATCH_SINGLE() \
+ op_int_Nop: /* wide prefix */ \
+ ++code; \
+ goto *jumpTable[0x100 | *reinterpret_cast<const uchar *>(code)];
#else
#define MOTH_JUMP_TABLE
#define MOTH_INSTR_CASE_AND_JUMP(instr) \
- INSTR_##instr(GET_CASE_AND_JUMP)
-#define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \
- case static_cast<uchar>(Instr::Type::name): goto op_byte_##name;
-#define MOTH_INSTR_CASE_AND_JUMP_WIDE(instr) \
+ INSTR_##instr(GET_CASE_AND_JUMP) \
INSTR_##instr(GET_CASE_AND_JUMP_WIDE)
+#define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \
+ case Instr::Type::name: goto op_byte_##name;
#define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \
- case (static_cast<uchar>(Instr::Type::name) + MOTH_NUM_INSTRUCTIONS()): goto op_int_##name;
+ case Instr::Type::name##_Wide: goto op_int_##name;
#define MOTH_DISPATCH() \
- switch (static_cast<uchar>(*code)) { \
+ Instr::Type type = Instr::Type(static_cast<uchar>(*code)); \
+ dispatch: \
+ switch (type) { \
+ case Instr::Type::Nop: \
+ ++code; \
+ type = Instr::Type(static_cast<uchar>(*code)); \
+ goto dispatch; \
+ case Instr::Type::Nop_Wide: /* wide prefix */ \
+ ++code; \
+ type = Instr::Type(0x100 | static_cast<uchar>(*code)); \
+ goto dispatch; \
FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP) \
- FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP_WIDE) \
}
#endif
@@ -471,12 +522,29 @@ inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals,
union Instr
{
enum class Type {
- FOR_EACH_MOTH_INSTR(MOTH_INSTR_ENUM)
+ FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_ENUM)
};
- FOR_EACH_MOTH_INSTR(MOTH_EMIT_STRUCTS)
+ static Type wideInstructionType(Type t) { return Type(int(t) | 1); }
+ static Type narrowInstructionType(Type t) { return Type(int(t) & ~1); }
+ static bool isWide(Type t) { return int(t) & 1; }
+ static bool isNarrow(Type t) { return !(int(t) & 1); }
+ static int encodedLength(Type t) { return int(t) >= 256 ? 2 : 1; }
+
+ static Type unpack(const uchar *c) { if (c[0] == 0x1) return Type(0x100 + c[1]); return Type(c[0]); }
+ static uchar *pack(uchar *c, Type t) {
+ if (uint(t) >= 256) {
+ c[0] = 0x1;
+ c[1] = uint(t) &0xff;
+ return c + 2;
+ }
+ c[0] = uchar(uint(t));
+ return c + 1;
+ }
+
+ FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_STRUCTS)
- FOR_EACH_MOTH_INSTR(MOTH_EMIT_INSTR_MEMBERS)
+ FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_INSTR_MEMBERS)
int argumentsAsInts[4];
};
@@ -487,8 +555,6 @@ struct InstrInfo
static int size(Instr::Type type);
};
-Q_STATIC_ASSERT(MOTH_NUM_INSTRUCTIONS() < 128);
-
template<int N>
struct InstrMeta {
};
@@ -506,7 +572,7 @@ QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
reinterpret_cast<const char *>(&v), \
Size); } \
};
-FOR_EACH_MOTH_INSTR(MOTH_INSTR_META_TEMPLATE);
+FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_META_TEMPLATE);
#undef MOTH_INSTR_META_TEMPLATE
QT_WARNING_POP
@@ -517,7 +583,7 @@ class InstrData : public InstrMeta<InstrType>::DataType
struct Instruction {
#define MOTH_INSTR_DATA_TYPEDEF(I) typedef InstrData<int(Instr::Type::I)> I;
-FOR_EACH_MOTH_INSTR(MOTH_INSTR_DATA_TYPEDEF)
+FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_DATA_TYPEDEF)
#undef MOTH_INSTR_DATA_TYPEDEF
private:
Instruction();
diff --git a/src/qml/configure.json b/src/qml/configure.json
index 681cecea99..481cc553ae 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -40,6 +40,59 @@
],
"output": [ "privateFeature" ]
},
+ "qml-preview": {
+ "label": "Command line QML Preview tool",
+ "purpose": "Updates QML documents in your application live as you change them on disk",
+ "section": "QML",
+ "condition": [
+ "features.commandlineparser",
+ "features.localserver",
+ "features.process",
+ "features.qml-debug"
+ ],
+ "output": [ "privateFeature" ]
+ },
+ "qml-devtools": {
+ "label": "QML Development Tools",
+ "purpose": "Provides the QmlDevtools library and various utilities.",
+ "section": "QML",
+ "output": [ "privateFeature" ]
+ },
+ "qml-sequence-object": {
+ "label": "QML sequence object",
+ "purpose": "Supports mapping sequence types into QML.",
+ "section": "QML",
+ "output": [ "privateFeature" ]
+ },
+ "qml-list-model": {
+ "label": "QML list model",
+ "purpose": "Provides the ListModel QML type.",
+ "section": "QML",
+ "output": [ "privateFeature" ]
+ },
+ "qml-xml-http-request": {
+ "label": "QML XML http request",
+ "purpose": "Provides support for sending XML http requests.",
+ "section": "QML",
+ "condition": [
+ "features.xmlstreamreader",
+ "features.qml-network"
+ ],
+ "output": [ "privateFeature" ]
+ },
+ "qml-locale": {
+ "label": "QML Locale",
+ "purpose": "Provides support for locales in QML.",
+ "section": "QML",
+ "output": [ "privateFeature" ]
+ },
+ "qml-animation": {
+ "label": "QML Animations",
+ "purpose": "Provides support for animations and timers in QML.",
+ "section": "QML",
+ "condition": "features.animation",
+ "output": [ "privateFeature" ]
+ },
"qml-delegate-model": {
"label": "QML delegate model",
"purpose": "Provides the DelegateModel QML type.",
@@ -54,6 +107,10 @@
"entries": [
"qml-network",
"qml-debug",
+ "qml-sequence-object",
+ "qml-list-model",
+ "qml-xml-http-request",
+ "qml-locale",
"qml-delegate-model"
]
}
diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index c63e694c7e..f39f8fccd2 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -73,13 +73,13 @@ public:
~QQmlAbstractProfilerAdapter() override {}
void setService(QQmlProfilerService *new_service) { service = new_service; }
- virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) = 0;
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
void startProfiling(quint64 features);
void stopProfiling();
- void reportData(bool trackLocations) { emit dataRequested(trackLocations); }
+ void reportData() { emit dataRequested(); }
void stopWaiting() { waiting = false; }
void startWaiting() { waiting = true; }
@@ -96,7 +96,7 @@ signals:
void profilingDisabled();
void profilingDisabledWhileWaiting();
- void dataRequested(bool trackLocations);
+ void dataRequested();
void referenceTimeKnown(const QElapsedTimer &timer);
protected:
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
index d9f51ce09f..0ef40d6911 100644
--- a/src/qml/debugger/qqmldebugconnector.cpp
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -82,7 +82,7 @@ Q_GLOBAL_STATIC(QQmlDebugConnectorParams, qmlDebugConnectorParams)
void QQmlDebugConnector::setPluginKey(const QString &key)
{
QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
- if (params) {
+ if (params && params->pluginKey != key) {
if (params->instance)
qWarning() << "QML debugger: Cannot set plugin key after loading the plugin.";
else
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index 8c0bd73822..da0b14dd85 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -59,19 +59,18 @@ void QQmlProfiler::startProfiling(quint64 features)
void QQmlProfiler::stopProfiling()
{
featuresEnabled = false;
- reportData(true);
+ reportData();
m_locations.clear();
}
-void QQmlProfiler::reportData(bool trackLocations)
+void QQmlProfiler::reportData()
{
LocationHash resolved;
resolved.reserve(m_locations.size());
for (auto it = m_locations.begin(), end = m_locations.end(); it != end; ++it) {
- if (!trackLocations || !it->sent) {
+ if (!it->sent) {
resolved.insert(it.key(), it.value());
- if (trackLocations)
- it->sent = true;
+ it->sent = true;
}
}
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 287c53ea05..d01e2bc429 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -383,7 +383,7 @@ public:
void startProfiling(quint64 features);
void stopProfiling();
- void reportData(bool trackLocations);
+ void reportData();
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 8a606d672a..7fb4724f73 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -262,8 +262,8 @@ method.
\section2 Sequence Type to JavaScript Array
-Certain C++ sequence types are supported transparently in QML as JavaScript
-\c Array types.
+Certain C++ sequence types are supported transparently in QML to behave like
+JavaScript \c Array types.
In particular, QML currently supports:
\list
diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
index aefdfd9401..52534b4a62 100644
--- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
+++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
@@ -255,9 +255,6 @@ type, and so cannot provide the necessary QML property characteristics
through the Qt meta object system, such as signal notifications when a list
is modified.
-QQmlListProperty is a template class that can be conveniently constructed from
-a QList value.
-
For example, the \c MessageBoard class below has a \c messages property of
type QQmlListProperty that stores a list of \c Message instances:
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index 55ca040af6..62c0f5d81b 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -538,30 +538,6 @@
}
\endqml
- Since singleton types do not have an associated QQmlContext object, then within the functions of a QObject-derived
- type that is registered as a singleton type implementation the QML context and engine information is not available.
- The QQmlEngine::contextForObject() function returns NULL when supplied with a pointer to an QObject that
- implements a singleton type.
-
- Extending the above example:
-
- \code
- class SingletonTypeExample : public QObject
- {
- ...
-
- Q_INVOKABLE void doSomethingElse()
- {
- // QML Engine/Context information is not accessible here:
- Q_ASSERT(QQmlEngine::contextForObject(this) == 0);
- Q_ASSERT(qmlContext(this) == 0);
- Q_ASSERT(qmlEngine(this) == 0);
- }
-
- ...
- }
- \endcode
-
\sa {Choosing the Correct Integration Method Between C++ and QML}
*/
@@ -662,3 +638,25 @@
are registered for that version. This is particularly useful for keeping the
versions of related modules in sync.
*/
+
+/*!
+ \since 5.12
+ \fn int qmlTypeId(const char* uri, int versionMajor, int versionMinor, const char *qmlName);
+ \relates QQmlEngine
+
+ Returns the QML type id of a type that was registered with the
+ name \a qmlName in a particular \a uri and a version specified in \a
+ versionMajor and \a versionMinor.
+
+ This function returns the same value as the QML type registration functions
+ such as qmlRegisterType() and qmlRegisterSingletonType().
+
+ If \a qmlName, \a uri and \a versionMajor match a registered type, but the
+ specified minor version in \a versionMinor is higher, then the id of the type
+ with the closest minor version is returned.
+
+ Returns -1 if no matching type was found or one of the given parameters
+ was invalid.
+
+ \sa qmlRegisterType(), qmlRegisterSingletonType()
+*/
diff --git a/src/qml/jit/jit.pri b/src/qml/jit/jit.pri
index 2080844d93..9e3cf44387 100644
--- a/src/qml/jit/jit.pri
+++ b/src/qml/jit/jit.pri
@@ -2,9 +2,11 @@ INCLUDEPATH += $$PWD
INCLUDEPATH += $$OUT_PWD
SOURCES += \
- $$PWD/qv4jit.cpp \
+ $$PWD/qv4jithelpers.cpp \
+ $$PWD/qv4baselinejit.cpp \
$$PWD/qv4assembler.cpp
HEADERS += \
- $$PWD/qv4jit_p.h \
+ $$PWD/qv4jithelpers_p.h \
+ $$PWD/qv4baselinejit_p.h \
$$PWD/qv4assembler_p.h
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 9786293e4c..7d668950d7 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -44,6 +44,7 @@
#include "qv4assembler_p.h"
#include <private/qv4function_p.h>
#include <private/qv4runtime_p.h>
+#include <private/qv4stackframe_p.h>
#include <wtf/Vector.h>
#include <assembler/MacroAssembler.h>
@@ -680,6 +681,12 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
store64(AccumulatorRegister, addr);
}
+ void moveReg(Address sourceRegAddress, Address destRegAddress)
+ {
+ load64(sourceRegAddress, ScratchRegister);
+ store64(ScratchRegister, destRegAddress);
+ }
+
void loadString(int stringId)
{
loadAccumulator(loadStringAddress(stringId));
@@ -700,6 +707,17 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();});
}
+ void jumpNotUndefined(int offset)
+ {
+ auto jump = branch64(NotEqual, AccumulatorRegister, TrustedImm64(0));
+ patches.push_back({ jump, offset });
+ }
+
+ Jump jumpEmpty()
+ {
+ return branch64(Equal, AccumulatorRegister, TrustedImm64(Primitive::emptyValue().asReturnedValue()));
+ }
+
void toBoolean(std::function<void(RegisterID)> continuation)
{
urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister);
@@ -803,26 +821,6 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
return branch32(Equal, TrustedImm32(3), ScratchRegister);
}
- void jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset)
- {
- Address lhsAddr(JSStackFrameRegister, lhs * int(sizeof(Value)));
- load64(lhsAddr, ScratchRegister);
- Jump isUndef = branch64(Equal, ScratchRegister, TrustedImm64(0));
- Jump equal = branch32(Equal, TrustedImm32(rhs), ScratchRegister);
- patches.push_back({ equal, offset });
- isUndef.link(this);
- }
-
- void jumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset)
- {
- Address lhsAddr(JSStackFrameRegister, lhs * int(sizeof(Value)));
- load64(lhsAddr, ScratchRegister);
- Jump isUndef = branch64(Equal, ScratchRegister, TrustedImm64(0));
- patches.push_back({ isUndef, offset });
- Jump notEqual = branch32(NotEqual, TrustedImm32(rhs), ScratchRegister);
- patches.push_back({ notEqual, offset });
- }
-
void setAccumulatorTag(QV4::Value::ValueTypeInternal tag, RegisterID sourceReg = NoRegister)
{
if (sourceReg == NoRegister)
@@ -960,6 +958,16 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
store32(AccumulatorRegisterTag, addr);
}
+ void moveReg(Address sourceRegAddress, Address destRegAddress)
+ {
+ load32(sourceRegAddress, ReturnValueRegisterValue);
+ sourceRegAddress.offset += 4;
+ load32(sourceRegAddress, ReturnValueRegisterTag);
+ store32(ReturnValueRegisterValue, destRegAddress);
+ destRegAddress.offset += 4;
+ store32(ReturnValueRegisterTag, destRegAddress);
+ }
+
void loadString(int stringId)
{
load32(loadStringAddress(stringId), AccumulatorRegisterValue);
@@ -1135,6 +1143,19 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
push(TrustedImm32(v));
}
+ void jumpNotUndefined(int offset)
+ {
+ move(AccumulatorRegisterTag, ScratchRegister);
+ or32(AccumulatorRegisterValue, ScratchRegister);
+ auto jump = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
+ patches.push_back({ jump, offset });
+ }
+
+ Jump jumpEmpty()
+ {
+ return branch32(Equal, AccumulatorRegisterTag, TrustedImm32(Primitive::emptyValue().asReturnedValue() >> 32));
+ }
+
void toBoolean(std::function<void(RegisterID)> continuation)
{
urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerConvertible_Shift - 32),
@@ -1174,34 +1195,6 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
done.link(this);
}
- void jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset)
- {
- Address lhsAddr(JSStackFrameRegister, lhs * int(sizeof(Value)));
- load32(lhsAddr, ScratchRegister);
- Jump notEqInt = branch32(NotEqual, ScratchRegister, TrustedImm32(rhs));
- Jump notEqUndefVal = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
- patches.push_back({ notEqUndefVal, offset });
- lhsAddr.offset += 4;
- load32(lhsAddr, ScratchRegister);
- Jump notEqUndefTag = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
- patches.push_back({ notEqUndefTag, offset });
- notEqInt.link(this);
- }
-
- void jumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset)
- {
- Address lhsAddr(JSStackFrameRegister, lhs * int(sizeof(Value)));
- load32(lhsAddr, ScratchRegister);
- Jump notEqual = branch32(NotEqual, TrustedImm32(rhs), ScratchRegister);
- patches.push_back({ notEqual, offset });
- Jump notUndefValue = branch32(NotEqual, TrustedImm32(0), ScratchRegister);
- lhsAddr.offset += 4;
- load32(lhsAddr, ScratchRegister);
- Jump equalUndef = branch32(Equal, TrustedImm32(0), ScratchRegister);
- patches.push_back({ equalUndef, offset });
- notUndefValue.link(this);
- }
-
void setAccumulatorTag(QV4::Value::ValueTypeInternal tag, RegisterID sourceReg = NoRegister)
{
if (sourceReg != NoRegister)
@@ -1415,7 +1408,6 @@ void Assembler::link(Function *function)
function->codeRef = new JSC::MacroAssemblerCodeRef(codeRef);
function->jittedCode = reinterpret_cast<Function::JittedCode>(function->codeRef->code().executableAddress());
-#if defined(Q_OS_LINUX)
// This implements writing of JIT'd addresses so that perf can find the
// symbol names.
//
@@ -1423,7 +1415,7 @@ void Assembler::link(Function *function)
// content, for more information, see:
// https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
- if (doProfile) {
+ if (Q_UNLIKELY(doProfile)) {
static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map")
.arg(QCoreApplication::applicationPid()));
static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly);
@@ -1441,7 +1433,6 @@ void Assembler::link(Function *function)
perfMapFile.flush();
}
}
-#endif
}
void Assembler::addLabel(int offset)
@@ -1469,6 +1460,11 @@ void Assembler::loadReg(int reg)
pasm()->loadAccumulator(regAddr(reg));
}
+void JIT::Assembler::moveReg(int sourceReg, int destReg)
+{
+ pasm()->moveReg(regAddr(sourceReg), regAddr(destReg));
+}
+
void Assembler::storeReg(int reg)
{
pasm()->storeAccumulator(regAddr(reg));
@@ -1981,14 +1977,19 @@ void Assembler::jumpFalse(int offset)
});
}
-void Assembler::jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset)
+void Assembler::jumpNoException(int offset)
{
- pasm()->jumpStrictEqualStackSlotInt(lhs, rhs, offset);
+ auto jump = pasm()->branch32(
+ PlatformAssembler::Equal,
+ PlatformAssembler::Address(PlatformAssembler::EngineRegister,
+ offsetof(EngineBase, hasException)),
+ TrustedImm32(0));
+ pasm()->patches.push_back({ jump, offset });
}
-void Assembler::jumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset)
+void Assembler::jumpNotUndefined(int offset)
{
- pasm()->jumpStrictNotEqualStackSlotInt(lhs, rhs, offset);
+ pasm()->jumpNotUndefined(offset);
}
void Assembler::prepareCallWithArgCount(int argc)
@@ -2182,39 +2183,70 @@ void Assembler::getException()
void Assembler::setException()
{
+ auto noException = pasm()->jumpEmpty();
Address addr(PlatformAssembler::EngineRegister, offsetof(EngineBase, exceptionValue));
pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister);
pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister));
addr.offset = offsetof(EngineBase, hasException);
Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1);
pasm()->store8(TrustedImm32(1), addr);
+ noException.link(pasm());
}
-void Assembler::setExceptionHandler(int offset)
+void Assembler::setUnwindHandler(int offset)
{
auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress());
pasm()->ehTargets.push_back({ l, offset });
}
-void Assembler::clearExceptionHandler()
+void Assembler::clearUnwindHandler()
{
pasm()->storePtr(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress());
}
-void Assembler::pushCatchContext(int name, int reg)
+void JIT::Assembler::unwindDispatch()
{
- pasm()->copyReg(pasm()->contextAddress(), regAddr(reg));
- prepareCallWithArgCount(2);
- passInt32AsArg(name, 1);
+ checkException();
+ pasm()->load32(Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)), PlatformAssembler::ScratchRegister);
+ auto noUnwind = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
+ pasm()->sub32(TrustedImm32(1), PlatformAssembler::ScratchRegister);
+ pasm()->store32(PlatformAssembler::ScratchRegister, Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)));
+ auto jump = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
+ gotoCatchException();
+ jump.link(pasm());
+
+ pasm()->loadPtr(Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel)), PlatformAssembler::ScratchRegister);
+ pasm()->jump(PlatformAssembler::ScratchRegister);
+
+ noUnwind.link(pasm());
+}
+
+void JIT::Assembler::unwindToLabel(int level, int offset)
+{
+ auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel)));
+ pasm()->ehTargets.push_back({ l, offset });
+ pasm()->store32(TrustedImm32(level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)));
+ gotoCatchException();
+}
+
+void Assembler::pushCatchContext(int index, int name)
+{
+ prepareCallWithArgCount(3);
+ passInt32AsArg(name, 2);
+ passInt32AsArg(index, 1);
passRegAsArg(CallData::Context, 0);
IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_createCatchContext, ResultInAccumulator);
pasm()->storeAccumulator(pasm()->contextAddress());
}
-void Assembler::popContext(int reg)
+void Assembler::popContext()
{
- pasm()->copyReg(regAddr(reg), pasm()->contextAddress());
+ Heap::CallContext ctx;
+ Q_UNUSED(ctx)
+ pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
+ pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset));
+ pasm()->storeAccumulator(regAddr(CallData::Context));
}
void Assembler::ret()
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 37d4232a17..2cf59f53ee 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -90,6 +90,7 @@ public:
void loadConst(int constIndex);
void copyConst(int constIndex, int destReg);
void loadReg(int reg);
+ void moveReg(int sourceReg, int destReg);
void storeReg(int reg);
void loadLocal(int index, int level = 0);
void storeLocal(int index, int level = 0);
@@ -140,8 +141,8 @@ public:
void jump(int offset);
void jumpTrue(int offset);
void jumpFalse(int offset);
- void jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset);
- void jumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset);
+ void jumpNoException(int offset);
+ void jumpNotUndefined(int offset);
// stuff for runtime calls
void prepareCallWithArgCount(int argc);
@@ -160,10 +161,12 @@ public:
void gotoCatchException();
void getException();
void setException();
- void setExceptionHandler(int offset);
- void clearExceptionHandler();
- void pushCatchContext(int name, int reg);
- void popContext(int reg);
+ void setUnwindHandler(int offset);
+ void clearUnwindHandler();
+ void unwindDispatch();
+ void unwindToLabel(int level, int offset);
+ void pushCatchContext(int index, int name);
+ void popContext();
// other stuff
void ret();
diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4baselinejit.cpp
index bc46c0ca1d..9132b194a5 100644
--- a/src/qml/jit/qv4jit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -37,9 +37,11 @@
**
****************************************************************************/
-#include "qv4jit_p.h"
+#include "qv4baselinejit_p.h"
+#include "qv4jithelpers_p.h"
#include "qv4assembler_p.h"
#include <private/qv4lookup_p.h>
+#include <private/qv4generatorobject_p.h>
#ifdef V4_ENABLE_JIT
@@ -48,42 +50,6 @@ using namespace QV4;
using namespace QV4::JIT;
using namespace QV4::Moth;
-ByteCodeHandler::~ByteCodeHandler()
-{
-}
-
-#define DISPATCH_INSTRUCTION(name, nargs, ...) \
- generate_##name( \
- __VA_ARGS__ \
- );
-
-#define DECODE_AND_DISPATCH(instr) \
- { \
- INSTR_##instr(MOTH_DECODE_WITH_BASE) \
- Q_UNUSED(base_ptr); \
- startInstruction(Instr::Type::instr); \
- _offset = code - start; \
- INSTR_##instr(DISPATCH) \
- endInstruction(Instr::Type::instr); \
- continue; \
- }
-
-void ByteCodeHandler::decode(const char *code, uint len)
-{
- MOTH_JUMP_TABLE;
-
- const char *start = code;
- const char *end = code + len;
- while (code < end) {
- MOTH_DISPATCH()
-
- FOR_EACH_MOTH_INSTR(DECODE_AND_DISPATCH)
- }
-}
-
-#undef DECODE_AND_DISPATCH
-#undef DISPATCH_INSTRUCTION
-
BaselineJIT::BaselineJIT(Function *function)
: function(function)
, as(new Assembler(function->compilationUnit->constants))
@@ -95,10 +61,12 @@ BaselineJIT::~BaselineJIT()
void BaselineJIT::generate()
{
// qDebug()<<"jitting" << function->name()->toQString();
- collectLabelsInBytecode();
+ const char *code = function->codeData;
+ uint len = function->compiledFunction->codeSize;
+ labels = collectLabelsInBytecode(code, len);
as->generatePrologue();
- decode(reinterpret_cast<const char *>(function->codeData), function->compiledFunction->codeSize);
+ decode(code, len);
as->generateEpilogue();
as->link(function);
@@ -168,8 +136,8 @@ void BaselineJIT::generate_StoreReg(int reg)
void BaselineJIT::generate_MoveReg(int srcReg, int destReg)
{
- as->loadReg(srcReg);
- as->storeReg(destReg);
+ // Don't clobber the accumulator.
+ as->moveReg(srcReg, destReg);
}
void BaselineJIT::generate_LoadLocal(int index)
@@ -226,19 +194,13 @@ void BaselineJIT::generate_LoadName(int name)
as->checkException();
}
-static ReturnedValue loadGlobalLookupHelper(ExecutionEngine *engine, QV4::Function *f, int index)
-{
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
- return l->globalGetter(l, engine);
-}
-
void BaselineJIT::generate_LoadGlobalLookup(int index)
{
as->prepareCallWithArgCount(3);
as->passInt32AsArg(index, 2);
as->passFunctionAsArg(1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(loadGlobalLookupHelper, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::loadGlobalLookup, Assembler::ResultInAccumulator);
as->checkException();
}
@@ -266,18 +228,7 @@ void BaselineJIT::generate_StoreNameStrict(int name)
as->checkException();
}
-void BaselineJIT::generate_LoadElement(int base, int index)
-{
- STORE_IP();
- as->prepareCallWithArgCount(3);
- as->passRegAsArg(index, 2);
- as->passRegAsArg(base, 1);
- as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, Assembler::ResultInAccumulator);
- as->checkException();
-}
-
-void BaselineJIT::generate_LoadElementA(int base)
+void BaselineJIT::generate_LoadElement(int base)
{
STORE_IP();
STORE_ACC();
@@ -289,13 +240,6 @@ void BaselineJIT::generate_LoadElementA(int base)
as->checkException();
}
-static void storeElementHelper(QV4::Function *f, const Value &base, const Value &index, const Value &value)
-{
- auto engine = f->internalClass->engine;
- if (!Runtime::method_storeElement(engine, base, index, value) && f->isStrict())
- engine->throwTypeError();
-}
-
void BaselineJIT::generate_StoreElement(int base, int index)
{
STORE_IP();
@@ -304,22 +248,12 @@ void BaselineJIT::generate_StoreElement(int base, int index)
as->passAccumulatorAsArg(3);
as->passRegAsArg(index, 2);
as->passRegAsArg(base, 1);
- as->passFunctionAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(storeElementHelper, Assembler::IgnoreResult);
- as->checkException();
-}
-
-void BaselineJIT::generate_LoadProperty(int name, int base)
-{
- STORE_IP();
- as->prepareCallWithArgCount(3);
- as->passInt32AsArg(name, 2);
- as->passRegAsArg(base, 1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeElement, Assembler::IgnoreResult);
as->checkException();
}
-void BaselineJIT::generate_LoadPropertyA(int name)
+
+void BaselineJIT::generate_LoadProperty(int name)
{
STORE_IP();
STORE_ACC();
@@ -331,78 +265,69 @@ void BaselineJIT::generate_LoadPropertyA(int name)
as->checkException();
}
-static ReturnedValue getLookupHelper(ExecutionEngine *engine, QV4::Function *f, int index, const QV4::Value &base)
-{
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
- return l->getter(l, engine, base);
-}
-
-void BaselineJIT::generate_GetLookup(int index, int base)
+void BaselineJIT::generate_GetLookup(int index)
{
STORE_IP();
+ STORE_ACC();
as->prepareCallWithArgCount(4);
- as->passRegAsArg(base, 3);
+ as->passAccumulatorAsArg(3);
as->passInt32AsArg(index, 2);
as->passFunctionAsArg(1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(getLookupHelper, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::getLookup, Assembler::ResultInAccumulator);
as->checkException();
}
-void BaselineJIT::generate_GetLookupA(int index)
+void BaselineJIT::generate_StoreProperty(int name, int base)
{
STORE_IP();
STORE_ACC();
as->prepareCallWithArgCount(4);
as->passAccumulatorAsArg(3);
- as->passInt32AsArg(index, 2);
- as->passFunctionAsArg(1);
+ as->passInt32AsArg(name, 2);
+ as->passRegAsArg(base, 1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(getLookupHelper, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeProperty, Assembler::IgnoreResult);
as->checkException();
}
-static void storePropertyHelper(QV4::Function *f, const Value &base, int name, const Value &value)
-{
- auto engine = f->internalClass->engine;
- if (!Runtime::method_storeProperty(engine, base, name, value) && f->isStrict())
- engine->throwTypeError();
-}
-
-void BaselineJIT::generate_StoreProperty(int name, int base)
+void BaselineJIT::generate_SetLookup(int index, int base)
{
STORE_IP();
STORE_ACC();
as->prepareCallWithArgCount(4);
as->passAccumulatorAsArg(3);
- as->passInt32AsArg(name, 2);
- as->passRegAsArg(base, 1);
+ as->passRegAsArg(base, 2);
+ as->passInt32AsArg(index, 1);
as->passFunctionAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(storePropertyHelper, Assembler::IgnoreResult);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::setLookup, Assembler::ResultInAccumulator);
as->checkException();
}
-static void setLookupHelper(QV4::Function *f, int index, QV4::Value &base, const QV4::Value &value)
+void BaselineJIT::generate_LoadSuperProperty(int property)
{
- ExecutionEngine *engine = f->internalClass->engine;
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
- if (!l->setter(l, engine, base, value) && f->isStrict())
- engine->throwTypeError();
+ STORE_IP();
+ STORE_ACC();
+ as->prepareCallWithArgCount(2);
+ as->passRegAsArg(property, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadSuperProperty, Assembler::ResultInAccumulator);
+ as->checkException();
}
-void BaselineJIT::generate_SetLookup(int index, int base)
+void BaselineJIT::generate_StoreSuperProperty(int property)
{
STORE_IP();
STORE_ACC();
- as->prepareCallWithArgCount(4);
- as->passAccumulatorAsArg(3);
- as->passRegAsArg(base, 2);
- as->passInt32AsArg(index, 1);
+ as->prepareCallWithArgCount(3);
+ as->passAccumulatorAsArg(2);
+ as->passRegAsArg(property, 1);
as->passFunctionAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(setLookupHelper, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeSuperProperty, Assembler::IgnoreResult);
as->checkException();
}
+
void BaselineJIT::generate_StoreScopeObjectProperty(int base, int propertyIndex)
{
STORE_ACC();
@@ -462,6 +387,18 @@ void BaselineJIT::generate_LoadIdObject(int index, int base)
as->checkException();
}
+void BaselineJIT::generate_Yield()
+{
+ // #####
+ Q_UNREACHABLE();
+}
+
+void BaselineJIT::generate_Resume(int)
+{
+ // #####
+ Q_UNREACHABLE();
+}
+
void BaselineJIT::generate_CallValue(int name, int argc, int argv)
{
STORE_IP();
@@ -574,14 +511,68 @@ void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int
as->checkException();
}
-void BaselineJIT::generate_SetExceptionHandler(int offset)
+
+void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, int argv)
+{
+ STORE_IP();
+ as->prepareCallWithArgCount(5);
+ as->passInt32AsArg(argc, 4);
+ as->passRegAsArg(argv, 3);
+ as->passRegAsArg(thisObject, 2);
+ as->passRegAsArg(func, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_callWithSpread, Assembler::ResultInAccumulator);
+ as->checkException();
+}
+
+
+void BaselineJIT::generate_Construct(int func, int argc, int argv)
+{
+ STORE_IP();
+ STORE_ACC();
+ as->prepareCallWithArgCount(5);
+ as->passInt32AsArg(argc, 4);
+ as->passRegAsArg(argv, 3);
+ as->passAccumulatorAsArg(2);
+ as->passRegAsArg(func, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, Assembler::ResultInAccumulator);
+ as->checkException();
+}
+
+void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv)
+{
+ STORE_IP();
+ STORE_ACC();
+ as->prepareCallWithArgCount(5);
+ as->passInt32AsArg(argc, 4);
+ as->passRegAsArg(argv, 3);
+ as->passAccumulatorAsArg(2);
+ as->passRegAsArg(func, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_constructWithSpread, Assembler::ResultInAccumulator);
+ as->checkException();
+}
+
+void BaselineJIT::generate_SetUnwindHandler(int offset)
{
if (offset)
- as->setExceptionHandler(instructionOffset() + offset);
+ as->setUnwindHandler(instructionOffset() + offset);
else
- as->clearExceptionHandler();
+ as->clearUnwindHandler();
}
+void BaselineJIT::generate_UnwindDispatch()
+{
+ as->unwindDispatch();
+}
+
+void BaselineJIT::generate_UnwindToLabel(int level, int offset)
+{
+ as->unwindToLabel(level, instructionOffset() + offset);
+}
+
+
void BaselineJIT::generate_ThrowException()
{
STORE_IP();
@@ -604,118 +595,119 @@ void BaselineJIT::generate_CreateCallContext()
as->storeHeapObject(CallData::Context);
}
-void BaselineJIT::generate_PushCatchContext(int name, int reg) { as->pushCatchContext(name, reg); }
+void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); }
-static void pushWithContextHelper(ExecutionEngine *engine, QV4::Value *stack, int reg)
-{
- QV4::Value &accumulator = stack[CallData::Accumulator];
- accumulator = accumulator.toObject(engine);
- if (engine->hasException)
- return;
- stack[reg] = stack[CallData::Context];
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- stack[CallData::Context] = Runtime::method_createWithContext(c, accumulator);
-}
-
-void BaselineJIT::generate_PushWithContext(int reg)
+void BaselineJIT::generate_PushWithContext()
{
STORE_IP();
as->saveAccumulatorInFrame();
- as->prepareCallWithArgCount(3);
- as->passInt32AsArg(reg, 2);
+ as->prepareCallWithArgCount(2);
as->passRegAsArg(0, 1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(pushWithContextHelper, Assembler::IgnoreResult);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_createWithContext, Assembler::IgnoreResult); // keeps result in return value register
as->checkException();
+ as->storeHeapObject(CallData::Context);
}
-void BaselineJIT::generate_PopContext(int reg) { as->popContext(reg); }
-
-void BaselineJIT::generate_ForeachIteratorObject()
+void BaselineJIT::generate_PushBlockContext(int index)
{
as->saveAccumulatorInFrame();
as->prepareCallWithArgCount(2);
- as->passAccumulatorAsArg(1);
- as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(Runtime::method_foreachIterator, Assembler::ResultInAccumulator);
- as->checkException();
+ as->passInt32AsArg(index, 1);
+ as->passRegAsArg(0, 0);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::pushBlockContext, Assembler::IgnoreResult);
}
-void BaselineJIT::generate_ForeachNextPropertyName()
+void BaselineJIT::generate_CloneBlockContext()
{
as->saveAccumulatorInFrame();
as->prepareCallWithArgCount(1);
- as->passAccumulatorAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(Runtime::method_foreachNextPropertyName,
- Assembler::ResultInAccumulator);
+ as->passRegAsArg(CallData::Context, 0);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::cloneBlockContext, Assembler::IgnoreResult);
+}
+
+void BaselineJIT::generate_PushScriptContext(int index)
+{
+ as->saveAccumulatorInFrame();
+ as->prepareCallWithArgCount(3);
+ as->passInt32AsArg(index, 2);
+ as->passEngineAsArg(1);
+ as->passRegAsArg(0, 0);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::pushScriptContext, Assembler::IgnoreResult);
+}
+
+void BaselineJIT::generate_PopScriptContext()
+{
+ as->saveAccumulatorInFrame();
+ as->prepareCallWithArgCount(2);
+ as->passEngineAsArg(1);
+ as->passRegAsArg(0, 0);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::popScriptContext, Assembler::IgnoreResult);
+}
+
+void BaselineJIT::generate_PopContext() { as->popContext(); }
+
+void BaselineJIT::generate_GetIterator(int iterator)
+{
+ as->saveAccumulatorInFrame();
+ as->prepareCallWithArgCount(3);
+ as->passInt32AsArg(iterator, 2);
+ as->passAccumulatorAsArg(1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_getIterator, Assembler::ResultInAccumulator);
as->checkException();
}
-static ReturnedValue deleteMemberHelper(QV4::Function *function, const QV4::Value &base, int member)
+void BaselineJIT::generate_IteratorNext(int value)
{
- auto engine = function->internalClass->engine;
- if (!Runtime::method_deleteMember(engine, base, member)) {
- if (function->isStrict())
- engine->throwTypeError();
- return Encode(false);
- } else {
- return Encode(true);
- }
+ as->saveAccumulatorInFrame();
+ as->prepareCallWithArgCount(3);
+ as->passRegAsArg(value, 2);
+ as->passAccumulatorAsArg(1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNext, Assembler::ResultInAccumulator);
+ as->checkException();
}
-void BaselineJIT::generate_DeleteMember(int member, int base)
+void BaselineJIT::generate_IteratorClose(int done)
{
- STORE_IP();
+ as->saveAccumulatorInFrame();
as->prepareCallWithArgCount(3);
- as->passInt32AsArg(member, 2);
- as->passRegAsArg(base, 1);
- as->passFunctionAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(deleteMemberHelper, Assembler::ResultInAccumulator);
+ as->passRegAsArg(done, 2);
+ as->passAccumulatorAsArg(1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorClose, Assembler::ResultInAccumulator);
as->checkException();
}
-static ReturnedValue deleteSubscriptHelper(QV4::Function *function, const QV4::Value &base, const QV4::Value &index)
+void BaselineJIT::generate_DestructureRestElement()
{
- auto engine = function->internalClass->engine;
- if (!Runtime::method_deleteElement(engine, base, index)) {
- if (function->isStrict())
- engine->throwTypeError();
- return Encode(false);
- } else {
- return Encode(true);
- }
+ as->saveAccumulatorInFrame();
+ as->prepareCallWithArgCount(2);
+ as->passAccumulatorAsArg(1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_destructureRestElement, Assembler::ResultInAccumulator);
+ as->checkException();
}
-void BaselineJIT::generate_DeleteSubscript(int base, int index)
+void BaselineJIT::generate_DeleteProperty(int base, int index)
{
STORE_IP();
as->prepareCallWithArgCount(3);
as->passRegAsArg(index, 2);
as->passRegAsArg(base, 1);
as->passFunctionAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(deleteSubscriptHelper, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::deleteProperty, Assembler::ResultInAccumulator);
as->checkException();
}
-static ReturnedValue deleteNameHelper(QV4::Function *function, int name)
-{
- auto engine = function->internalClass->engine;
- if (!Runtime::method_deleteName(engine, name)) {
- if (function->isStrict())
- engine->throwTypeError();
- return Encode(false);
- } else {
- return Encode(true);
- }
-}
-
void BaselineJIT::generate_DeleteName(int name)
{
STORE_IP();
as->prepareCallWithArgCount(2);
as->passInt32AsArg(name, 1);
as->passFunctionAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(deleteNameHelper, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::deleteName, Assembler::ResultInAccumulator);
as->checkException();
}
@@ -754,17 +746,26 @@ void BaselineJIT::generate_DefineArray(int argc, int args)
JIT_GENERATE_RUNTIME_CALL(Runtime::method_arrayLiteral, Assembler::ResultInAccumulator);
}
-void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int arrayValueCount,
- int arrayGetterSetterCountAndFlags, int args)
+void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int argc, int args)
{
- as->prepareCallWithArgCount(5);
- as->passInt32AsArg(arrayGetterSetterCountAndFlags, 4);
- as->passInt32AsArg(arrayValueCount, 3);
- as->passInt32AsArg(internalClassId, 2);
- as->passRegAsArg(args, 1);
+ as->prepareCallWithArgCount(4);
+ as->passRegAsArg(args, 3);
+ as->passInt32AsArg(argc, 2);
+ as->passInt32AsArg(internalClassId, 1);
as->passEngineAsArg(0);
JIT_GENERATE_RUNTIME_CALL(Runtime::method_objectLiteral, Assembler::ResultInAccumulator);
}
+
+void BaselineJIT::generate_CreateClass(int classIndex, int heritage, int computedNames)
+{
+ as->prepareCallWithArgCount(4);
+ as->passRegAsArg(computedNames, 3);
+ as->passRegAsArg(heritage, 2);
+ as->passInt32AsArg(classIndex, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_createClass, Assembler::ResultInAccumulator);
+}
+
void BaselineJIT::generate_CreateMappedArgumentsObject()
{
as->prepareCallWithArgCount(1);
@@ -781,15 +782,12 @@ void BaselineJIT::generate_CreateUnmappedArgumentsObject()
Assembler::ResultInAccumulator);
}
-static void convertThisToObjectHelper(ExecutionEngine *engine, Value *t)
+void BaselineJIT::generate_CreateRestParameter(int argIndex)
{
- if (!t->isObject()) {
- if (t->isNullOrUndefined()) {
- *t = engine->globalObject->asReturnedValue();
- } else {
- *t = t->toObject(engine)->asReturnedValue();
- }
- }
+ as->prepareCallWithArgCount(2);
+ as->passInt32AsArg(argIndex, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_createRestParameter, Assembler::ResultInAccumulator);
}
void BaselineJIT::generate_ConvertThisToObject()
@@ -797,25 +795,35 @@ void BaselineJIT::generate_ConvertThisToObject()
as->prepareCallWithArgCount(2);
as->passRegAsArg(CallData::This, 1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(convertThisToObjectHelper, Assembler::IgnoreResult);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::convertThisToObject, Assembler::IgnoreResult);
as->checkException();
}
-void BaselineJIT::generate_Construct(int func, int argc, int argv)
+void BaselineJIT::generate_LoadSuperConstructor()
{
- STORE_IP();
- as->prepareCallWithArgCount(4);
- as->passInt32AsArg(argc, 3);
- as->passRegAsArg(argv, 2);
- as->passRegAsArg(func, 1);
+ as->prepareCallWithArgCount(2);
+ as->passRegAsArg(CallData::Function, 1);
as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, Assembler::ResultInAccumulator);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::loadSuperConstructor, Assembler::ResultInAccumulator);
as->checkException();
}
+void BaselineJIT::generate_ToObject()
+{
+ STORE_ACC();
+ as->prepareCallWithArgCount(2);
+ as->passAccumulatorAsArg(1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::toObject, Assembler::ResultInAccumulator);
+ as->checkException();
+
+}
+
void BaselineJIT::generate_Jump(int offset) { as->jump(instructionOffset() + offset); }
void BaselineJIT::generate_JumpTrue(int offset) { as->jumpTrue(instructionOffset() + offset); }
void BaselineJIT::generate_JumpFalse(int offset) { as->jumpFalse(instructionOffset() + offset); }
+void BaselineJIT::generate_JumpNoException(int offset) { as->jumpNoException(instructionOffset() + offset); }
+void BaselineJIT::generate_JumpNotUndefined(int offset) { as->jumpNotUndefined(instructionOffset() + offset); }
void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); }
void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); }
@@ -852,16 +860,6 @@ void BaselineJIT::generate_CmpInstanceOf(int lhs)
as->checkException();
}
-void BaselineJIT::generate_JumpStrictEqualStackSlotInt(int lhs, int rhs, int offset)
-{
- as->jumpStrictEqualStackSlotInt(lhs, rhs, instructionOffset() + offset);
-}
-
-void BaselineJIT::generate_JumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset)
-{
- as->jumpStrictNotEqualStackSlotInt(lhs, rhs, instructionOffset() + offset);
-}
-
void BaselineJIT::generate_UNot() { as->unot(); }
void BaselineJIT::generate_UPlus() { as->toNumber(); }
void BaselineJIT::generate_UMinus() { as->uminus(); }
@@ -884,6 +882,15 @@ void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); }
void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); }
void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); }
+void BaselineJIT::generate_Exp(int lhs) {
+ STORE_IP();
+ STORE_ACC();
+ as->prepareCallWithArgCount(2);
+ as->passAccumulatorAsArg(1);
+ as->passRegAsArg(lhs, 0);
+ JIT_GENERATE_RUNTIME_CALL(Helpers::exp, Assembler::ResultInAccumulator);
+ as->checkException();
+}
void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); }
void BaselineJIT::generate_Div(int lhs) { as->div(lhs); }
void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); }
@@ -928,401 +935,4 @@ void BaselineJIT::endInstruction(Instr::Type instr)
Q_UNUSED(instr);
}
-#define MOTH_UNUSED_ARGS0()
-#define MOTH_UNUSED_ARGS1(arg) \
- Q_UNUSED(arg);
-#define MOTH_UNUSED_ARGS2(arg1, arg2) \
- Q_UNUSED(arg1); \
- Q_UNUSED(arg2);
-#define MOTH_UNUSED_ARGS3(arg1, arg2, arg3) \
- Q_UNUSED(arg1); \
- Q_UNUSED(arg2); \
- Q_UNUSED(arg3);
-#define MOTH_UNUSED_ARGS4(arg1, arg2, arg3, arg4) \
- Q_UNUSED(arg1); \
- Q_UNUSED(arg2); \
- Q_UNUSED(arg3); \
- Q_UNUSED(arg4);
-
-#define MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, ...) \
- MOTH_EXPAND_FOR_MSVC(MOTH_UNUSED_ARGS##nargs(__VA_ARGS__))
-
-#define MOTH_MARK_ARGS_UNUSED_INSTRUCTION(name, nargs, ...) \
- MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, __VA_ARGS__)
-
-#define MOTH_BEGIN_INSTR(instr) \
- { \
- INSTR_##instr(MOTH_DECODE_WITH_BASE) \
- INSTR_##instr(MOTH_MARK_ARGS_UNUSED) \
- Q_UNUSED(base_ptr);
-
-#define MOTH_END_INSTR(instr) \
- continue; \
- }
-
-void BaselineJIT::collectLabelsInBytecode()
-{
- MOTH_JUMP_TABLE;
-
- const auto addLabel = [&](int offset) {
- Q_ASSERT(offset >= 0 && offset < static_cast<int>(function->compiledFunction->codeSize));
- labels.push_back(offset);
- };
-
- const char *code = reinterpret_cast<const char *>(function->codeData);
- const char *start = code;
- const char *end = code + function->compiledFunction->codeSize;
- while (code < end) {
- MOTH_DISPATCH()
- Q_UNREACHABLE();
-
- MOTH_BEGIN_INSTR(LoadReg)
- MOTH_END_INSTR(LoadReg)
-
- MOTH_BEGIN_INSTR(StoreReg)
- MOTH_END_INSTR(StoreReg)
-
- MOTH_BEGIN_INSTR(MoveReg)
- MOTH_END_INSTR(MoveReg)
-
- MOTH_BEGIN_INSTR(LoadConst)
- MOTH_END_INSTR(LoadConst)
-
- MOTH_BEGIN_INSTR(LoadNull)
- MOTH_END_INSTR(LoadNull)
-
- MOTH_BEGIN_INSTR(LoadZero)
- MOTH_END_INSTR(LoadZero)
-
- MOTH_BEGIN_INSTR(LoadTrue)
- MOTH_END_INSTR(LoadTrue)
-
- MOTH_BEGIN_INSTR(LoadFalse)
- MOTH_END_INSTR(LoadFalse)
-
- MOTH_BEGIN_INSTR(LoadUndefined)
- MOTH_END_INSTR(LoadUndefined)
-
- MOTH_BEGIN_INSTR(LoadInt)
- MOTH_END_INSTR(LoadInt)
-
- MOTH_BEGIN_INSTR(MoveConst)
- MOTH_END_INSTR(MoveConst)
-
- MOTH_BEGIN_INSTR(LoadLocal)
- MOTH_END_INSTR(LoadLocal)
-
- MOTH_BEGIN_INSTR(StoreLocal)
- MOTH_END_INSTR(StoreLocal)
-
- MOTH_BEGIN_INSTR(LoadScopedLocal)
- MOTH_END_INSTR(LoadScopedLocal)
-
- MOTH_BEGIN_INSTR(StoreScopedLocal)
- MOTH_END_INSTR(StoreScopedLocal)
-
- MOTH_BEGIN_INSTR(LoadRuntimeString)
- MOTH_END_INSTR(LoadRuntimeString)
-
- MOTH_BEGIN_INSTR(MoveRegExp)
- MOTH_END_INSTR(MoveRegExp)
-
- MOTH_BEGIN_INSTR(LoadClosure)
- MOTH_END_INSTR(LoadClosure)
-
- MOTH_BEGIN_INSTR(LoadName)
- MOTH_END_INSTR(LoadName)
-
- MOTH_BEGIN_INSTR(LoadGlobalLookup)
- MOTH_END_INSTR(LoadGlobalLookup)
-
- MOTH_BEGIN_INSTR(StoreNameSloppy)
- MOTH_END_INSTR(StoreNameSloppy)
-
- MOTH_BEGIN_INSTR(StoreNameStrict)
- MOTH_END_INSTR(StoreNameStrict)
-
- MOTH_BEGIN_INSTR(LoadElement)
- MOTH_END_INSTR(LoadElement)
-
- MOTH_BEGIN_INSTR(LoadElementA)
- MOTH_END_INSTR(LoadElement)
-
- MOTH_BEGIN_INSTR(StoreElement)
- MOTH_END_INSTR(StoreElement)
-
- MOTH_BEGIN_INSTR(LoadProperty)
- MOTH_END_INSTR(LoadProperty)
-
- MOTH_BEGIN_INSTR(LoadPropertyA)
- MOTH_END_INSTR(LoadElementA)
-
- MOTH_BEGIN_INSTR(GetLookup)
- MOTH_END_INSTR(GetLookup)
-
- MOTH_BEGIN_INSTR(GetLookupA)
- MOTH_END_INSTR(GetLookupA)
-
- MOTH_BEGIN_INSTR(StoreProperty)
- MOTH_END_INSTR(StoreProperty)
-
- MOTH_BEGIN_INSTR(SetLookup)
- MOTH_END_INSTR(SetLookup)
-
- MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
- MOTH_END_INSTR(StoreScopeObjectProperty)
-
- MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
- MOTH_END_INSTR(LoadScopeObjectProperty)
-
- MOTH_BEGIN_INSTR(StoreContextObjectProperty)
- MOTH_END_INSTR(StoreContextObjectProperty)
-
- MOTH_BEGIN_INSTR(LoadContextObjectProperty)
- MOTH_END_INSTR(LoadContextObjectProperty)
-
- MOTH_BEGIN_INSTR(LoadIdObject)
- MOTH_END_INSTR(LoadIdObject)
-
- MOTH_BEGIN_INSTR(CallValue)
- MOTH_END_INSTR(CallValue)
-
- MOTH_BEGIN_INSTR(CallProperty)
- MOTH_END_INSTR(CallProperty)
-
- MOTH_BEGIN_INSTR(CallPropertyLookup)
- MOTH_END_INSTR(CallPropertyLookup)
-
- MOTH_BEGIN_INSTR(CallElement)
- MOTH_END_INSTR(CallElement)
-
- MOTH_BEGIN_INSTR(CallName)
- MOTH_END_INSTR(CallName)
-
- MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
- MOTH_END_INSTR(CallPossiblyDirectEval)
-
- MOTH_BEGIN_INSTR(CallGlobalLookup)
- MOTH_END_INSTR(CallGlobalLookup)
-
- MOTH_BEGIN_INSTR(CallScopeObjectProperty)
- MOTH_END_INSTR(CallScopeObjectProperty)
-
- MOTH_BEGIN_INSTR(CallContextObjectProperty)
- MOTH_END_INSTR(CallContextObjectProperty)
-
- MOTH_BEGIN_INSTR(SetExceptionHandler)
- addLabel(code - start + offset);
- MOTH_END_INSTR(SetExceptionHandler)
-
- MOTH_BEGIN_INSTR(ThrowException)
- MOTH_END_INSTR(ThrowException)
-
- MOTH_BEGIN_INSTR(GetException)
- MOTH_END_INSTR(HasException)
-
- MOTH_BEGIN_INSTR(SetException)
- MOTH_END_INSTR(SetExceptionFlag)
-
- MOTH_BEGIN_INSTR(CreateCallContext)
- MOTH_END_INSTR(CreateCallContext)
-
- MOTH_BEGIN_INSTR(PushCatchContext)
- MOTH_END_INSTR(PushCatchContext)
-
- MOTH_BEGIN_INSTR(PushWithContext)
- MOTH_END_INSTR(PushWithContext)
-
- MOTH_BEGIN_INSTR(PopContext)
- MOTH_END_INSTR(PopContext)
-
- MOTH_BEGIN_INSTR(ForeachIteratorObject)
- MOTH_END_INSTR(ForeachIteratorObject)
-
- MOTH_BEGIN_INSTR(ForeachNextPropertyName)
- MOTH_END_INSTR(ForeachNextPropertyName)
-
- MOTH_BEGIN_INSTR(DeleteMember)
- MOTH_END_INSTR(DeleteMember)
-
- MOTH_BEGIN_INSTR(DeleteSubscript)
- MOTH_END_INSTR(DeleteSubscript)
-
- MOTH_BEGIN_INSTR(DeleteName)
- MOTH_END_INSTR(DeleteName)
-
- MOTH_BEGIN_INSTR(TypeofName)
- MOTH_END_INSTR(TypeofName)
-
- MOTH_BEGIN_INSTR(TypeofValue)
- MOTH_END_INSTR(TypeofValue)
-
- MOTH_BEGIN_INSTR(DeclareVar)
- MOTH_END_INSTR(DeclareVar)
-
- MOTH_BEGIN_INSTR(DefineArray)
- MOTH_END_INSTR(DefineArray)
-
- MOTH_BEGIN_INSTR(DefineObjectLiteral)
- MOTH_END_INSTR(DefineObjectLiteral)
-
- MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
- MOTH_END_INSTR(CreateMappedArgumentsObject)
-
- MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
- MOTH_END_INSTR(CreateUnmappedArgumentsObject)
-
- MOTH_BEGIN_INSTR(ConvertThisToObject)
- MOTH_END_INSTR(ConvertThisToObject)
-
- MOTH_BEGIN_INSTR(Construct)
- MOTH_END_INSTR(Construct)
-
- MOTH_BEGIN_INSTR(Jump)
- addLabel(code - start + offset);
- MOTH_END_INSTR(Jump)
-
- MOTH_BEGIN_INSTR(JumpTrue)
- addLabel(code - start + offset);
- MOTH_END_INSTR(JumpTrue)
-
- MOTH_BEGIN_INSTR(JumpFalse)
- addLabel(code - start + offset);
- MOTH_END_INSTR(JumpFalse)
-
- MOTH_BEGIN_INSTR(CmpEqNull)
- MOTH_END_INSTR(CmpEqNull)
-
- MOTH_BEGIN_INSTR(CmpNeNull)
- MOTH_END_INSTR(CmpNeNull)
-
- MOTH_BEGIN_INSTR(CmpEqInt)
- MOTH_END_INSTR(CmpEq)
-
- MOTH_BEGIN_INSTR(CmpNeInt)
- MOTH_END_INSTR(CmpNeInt)
-
- MOTH_BEGIN_INSTR(CmpEq)
- MOTH_END_INSTR(CmpEq)
-
- MOTH_BEGIN_INSTR(CmpNe)
- MOTH_END_INSTR(CmpNe)
-
- MOTH_BEGIN_INSTR(CmpGt)
- MOTH_END_INSTR(CmpGt)
-
- MOTH_BEGIN_INSTR(CmpGe)
- MOTH_END_INSTR(CmpGe)
-
- MOTH_BEGIN_INSTR(CmpLt)
- MOTH_END_INSTR(CmpLt)
-
- MOTH_BEGIN_INSTR(CmpLe)
- MOTH_END_INSTR(CmpLe)
-
- MOTH_BEGIN_INSTR(CmpStrictEqual)
- MOTH_END_INSTR(CmpStrictEqual)
-
- MOTH_BEGIN_INSTR(CmpStrictNotEqual)
- MOTH_END_INSTR(CmpStrictNotEqual)
-
- MOTH_BEGIN_INSTR(CmpIn)
- MOTH_END_INSTR(CmpIn)
-
- MOTH_BEGIN_INSTR(CmpInstanceOf)
- MOTH_END_INSTR(CmpInstanceOf)
-
- MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
- addLabel(code - start + offset);
- MOTH_END_INSTR(JumpStrictEqualStackSlotInt)
-
- MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
- addLabel(code - start + offset);
- MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
-
- MOTH_BEGIN_INSTR(UNot)
- MOTH_END_INSTR(UNot)
-
- MOTH_BEGIN_INSTR(UPlus)
- MOTH_END_INSTR(UPlus)
-
- MOTH_BEGIN_INSTR(UMinus)
- MOTH_END_INSTR(UMinus)
-
- MOTH_BEGIN_INSTR(UCompl)
- MOTH_END_INSTR(UCompl)
-
- MOTH_BEGIN_INSTR(Increment)
- MOTH_END_INSTR(PreIncrement)
-
- MOTH_BEGIN_INSTR(Decrement)
- MOTH_END_INSTR(PreDecrement)
-
- MOTH_BEGIN_INSTR(Add)
- MOTH_END_INSTR(Add)
-
- MOTH_BEGIN_INSTR(BitAnd)
- MOTH_END_INSTR(BitAnd)
-
- MOTH_BEGIN_INSTR(BitOr)
- MOTH_END_INSTR(BitOr)
-
- MOTH_BEGIN_INSTR(BitXor)
- MOTH_END_INSTR(BitXor)
-
- MOTH_BEGIN_INSTR(UShr)
- MOTH_END_INSTR(UShr)
-
- MOTH_BEGIN_INSTR(Shr)
- MOTH_END_INSTR(Shr)
-
- MOTH_BEGIN_INSTR(Shl)
- MOTH_END_INSTR(Shl)
-
- MOTH_BEGIN_INSTR(BitAndConst)
- MOTH_END_INSTR(BitAndConst)
-
- MOTH_BEGIN_INSTR(BitOrConst)
- MOTH_END_INSTR(BitOr)
-
- MOTH_BEGIN_INSTR(BitXorConst)
- MOTH_END_INSTR(BitXor)
-
- MOTH_BEGIN_INSTR(UShrConst)
- MOTH_END_INSTR(UShrConst)
-
- MOTH_BEGIN_INSTR(ShrConst)
- MOTH_END_INSTR(ShrConst)
-
- MOTH_BEGIN_INSTR(ShlConst)
- MOTH_END_INSTR(ShlConst)
-
- MOTH_BEGIN_INSTR(Mul)
- MOTH_END_INSTR(Mul)
-
- MOTH_BEGIN_INSTR(Div)
- MOTH_END_INSTR(Div)
-
- MOTH_BEGIN_INSTR(Mod)
- MOTH_END_INSTR(Mod)
-
- MOTH_BEGIN_INSTR(Sub)
- MOTH_END_INSTR(Sub)
-
- MOTH_BEGIN_INSTR(Ret)
- MOTH_END_INSTR(Ret)
-
- MOTH_BEGIN_INSTR(Debug)
- MOTH_END_INSTR(Debug)
-
- MOTH_BEGIN_INSTR(LoadQmlContext)
- MOTH_END_INSTR(LoadQmlContext)
-
- MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
- MOTH_END_INSTR(LoadQmlImportedScripts)
- }
-}
-#undef MOTH_BEGIN_INSTR
-#undef MOTH_END_INSTR
-
#endif // V4_ENABLE_JIT
diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4baselinejit_p.h
index 5aebf78a8d..d96fd6ea6a 100644
--- a/src/qml/jit/qv4jit_p.h
+++ b/src/qml/jit/qv4baselinejit_p.h
@@ -54,36 +54,10 @@
#include <private/qv4global_p.h>
#include <private/qv4function_p.h>
#include <private/qv4instr_moth_p.h>
+#include <private/qv4bytecodehandler_p.h>
//QT_REQUIRE_CONFIG(qml_jit);
-#define JIT_DEFINE_ARGS(nargs, ...) \
- MOTH_EXPAND_FOR_MSVC(JIT_DEFINE_ARGS##nargs(__VA_ARGS__))
-
-#define JIT_DEFINE_ARGS0()
-#define JIT_DEFINE_ARGS1(arg) \
- int arg
-#define JIT_DEFINE_ARGS2(arg1, arg2) \
- int arg1, \
- int arg2
-#define JIT_DEFINE_ARGS3(arg1, arg2, arg3) \
- int arg1, \
- int arg2, \
- int arg3
-#define JIT_DEFINE_ARGS4(arg1, arg2, arg3, arg4) \
- int arg1, \
- int arg2, \
- int arg3, \
- int arg4
-
-#define JIT_DEFINE_VIRTUAL_BYTECODE_HANDLER_INSTRUCTION(name, nargs, ...) \
- virtual void generate_##name( \
- JIT_DEFINE_ARGS(nargs, __VA_ARGS__) \
- ) = 0;
-
-#define JIT_DEFINE_VIRTUAL_BYTECODE_HANDLER(instr) \
- INSTR_##instr(JIT_DEFINE_VIRTUAL_BYTECODE_HANDLER)
-
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -91,31 +65,12 @@ namespace JIT {
class Assembler;
-class ByteCodeHandler
-{
-public:
- virtual ~ByteCodeHandler();
-
- void decode(const char *code, uint len);
-
- int instructionOffset() const { return _offset; }
-
-protected:
- FOR_EACH_MOTH_INSTR(JIT_DEFINE_VIRTUAL_BYTECODE_HANDLER)
-
- virtual void startInstruction(Moth::Instr::Type instr) = 0;
- virtual void endInstruction(Moth::Instr::Type instr) = 0;
-
-private:
- int _offset = 0;
-};
-
#ifdef V4_ENABLE_JIT
-class BaselineJIT final: public ByteCodeHandler
+class BaselineJIT final: public Moth::ByteCodeHandler
{
public:
BaselineJIT(QV4::Function *);
- virtual ~BaselineJIT();
+ virtual ~BaselineJIT() Q_DECL_OVERRIDE;
void generate();
@@ -143,15 +98,14 @@ public:
void generate_LoadGlobalLookup(int index) override;
void generate_StoreNameSloppy(int name) override;
void generate_StoreNameStrict(int name) override;
- void generate_LoadElement(int base, int index) override;
- void generate_LoadElementA(int base) override;
+ void generate_LoadElement(int base) override;
void generate_StoreElement(int base, int index) override;
- void generate_LoadProperty(int name, int base) override;
- void generate_LoadPropertyA(int name) override;
- void generate_GetLookup(int index, int base) override;
- void generate_GetLookupA(int index) override;
+ void generate_LoadProperty(int name) override;
+ void generate_GetLookup(int index) override;
void generate_StoreProperty(int name, int base) override;
void generate_SetLookup(int index, int base) override;
+ void generate_LoadSuperProperty(int property) override;
+ void generate_StoreSuperProperty(int property) override;
void generate_StoreScopeObjectProperty(int base,
int propertyIndex) override;
void generate_StoreContextObjectProperty(int base,
@@ -161,6 +115,9 @@ public:
void generate_LoadContextObjectProperty(int propertyIndex, int base,
int captureRequired) override;
void generate_LoadIdObject(int index, int base) override;
+ void generate_Yield() override;
+ void generate_Resume(int) override;
+
void generate_CallValue(int name, int argc, int argv) override;
void generate_CallProperty(int name, int base, int argc, int argv) override;
void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) override;
@@ -170,33 +127,46 @@ public:
void generate_CallGlobalLookup(int index, int argc, int argv) override;
void generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) override;
void generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) override;
- void generate_SetExceptionHandler(int offset) override;
+ void generate_CallWithSpread(int func, int thisObject, int argc, int argv) override;
+ void generate_Construct(int func, int argc, int argv) override;
+ void generate_ConstructWithSpread(int func, int argc, int argv) override;
+ void generate_SetUnwindHandler(int offset) override;
+ void generate_UnwindDispatch() override;
+ void generate_UnwindToLabel(int level, int offset) override;
void generate_ThrowException() override;
void generate_GetException() override;
void generate_SetException() override;
void generate_CreateCallContext() override;
- void generate_PushCatchContext(int name, int reg) override;
- void generate_PushWithContext(int reg) override;
- void generate_PopContext(int reg) override;
- void generate_ForeachIteratorObject() override;
- void generate_ForeachNextPropertyName() override;
- void generate_DeleteMember(int member, int base) override;
- void generate_DeleteSubscript(int base, int index) override;
+ void generate_PushCatchContext(int index, int name) override;
+ void generate_PushWithContext() override;
+ void generate_PushBlockContext(int index) override;
+ void generate_CloneBlockContext() override;
+ void generate_PushScriptContext(int index) override;
+ void generate_PopScriptContext() override;
+ void generate_PopContext() override;
+ void generate_GetIterator(int iterator) override;
+ void generate_IteratorNext(int value) override;
+ void generate_IteratorClose(int done) override;
+ void generate_DestructureRestElement() override;
+ void generate_DeleteProperty(int base, int index) override;
void generate_DeleteName(int name) override;
void generate_TypeofName(int name) override;
void generate_TypeofValue() override;
void generate_DeclareVar(int varName, int isDeletable) override;
void generate_DefineArray(int argc, int args) override;
- void generate_DefineObjectLiteral(int internalClassId, int arrayValueCount,
- int arrayGetterSetterCountAndFlags,
- int args) override;
+ void generate_DefineObjectLiteral(int internalClassId, int argc, int args) override;
+ void generate_CreateClass(int classIndex, int heritage, int computedNames) override;
void generate_CreateMappedArgumentsObject() override;
void generate_CreateUnmappedArgumentsObject() override;
+ void generate_CreateRestParameter(int argIndex) override;
void generate_ConvertThisToObject() override;
- void generate_Construct(int func, int argc, int argv) override;
+ void generate_LoadSuperConstructor() override;
+ void generate_ToObject() override;
void generate_Jump(int offset) override;
void generate_JumpTrue(int offset) override;
void generate_JumpFalse(int offset) override;
+ void generate_JumpNoException(int offset) override;
+ void generate_JumpNotUndefined(int offset) override;
void generate_CmpEqNull() override;
void generate_CmpNeNull() override;
void generate_CmpEqInt(int lhs) override;
@@ -211,10 +181,6 @@ public:
void generate_CmpStrictNotEqual(int lhs) override;
void generate_CmpIn(int lhs) override;
void generate_CmpInstanceOf(int lhs) override;
- void generate_JumpStrictEqualStackSlotInt(int lhs, int rhs,
- int offset) override;
- void generate_JumpStrictNotEqualStackSlotInt(int lhs, int rhs,
- int offset) override;
void generate_UNot() override;
void generate_UPlus() override;
void generate_UMinus() override;
@@ -234,6 +200,7 @@ public:
void generate_UShrConst(int rhs) override;
void generate_ShrConst(int rhs) override;
void generate_ShlConst(int rhs) override;
+ void generate_Exp(int lhs) override;
void generate_Mul(int lhs) override;
void generate_Div(int lhs) override;
void generate_Mod(int lhs) override;
@@ -249,9 +216,6 @@ protected:
{ return std::find(labels.cbegin(), labels.cend(), instructionOffset()) != labels.cend(); }
private:
- void collectLabelsInBytecode();
-
-private:
QV4::Function *function;
QScopedPointer<Assembler> as;
std::vector<int> labels;
diff --git a/src/qml/jit/qv4jithelpers.cpp b/src/qml/jit/qv4jithelpers.cpp
new file mode 100644
index 0000000000..23e3095a85
--- /dev/null
+++ b/src/qml/jit/qv4jithelpers.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4jithelpers_p.h"
+#include "qv4engine_p.h"
+#include "qv4function_p.h"
+#include "qv4value_p.h"
+#include "qv4object_p.h"
+#include "qv4lookup_p.h"
+#include <QtCore/private/qnumeric_p.h>
+
+#ifdef V4_ENABLE_JIT
+
+QT_BEGIN_NAMESPACE
+namespace QV4 {
+namespace JIT {
+namespace Helpers {
+
+void convertThisToObject(ExecutionEngine *engine, Value *t)
+{
+ if (!t->isObject()) {
+ if (t->isNullOrUndefined()) {
+ *t = engine->globalObject->asReturnedValue();
+ } else {
+ *t = t->toObject(engine)->asReturnedValue();
+ }
+ }
+}
+
+ReturnedValue loadGlobalLookup(ExecutionEngine *engine, Function *f, int index)
+{
+ Lookup *l = f->compilationUnit->runtimeLookups + index;
+ return l->globalGetter(l, engine);
+}
+
+ReturnedValue loadSuperConstructor(ExecutionEngine *engine, const Value *t)
+{
+ if (!t->isObject()) {
+ engine->throwTypeError();
+ return Encode::undefined();
+ }
+ return static_cast<const Object *>(t)->getPrototypeOf()->asReturnedValue();
+}
+
+ReturnedValue toObject(ExecutionEngine *engine, const Value &obj)
+{
+ if (obj.isObject())
+ return obj.asReturnedValue();
+
+ return obj.toObject(engine)->asReturnedValue();
+}
+
+ReturnedValue exp(const Value &base, const Value &exp)
+{
+ double b = base.toNumber();
+ double e = exp.toNumber();
+ if (qt_is_inf(e) && (b == 1 || b == -1))
+ return Encode(qt_snan());
+ return Encode(pow(b,e));
+}
+
+ReturnedValue getLookup(ExecutionEngine *engine, Function *f, int index, const Value &base)
+{
+ Lookup *l = f->compilationUnit->runtimeLookups + index;
+ return l->getter(l, engine, base);
+}
+
+void setLookup(Function *f, int index, Value &base, const Value &value)
+{
+ ExecutionEngine *engine = f->internalClass->engine;
+ QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ if (!l->setter(l, engine, base, value) && f->isStrict())
+ engine->throwTypeError();
+}
+
+void pushBlockContext(Value *stack, int index)
+{
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ stack[CallData::Context] = Runtime::method_createBlockContext(c, index);
+}
+
+void cloneBlockContext(Value *contextSlot)
+{
+ *contextSlot = Runtime::method_cloneBlockContext(static_cast<QV4::ExecutionContext *>(contextSlot));
+}
+
+void pushScriptContext(Value *stack, ExecutionEngine *engine, int index)
+{
+ stack[CallData::Context] = Runtime::method_createScriptContext(engine, index);
+}
+
+void popScriptContext(Value *stack, ExecutionEngine *engine)
+{
+ stack[CallData::Context] = Runtime::method_popScriptContext(engine);
+}
+
+ReturnedValue deleteProperty(QV4::Function *function, const QV4::Value &base, const QV4::Value &index)
+{
+ auto engine = function->internalClass->engine;
+ if (!Runtime::method_deleteProperty(engine, base, index)) {
+ if (function->isStrict())
+ engine->throwTypeError();
+ return Encode(false);
+ } else {
+ return Encode(true);
+ }
+}
+
+ReturnedValue deleteName(Function *function, int name)
+{
+ auto engine = function->internalClass->engine;
+ if (!Runtime::method_deleteName(engine, name)) {
+ if (function->isStrict())
+ engine->throwTypeError();
+ return Encode(false);
+ } else {
+ return Encode(true);
+ }
+}
+
+} // Helpers namespace
+} // JIT namespace
+} // QV4 namespace
+QT_END_NAMESPACE
+
+#endif // V4_ENABLE_JIT
diff --git a/src/qml/jit/qv4jithelpers_p.h b/src/qml/jit/qv4jithelpers_p.h
new file mode 100644
index 0000000000..e0dfdc47d9
--- /dev/null
+++ b/src/qml/jit/qv4jithelpers_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEMPLATE_H
+#define TEMPLATE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4global_p.h>
+
+//QT_REQUIRE_CONFIG(qml_jit);
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+#ifdef V4_ENABLE_JIT
+
+namespace JIT {
+namespace Helpers {
+
+void convertThisToObject(ExecutionEngine *engine, Value *t);
+ReturnedValue loadGlobalLookup(ExecutionEngine *engine, Function *f, int index);
+ReturnedValue loadSuperConstructor(ExecutionEngine *engine, const Value *t);
+ReturnedValue toObject(ExecutionEngine *engine, const Value &obj);
+ReturnedValue exp(const Value &base, const Value &exp);
+ReturnedValue getLookup(ExecutionEngine *engine, Function *f, int index, const Value &base);
+void setLookup(Function *f, int index, Value &base, const Value &value);
+void pushBlockContext(Value *stack, int index);
+void cloneBlockContext(Value *contextSlot);
+void pushScriptContext(Value *stack, ExecutionEngine *engine, int index);
+void popScriptContext(Value *stack, ExecutionEngine *engine);
+ReturnedValue deleteProperty(QV4::Function *function, const QV4::Value &base, const QV4::Value &index);
+ReturnedValue deleteName(Function *function, int name);
+
+} // Helpers namespace
+} // JIT namespace
+
+#endif // V4_ENABLE_JIT
+
+} // QV4 namespace
+
+QT_END_NAMESPACE
+
+#endif // TEMPLATE_H
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index c483af638b..5fa81ccc2a 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -51,6 +51,7 @@
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4stackframe_p.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmetaobject.h>
@@ -304,9 +305,9 @@ QJSEngine::QJSEngine()
QJSEngine::QJSEngine(QObject *parent)
: QObject(*new QJSEnginePrivate, parent)
- , m_v4Engine(new QV4::ExecutionEngine)
+ , m_v4Engine(new QV4::ExecutionEngine(this))
{
- m_v4Engine->v8Engine = new QV8Engine(this, m_v4Engine);
+ m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
checkForApplicationInstance();
QJSEnginePrivate::addToDebugServer(this);
@@ -317,9 +318,9 @@ QJSEngine::QJSEngine(QObject *parent)
*/
QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
: QObject(dd, parent)
- , m_v4Engine(new QV4::ExecutionEngine)
+ , m_v4Engine(new QV4::ExecutionEngine(this))
{
- m_v4Engine->v8Engine = new QV8Engine(this, m_v4Engine);
+ m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
checkForApplicationInstance();
}
@@ -462,7 +463,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
QV4::Scope scope(v4);
QV4::ScopedValue result(scope);
- QV4::Script script(v4->rootContext(), QV4::Compiler::GlobalCode, program, fileName, lineNumber);
+ QV4::Script script(v4->rootContext(), QV4::Compiler::ContextType::Global, program, fileName, lineNumber);
script.strictMode = false;
if (v4->currentStackFrame)
script.strictMode = v4->currentStackFrame->v4Function->isStrict();
@@ -738,6 +739,74 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
\sa toScriptValue()
*/
+/*!
+ Throws a run-time error (exception) with the given \a message.
+
+ This method is the C++ counterpart of a \c throw() expression in
+ JavaScript. It enables C++ code to report run-time errors to QJSEngine.
+ Therefore it should only be called from C++ code that was invoked by a
+ JavaScript function through QJSEngine.
+
+ When returning from C++, the engine will interrupt the normal flow of
+ execution and call the the next pre-registered exception handler with
+ an error object that contains the given \a message. The error object
+ will point to the location of the top-most context on the JavaScript
+ caller stack; specifically, it will have properties \c lineNumber,
+ \c fileName and \c stack. These properties are described in
+ \l{Script Exceptions}.
+
+ In the following example a C++ method in \e FileAccess.cpp throws an error
+ in \e qmlFile.qml at the position where \c readFileAsText() is called:
+
+ \code
+ // qmlFile.qml
+ function someFunction() {
+ ...
+ var text = FileAccess.readFileAsText("/path/to/file.txt");
+ }
+ \endcode
+
+ \code
+ // FileAccess.cpp
+ // Assuming that FileAccess is a QObject-derived class that has been
+ // registered as a singleton type and provides an invokable method
+ // readFileAsText()
+
+ QJSValue FileAccess::readFileAsText(const QString & filePath) {
+ QFile file(filePath);
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ jsEngine->throwError(file.errorString());
+ return QString();
+ }
+
+ ...
+ return content;
+ }
+ \endcode
+
+ It is also possible to catch the thrown error in JavaScript:
+ \code
+ // qmlFile.qml
+ function someFunction() {
+ ...
+ var text;
+ try {
+ text = FileAccess.readFileAsText("/path/to/file.txt");
+ } catch (error) {
+ console.warn("In " + error.fileName + ":" + "error.lineNumber" +
+ ": " + error.message);
+ }
+ }
+ \endcode
+
+ \since Qt 5.12
+ \sa {Script Exceptions}
+*/
+void QJSEngine::throwError(const QString &message)
+{
+ m_v4Engine->throwError(message);
+}
QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e)
{
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 3ba2b52e89..36a3e475f2 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -111,6 +111,8 @@ public:
QV4::ExecutionEngine *handle() const { return m_v4Engine; }
+ void throwError(const QString &message);
+
private:
QJSValue create(int type, const void *ptr);
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 348ddb25d9..bf8000bdd8 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -852,7 +852,7 @@ QJSValue QJSValue::prototype() const
ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<QV4::Object>());
if (!o)
return QJSValue();
- ScopedObject p(scope, o->prototype());
+ ScopedObject p(scope, o->getPrototypeOf());
if (!p)
return QJSValue(NullValue);
return QJSValue(o->internalClass()->engine, p.asReturnedValue());
@@ -884,7 +884,7 @@ void QJSValue::setPrototype(const QJSValue& prototype)
if (!val)
return;
if (val->isNull()) {
- o->setPrototype(nullptr);
+ o->setPrototypeOf(nullptr);
return;
}
@@ -895,7 +895,7 @@ void QJSValue::setPrototype(const QJSValue& prototype)
qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
return;
}
- if (!o->setPrototype(p))
+ if (!o->setPrototypeOf(p))
qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
}
@@ -1058,12 +1058,7 @@ QJSValue QJSValue::property(const QString& name) const
return QJSValue();
ScopedString s(scope, engine->newString(name));
- uint idx = s->asArrayIndex();
- if (idx < UINT_MAX)
- return property(idx);
-
- s->makeIdentifier();
- QV4::ScopedValue result(scope, o->get(s));
+ QV4::ScopedValue result(scope, o->get(s->toPropertyKey()));
if (engine->hasException)
result = engine->catchException();
@@ -1110,7 +1105,7 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
if (!o)
return QJSValue();
- QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->getIndexed(arrayIndex));
+ QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->get(arrayIndex));
if (engine->hasException)
engine->catchException();
return QJSValue(engine, result->asReturnedValue());
@@ -1148,15 +1143,8 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
}
ScopedString s(scope, engine->newString(name));
- uint idx = s->asArrayIndex();
- if (idx < UINT_MAX) {
- setProperty(idx, value);
- return;
- }
-
- s->makeIdentifier();
QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
- o->put(s, v);
+ o->put(s->toPropertyKey(), v);
if (engine->hasException)
engine->catchException();
}
@@ -1209,10 +1197,8 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
}
QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
- if (arrayIndex != UINT_MAX)
- o->putIndexed(arrayIndex, v);
- else
- o->put(engine->id_uintMax(), v);
+ PropertyKey id = arrayIndex != UINT_MAX ? PropertyKey::fromArrayIndex(arrayIndex) : engine->id_uintMax()->propertyKey();
+ o->put(id, v);
if (engine->hasException)
engine->catchException();
}
@@ -1249,7 +1235,7 @@ bool QJSValue::deleteProperty(const QString &name)
return false;
ScopedString s(scope, engine->newString(name));
- return o->deleteProperty(s);
+ return o->deleteProperty(s->toPropertyKey());
}
/*!
@@ -1269,8 +1255,8 @@ bool QJSValue::hasProperty(const QString &name) const
if (!o)
return false;
- ScopedString s(scope, engine->newIdentifier(name));
- return o->hasProperty(s);
+ ScopedString s(scope, engine->newString(name));
+ return o->hasProperty(s->toPropertyKey());
}
/*!
@@ -1291,7 +1277,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasOwnProperty(s);
+ return o->getOwnProperty(s->propertyKey()) != Attr_Invalid;
}
/*!
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 62e09f72be..bcf0a9d12d 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -62,7 +62,7 @@
QT_BEGIN_NAMESPACE
-class QJSValuePrivate
+class Q_AUTOTEST_EXPORT QJSValuePrivate
{
public:
static inline QV4::Value *getValue(const QJSValue *jsval)
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index ce472ce7e5..35c6ecc668 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -57,7 +57,7 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
QV4::Scope scope(e);
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v));
- iterator.set(e, e->newForEachIteratorObject(o));
+ iterator.set(e, e->newForInIteratorObject(o));
}
@@ -102,7 +102,7 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
if (!v4)
return;
QV4::Scope scope(v4);
- QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+ QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it().flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
QV4::Property nextProperty;
@@ -153,7 +153,7 @@ bool QJSValueIterator::next()
if (!v4)
return false;
QV4::Scope scope(v4);
- QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+ QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value());
QV4::ScopedString nm(scope);
QV4::Property nextProperty;
QV4::PropertyAttributes nextAttributes;
@@ -200,7 +200,7 @@ QJSValue QJSValueIterator::value() const
if (!d_ptr->currentName.as<QV4::String>() && d_ptr->currentIndex == UINT_MAX)
return QJSValue();
- QV4::ScopedValue v(scope, d_ptr->currentIndex == UINT_MAX ? obj->get(d_ptr->currentName.as<QV4::String>()) : obj->getIndexed(d_ptr->currentIndex));
+ QV4::ScopedValue v(scope, d_ptr->currentIndex == UINT_MAX ? obj->get(d_ptr->currentName.as<QV4::String>()) : obj->get(d_ptr->currentIndex));
if (scope.hasException()) {
engine->catchException();
return QJSValue();
@@ -229,8 +229,8 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&object));
- d_ptr->iterator.set(v4, v4->newForEachIteratorObject(o));
- QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+ d_ptr->iterator.set(v4, v4->newForInIteratorObject(o));
+ QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it().flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
QV4::Property nextProperty;
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 4bc877bd9d..ec5803b2df 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -14,21 +14,29 @@ SOURCES += \
$$PWD/qv4sparsearray.cpp \
$$PWD/qv4arraydata.cpp \
$$PWD/qv4arrayobject.cpp \
+ $$PWD/qv4arrayiterator.cpp \
$$PWD/qv4argumentsobject.cpp \
$$PWD/qv4booleanobject.cpp \
$$PWD/qv4dateobject.cpp \
$$PWD/qv4errorobject.cpp \
$$PWD/qv4function.cpp \
$$PWD/qv4functionobject.cpp \
+ $$PWD/qv4generatorobject.cpp \
$$PWD/qv4globalobject.cpp \
+ $$PWD/qv4iterator.cpp \
$$PWD/qv4jsonobject.cpp \
$$PWD/qv4mathobject.cpp \
$$PWD/qv4memberdata.cpp \
$$PWD/qv4numberobject.cpp \
$$PWD/qv4object.cpp \
$$PWD/qv4objectproto.cpp \
+ $$PWD/qv4propertykey.cpp \
+ $$PWD/qv4proxy.cpp \
$$PWD/qv4qmlcontext.cpp \
+ $$PWD/qv4reflect.cpp \
$$PWD/qv4regexpobject.cpp \
+ $$PWD/qv4stackframe.cpp \
+ $$PWD/qv4stringiterator.cpp \
$$PWD/qv4stringobject.cpp \
$$PWD/qv4variantobject.cpp \
$$PWD/qv4objectiterator.cpp \
@@ -36,13 +44,18 @@ SOURCES += \
$$PWD/qv4runtimecodegen.cpp \
$$PWD/qv4serialize.cpp \
$$PWD/qv4script.cpp \
- $$PWD/qv4sequenceobject.cpp \
+ $$PWD/qv4symbol.cpp \
+ $$PWD/qv4setobject.cpp \
+ $$PWD/qv4setiterator.cpp \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
$$PWD/qv4arraybuffer.cpp \
$$PWD/qv4typedarray.cpp \
$$PWD/qv4dataview.cpp \
- $$PWD/qv4vme_moth.cpp
+ $$PWD/qv4vme_moth.cpp \
+ $$PWD/qv4mapobject.cpp \
+ $$PWD/qv4mapiterator.cpp \
+ $$PWD/qv4estable.cpp
qtConfig(qml-debug): SOURCES += $$PWD/qv4profiling.cpp
@@ -64,22 +77,30 @@ HEADERS += \
$$PWD/qv4sparsearray_p.h \
$$PWD/qv4arraydata_p.h \
$$PWD/qv4arrayobject_p.h \
+ $$PWD/qv4arrayiterator_p.h \
$$PWD/qv4argumentsobject_p.h \
$$PWD/qv4booleanobject_p.h \
$$PWD/qv4dateobject_p.h \
$$PWD/qv4errorobject_p.h \
$$PWD/qv4function_p.h \
$$PWD/qv4functionobject_p.h \
+ $$PWD/qv4generatorobject_p.h \
$$PWD/qv4globalobject_p.h \
+ $$PWD/qv4iterator_p.h \
$$PWD/qv4jsonobject_p.h \
$$PWD/qv4mathobject_p.h \
$$PWD/qv4memberdata_p.h \
$$PWD/qv4numberobject_p.h \
$$PWD/qv4object_p.h \
$$PWD/qv4objectproto_p.h \
+ $$PWD/qv4propertykey_p.h \
+ $$PWD/qv4proxy_p.h \
$$PWD/qv4qmlcontext_p.h \
+ $$PWD/qv4reflect_p.h \
$$PWD/qv4regexpobject_p.h \
$$PWD/qv4runtimecodegen_p.h \
+ $$PWD/qv4stackframe_p.h \
+ $$PWD/qv4stringiterator_p.h \
$$PWD/qv4stringobject_p.h \
$$PWD/qv4variantobject_p.h \
$$PWD/qv4property_p.h \
@@ -87,16 +108,30 @@ HEADERS += \
$$PWD/qv4regexp_p.h \
$$PWD/qv4serialize_p.h \
$$PWD/qv4script_p.h \
+ $$PWD/qv4symbol_p.h \
+ $$PWD/qv4setobject_p.h \
+ $$PWD/qv4setiterator_p.h \
$$PWD/qv4scopedvalue_p.h \
$$PWD/qv4executableallocator_p.h \
- $$PWD/qv4sequenceobject_p.h \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
$$PWD/qv4typedarray_p.h \
$$PWD/qv4dataview_p.h \
- $$PWD/qv4vme_moth_p.h
+ $$PWD/qv4vme_moth_p.h \
+ $$PWD/qv4mapobject_p.h \
+ $$PWD/qv4mapiterator_p.h \
+ $$PWD/qv4estable_p.h \
+ $$PWD/qv4vtable_p.h
+
+qtConfig(qml-sequence-object) {
+ HEADERS += \
+ $$PWD/qv4sequenceobject_p.h
+
+ SOURCES += \
+ $$PWD/qv4sequenceobject.cpp
+}
}
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 075e7afd8a..7b501b9fbb 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -37,11 +37,13 @@
**
****************************************************************************/
#include <qv4argumentsobject_p.h>
+#include <qv4arrayobject_p.h>
#include <qv4alloca_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4string_p.h>
#include <qv4function_p.h>
#include <qv4jscall_p.h>
+#include <qv4symbol_p.h>
using namespace QV4;
@@ -61,10 +63,12 @@ void Heap::ArgumentsObject::init(QV4::CppStackFrame *frame)
this->context.set(v4, context->d());
Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
- Q_ASSERT(CalleePropertyIndex == internalClass->find(v4->id_callee()));
+ Q_ASSERT(CalleePropertyIndex == internalClass->find(v4->id_callee()->propertyKey()));
setProperty(v4, CalleePropertyIndex, context->d()->function);
- Q_ASSERT(LengthPropertyIndex == internalClass->find(v4->id_length()));
+ Q_ASSERT(LengthPropertyIndex == internalClass->find(v4->id_length()->propertyKey()));
setProperty(v4, LengthPropertyIndex, Primitive::fromInt32(context->argc()));
+ Q_ASSERT(SymbolIteratorPropertyIndex == internalClass->find(v4->symbol_iterator()->propertyKey()));
+ setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues());
}
void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame)
@@ -74,19 +78,18 @@ void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame)
Object::init();
- Q_ASSERT(CalleePropertyIndex == internalClass->find(v4->id_callee()));
- Q_ASSERT(CallerPropertyIndex == internalClass->find(v4->id_caller()));
+ Q_ASSERT(CalleePropertyIndex == internalClass->find(v4->id_callee()->propertyKey()));
+ Q_ASSERT(SymbolIteratorPropertyIndex == internalClass->find(v4->symbol_iterator()->propertyKey()));
+ setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues());
setProperty(v4, CalleePropertyIndex + QV4::Object::GetterOffset, *v4->thrower());
setProperty(v4, CalleePropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
- setProperty(v4, CallerPropertyIndex + QV4::Object::GetterOffset, *v4->thrower());
- setProperty(v4, CallerPropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
Scope scope(v4);
Scoped<QV4::StrictArgumentsObject> args(scope, this);
args->arrayReserve(frame->originalArgumentsCount);
args->arrayPut(0, frame->originalArguments, frame->originalArgumentsCount);
- Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(v4->id_length()));
+ Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(v4->id_length()->propertyKey()));
setProperty(v4, LengthPropertyIndex, Primitive::fromInt32(frame->originalArgumentsCount));
}
@@ -117,106 +120,111 @@ void ArgumentsObject::fullyCreate()
d()->fullyCreated = true;
}
-bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs)
+bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *desc, PropertyAttributes attrs)
{
- fullyCreate();
+ if (!id.isArrayIndex())
+ return Object::virtualDefineOwnProperty(m, id, desc, attrs);
- Scope scope(engine);
+ ArgumentsObject *a = static_cast<ArgumentsObject *>(m);
+ a->fullyCreate();
+
+ uint index = id.asArrayIndex();
+ Scope scope(m);
ScopedProperty map(scope);
PropertyAttributes mapAttrs;
- uint numAccessors = qMin(d()->nFormals, context()->argc());
+ uint numAccessors = qMin(a->d()->nFormals, a->context()->argc());
bool isMapped = false;
- if (arrayData() && index < numAccessors &&
- arrayData()->attributes(index).isAccessor() &&
- arrayData()->get(index) == scope.engine->argumentsAccessors[index].getter()->asReturnedValue())
+ if (a->arrayData() && index < numAccessors &&
+ a->arrayData()->attributes(index).isAccessor() &&
+ a->arrayData()->get(index) == scope.engine->argumentsAccessors[index].getter()->asReturnedValue())
isMapped = true;
if (isMapped) {
- Q_ASSERT(arrayData());
- mapAttrs = arrayData()->attributes(index);
- arrayData()->getProperty(index, map, &mapAttrs);
- setArrayAttributes(index, Attr_Data);
- ArrayData::Index arrayIndex{ arrayData(), arrayData()->mappedIndex(index) };
- arrayIndex.set(scope.engine, d()->mappedArguments->values[index]);
+ Q_ASSERT(a->arrayData());
+ mapAttrs = a->arrayData()->attributes(index);
+ a->arrayData()->getProperty(index, map, &mapAttrs);
+ a->setArrayAttributes(index, Attr_Data);
+ PropertyIndex arrayIndex{ a->arrayData(), a->arrayData()->values.values + a->arrayData()->mappedIndex(index) };
+ arrayIndex.set(scope.engine, a->d()->mappedArguments->values[index]);
}
- bool result = Object::defineOwnProperty2(scope.engine, index, desc, attrs);
- if (!result) {
+ bool result = Object::virtualDefineOwnProperty(m, id, desc, attrs);
+ if (!result)
return false;
- }
if (isMapped && attrs.isData()) {
- Q_ASSERT(arrayData());
+ Q_ASSERT(a->arrayData());
ScopedFunctionObject setter(scope, map->setter());
JSCallData jsCallData(scope, 1);
- *jsCallData->thisObject = this->asReturnedValue();
+ *jsCallData->thisObject = a->asReturnedValue();
jsCallData->args[0] = desc->value;
setter->call(jsCallData);
if (attrs.isWritable()) {
- setArrayAttributes(index, mapAttrs);
- arrayData()->setProperty(engine, index, map);
+ a->setArrayAttributes(index, mapAttrs);
+ a->arrayData()->setProperty(m->engine(), index, map);
}
}
return result;
}
-ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *hasProperty)
+ReturnedValue ArgumentsObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- if (args->fullyCreated())
- return Object::getIndexed(m, index, hasProperty);
-
- if (index < static_cast<uint>(args->context()->argc())) {
- if (hasProperty)
- *hasProperty = true;
- return args->context()->args()[index].asReturnedValue();
+ if (id.isArrayIndex() && !args->fullyCreated()) {
+ uint index = id.asArrayIndex();
+ if (index < static_cast<uint>(args->context()->argc())) {
+ if (hasProperty)
+ *hasProperty = true;
+ return args->context()->args()[index].asReturnedValue();
+ }
}
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
+ return Object::virtualGet(m, id, receiver, hasProperty);
}
-bool ArgumentsObject::putIndexed(Managed *m, uint index, const Value &value)
+bool ArgumentsObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->argc()))
- args->fullyCreate();
-
- if (args->fullyCreated())
- return Object::putIndexed(m, index, value);
-
- args->context()->setArg(index, value);
- return true;
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->argc()))
+ args->fullyCreate();
+
+ if (!args->fullyCreated()) {
+ args->context()->setArg(index, value);
+ return true;
+ }
+ }
+ return Object::virtualPut(m, id, value, receiver);
}
-bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
+bool ArgumentsObject::virtualDeleteProperty(Managed *m, PropertyKey id)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
if (!args->fullyCreated())
args->fullyCreate();
- return Object::deleteIndexedProperty(m, index);
+ return Object::virtualDeleteProperty(m, id);
}
-PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
+PropertyAttributes ArgumentsObject::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
{
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- if (args->fullyCreated())
- return Object::queryIndexed(m, index);
+ if (!id.isArrayIndex() || args->fullyCreated())
+ return Object::virtualGetOwnProperty(m, id, p);
- uint numAccessors = qMin(args->d()->nFormals, args->context()->argc());
+ uint index = id.asArrayIndex();
uint argCount = args->context()->argc();
if (index >= argCount)
return PropertyAttributes();
- if (index >= numAccessors)
- return Attr_Data;
- return Attr_Accessor;
+ if (p)
+ p->value = args->context()->args()[index];
+ return Attr_Data;
}
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
-ReturnedValue ArgumentsGetterFunction::call(const FunctionObject *getter, const Value *thisObject, const Value *, int)
+ReturnedValue ArgumentsGetterFunction::virtualCall(const FunctionObject *getter, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = getter->engine();
Scope scope(v4);
@@ -231,7 +239,7 @@ ReturnedValue ArgumentsGetterFunction::call(const FunctionObject *getter, const
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
-ReturnedValue ArgumentsSetterFunction::call(const FunctionObject *setter, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue ArgumentsSetterFunction::virtualCall(const FunctionObject *setter, const Value *thisObject, const Value *argv, int argc)
{
ExecutionEngine *v4 = setter->engine();
Scope scope(v4);
@@ -245,10 +253,8 @@ ReturnedValue ArgumentsSetterFunction::call(const FunctionObject *setter, const
return Encode::undefined();
}
-uint ArgumentsObject::getLength(const Managed *m)
+qint64 ArgumentsObject::virtualGetLength(const Managed *m)
{
const ArgumentsObject *a = static_cast<const ArgumentsObject *>(m);
- if (a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->isInteger())
- return a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->integerValue();
- return Primitive::toUInt32(a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->doubleValue());
+ return a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->toLength();
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index ac281f555a..9ac9ac5d8b 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -85,7 +85,8 @@ DECLARE_HEAP_OBJECT(ArgumentsObject, Object) {
DECLARE_MARKOBJECTS(ArgumentsObject);
enum {
LengthPropertyIndex = 0,
- CalleePropertyIndex = 1
+ SymbolIteratorPropertyIndex = 1,
+ CalleePropertyIndex = 2
};
void init(CppStackFrame *frame);
};
@@ -95,8 +96,8 @@ DECLARE_HEAP_OBJECT(ArgumentsObject, Object) {
DECLARE_HEAP_OBJECT(StrictArgumentsObject, Object) {
enum {
LengthPropertyIndex = 0,
- CalleePropertyIndex = 1,
- CallerPropertyIndex = 3
+ SymbolIteratorPropertyIndex = 1,
+ CalleePropertyIndex = 2
};
void init(CppStackFrame *frame);
};
@@ -108,7 +109,7 @@ struct ArgumentsGetterFunction: FunctionObject
V4_OBJECT2(ArgumentsGetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
inline void
@@ -123,7 +124,7 @@ struct ArgumentsSetterFunction: FunctionObject
V4_OBJECT2(ArgumentsSetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
inline void
@@ -142,15 +143,15 @@ struct ArgumentsObject: Object {
bool fullyCreated() const { return d()->fullyCreated; }
static bool isNonStrictArgumentsObject(Managed *m) {
- return m->d()->vtable() == staticVTable();
+ return m->vtable() == staticVTable();
}
- bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool putIndexed(Managed *m, uint index, const Value &value);
- static bool deleteIndexedProperty(Managed *m, uint index);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static uint getLength(const Managed *m);
+ static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *desc, PropertyAttributes attrs);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static bool virtualDeleteProperty(Managed *m, PropertyKey id);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static qint64 virtualGetLength(const Managed *m);
void fullyCreate();
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 59a2b9d913..f80c9a0ab2 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -41,6 +41,7 @@
#include "qv4dataview_p.h"
#include "qv4string_p.h"
#include "qv4jscall_p.h"
+#include "qv4symbol_p.h"
using namespace QV4;
@@ -52,7 +53,7 @@ void Heap::ArrayBufferCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("ArrayBuffer"));
}
-ReturnedValue ArrayBufferCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
ExecutionEngine *v4 = f->engine();
Scope scope(v4);
@@ -73,9 +74,9 @@ ReturnedValue ArrayBufferCtor::callAsConstructor(const FunctionObject *f, const
}
-ReturnedValue ArrayBufferCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue ArrayBufferCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
- return callAsConstructor(f, argv, argc);
+ return virtualCallAsConstructor(f, argv, argc, f);
}
ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -94,7 +95,8 @@ ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value
void Heap::ArrayBuffer::init(size_t length)
{
Object::init();
- data = QTypedArrayData<char>::allocate(length + 1);
+ if (length < UINT_MAX)
+ data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
return;
@@ -147,13 +149,17 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
+ ctor->addSymbolSpecies();
+
defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
defineDefaultProperty(QStringLiteral("toString"), method_toString, 0);
+ ScopedString name(scope, engine->newString(QStringLiteral("ArrayBuffer")));
+ defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name);
}
ReturnedValue ArrayBufferPrototype::method_get_byteLength(const FunctionObject *b, const Value *thisObject, const Value *, int)
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index 59e78ee85f..089dbc522f 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -78,8 +78,8 @@ struct ArrayBufferCtor: FunctionObject
{
V4_OBJECT2(ArrayBufferCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_isView(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 855407e6f7..ce1d0503df 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -47,25 +47,7 @@
using namespace QV4;
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON
-
-const QV4::VTable QV4::ArrayData::static_vtbl = {
- nullptr,
- 0,
- 0,
- QV4::ArrayData::IsExecutionContext,
- QV4::ArrayData::IsString,
- QV4::ArrayData::IsObject,
- QV4::ArrayData::IsFunctionObject,
- QV4::ArrayData::IsErrorObject,
- QV4::ArrayData::IsArrayData,
- 0,
- QV4::ArrayData::MyType,
- "ArrayData",
- Q_VTABLE_FUNCTION(QV4::ArrayData, destroy),
- ArrayData::Data::markObjects,
- isEqualTo
-};
+DEFINE_MANAGED_VTABLE(ArrayData);
const ArrayVTable SimpleArrayData::static_vtbl =
{
@@ -99,18 +81,9 @@ const ArrayVTable SparseArrayData::static_vtbl =
SparseArrayData::length
};
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
-
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
-static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
-{
- Value v;
- v.setEmpty(value);
- *target = v.asReturnedValue();
-}
-
void Heap::ArrayData::markObjects(Heap::Base *base, MarkStack *stack)
{
ArrayData *a = static_cast<ArrayData *>(base);
@@ -195,7 +168,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
Heap::SparseArrayData *sparse = static_cast<Heap::SparseArrayData *>(newData->d());
- ReturnedValue *lastFree;
+ Value *lastFree;
if (d && d->type() == Heap::ArrayData::Sparse) {
Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
sparse->sparse = old->sparse;
@@ -204,29 +177,29 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
} else {
sparse->sparse = new SparseArray;
lastFree = &sparse->sparse->freeList;
- storeValue(lastFree, 0);
+ *lastFree = Encode(0);
for (uint i = 0; i < toCopy; ++i) {
if (!sparse->values[i].isEmpty()) {
SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
- storeValue(lastFree, i);
+ *lastFree = Encode(i);
sparse->values.values[i].setEmpty();
- lastFree = &sparse->values.values[i].rawValueRef();
+ lastFree = &sparse->values.values[i];
}
}
}
if (toCopy < sparse->values.alloc) {
for (uint i = toCopy; i < sparse->values.alloc; ++i) {
- storeValue(lastFree, i);
+ *lastFree = Encode(i);
sparse->values.values[i].setEmpty();
- lastFree = &sparse->values.values[i].rawValueRef();
+ lastFree = &sparse->values.values[i];
}
}
- storeValue(lastFree, UINT_MAX);
+ *lastFree = Encode(-1);
- Q_ASSERT(Value::fromReturnedValue(sparse->sparse->freeList).isEmpty());
+ Q_ASSERT(sparse->sparse->freeList.isInteger());
// ### Could explicitly free the old data
}
@@ -368,12 +341,12 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->values.values + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
- v[1].setEmpty(Value::fromReturnedValue(d->sparse->freeList).emptyValue());
- v[0].setEmpty(idx + 1);
+ v[1] = d->sparse->freeList;
+ v[0] = Encode(idx + 1);
} else {
- v->setEmpty(Value::fromReturnedValue(d->sparse->freeList).emptyValue());
+ *v = d->sparse->freeList;
}
- d->sparse->freeList = Primitive::emptyValue(idx).asReturnedValue();
+ d->sparse->freeList = Encode(idx);
if (d->attrs)
d->attrs[idx].clear();
}
@@ -390,36 +363,34 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (doubleSlot) {
- ReturnedValue *last = &dd->sparse->freeList;
+ Value *last = &dd->sparse->freeList;
while (1) {
- if (Value::fromReturnedValue(*last).value() == UINT_MAX) {
+ if (last->int_32() == -1) {
reallocate(o, dd->values.alloc + 2, true);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
last = &dd->sparse->freeList;
- Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
+ Q_ASSERT(last->int_32() != -1);
}
- Q_ASSERT(dd->values[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
- if (dd->values[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
+ Q_ASSERT(dd->values[static_cast<uint>(last->int_32())].int_32() != last->int_32());
+ if (dd->values[static_cast<uint>(last->int_32())].int_32() == last->int_32() + 1) {
// found two slots in a row
- uint idx = Value::fromReturnedValue(*last).emptyValue();
- Value lastV = Value::fromReturnedValue(*last);
- lastV.setEmpty(dd->values[lastV.emptyValue() + 1].value());
- *last = lastV.rawValue();
+ uint idx = static_cast<uint>(last->int_32());
+ *last = Encode(dd->values[static_cast<uint>(last->int_32()) + 1].int_32());
dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->values.values[Value::fromReturnedValue(*last).value()].rawValueRef();
+ last = &dd->values.values[last->int_32()];
}
} else {
- if (Value::fromReturnedValue(dd->sparse->freeList).value() == UINT_MAX) {
+ if (dd->sparse->freeList.int_32() == -1) {
reallocate(o, dd->values.alloc + 1, false);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- uint idx = Value::fromReturnedValue(dd->sparse->freeList).value();
- Q_ASSERT(idx != UINT_MAX);
- dd->sparse->freeList = dd->values[idx].asReturnedValue();
- Q_ASSERT(Value::fromReturnedValue(dd->sparse->freeList).isEmpty());
+ Q_ASSERT(dd->sparse->freeList.int_32() != -1);
+ uint idx = static_cast<uint>(dd->sparse->freeList.int_32());
+ dd->sparse->freeList = dd->values[idx];
+ Q_ASSERT(dd->sparse->freeList.isInteger());
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -474,14 +445,14 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->values.values[pidx + 1].setEmpty(Value::fromReturnedValue(dd->sparse->freeList).emptyValue());
- dd->values.values[pidx].setEmpty(pidx + 1);
+ dd->values.values[pidx + 1] = dd->sparse->freeList;
+ dd->values.values[pidx] = Encode(pidx + 1);
} else {
Q_ASSERT(dd->type == Heap::ArrayData::Sparse);
- dd->values.values[pidx].setEmpty(Value::fromReturnedValue(dd->sparse->freeList).emptyValue());
+ dd->values.values[pidx] = dd->sparse->freeList;
}
- dd->sparse->freeList = Primitive::emptyValue(pidx).asReturnedValue();
+ dd->sparse->freeList = Encode(pidx);
dd->sparse->erase(n);
return true;
}
@@ -593,7 +564,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
if (!other || ArgumentsObject::isNonStrictArgumentsObject(otherObj)) {
ScopedValue v(scope);
for (uint i = 0; i < n; ++i)
- obj->arraySet(oldSize + i, (v = otherObj->getIndexed(i)));
+ obj->arraySet(oldSize + i, (v = otherObj->get(i)));
} else if (other && other->isSparse()) {
Heap::SparseArrayData *os = static_cast<Heap::SparseArrayData *>(other->d());
if (other->hasAttributes()) {
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 7ec060f9c6..ac5b430356 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -103,28 +103,16 @@ DECLARE_HEAP_OBJECT(ArrayData, Base) {
enum Type { Simple = 0, Complex = 1, Sparse = 2, Custom = 3 };
- struct Index {
- Heap::ArrayData *arrayData;
- uint index;
-
- void set(EngineBase *e, Value newVal) {
- arrayData->values.set(e, index, newVal);
- }
- const Value *operator->() const { return &arrayData->values[index]; }
- const Value &operator*() const { return arrayData->values[index]; }
- bool isNull() const { return !arrayData; }
- };
-
bool isSparse() const { return type == Sparse; }
- const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); }
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
}
inline bool getProperty(uint index, Property *p, PropertyAttributes *attrs);
inline void setProperty(EngineBase *e, uint index, const Property *p);
- inline Index getValueOrSetter(uint index, PropertyAttributes *attrs);
+ inline PropertyIndex getValueOrSetter(uint index, PropertyAttributes *attrs);
inline PropertyAttributes attributes(uint i) const;
bool isEmpty(uint i) const {
@@ -187,8 +175,6 @@ struct Q_QML_EXPORT ArrayData : public Managed
IsArrayData = true
};
- typedef Heap::ArrayData::Index Index;
-
uint alloc() const { return d()->values.alloc; }
uint &alloc() { return d()->values.alloc; }
void setAlloc(uint a) { d()->values.alloc = a; }
@@ -303,9 +289,9 @@ bool ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
*attrs = attributes(index);
if (p) {
- p->value = *(Index{ this, mapped });
+ p->value = *(PropertyIndex{ this, values.values + mapped });
if (attrs->isAccessor())
- p->set = *(Index{ this, mapped + 1 /*Object::SetterOffset*/ });
+ p->set = *(PropertyIndex{ this, values.values + mapped + 1 /*Object::SetterOffset*/ });
}
return true;
}
@@ -326,16 +312,18 @@ inline PropertyAttributes ArrayData::attributes(uint i) const
return static_cast<const SimpleArrayData *>(this)->attributes(i);
}
-ArrayData::Index ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
+PropertyIndex ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
{
uint idx = mappedIndex(index);
if (idx == UINT_MAX) {
*attrs = Attr_Invalid;
- return { nullptr, 0 };
+ return { nullptr, nullptr };
}
*attrs = attributes(index);
- return { this, attrs->isAccessor() ? idx + 1 /* QV4::Object::SetterOffset*/ : idx };
+ if (attrs->isAccessor())
+ ++idx;
+ return { this, values.values + idx };
}
diff --git a/src/qml/jsruntime/qv4arrayiterator.cpp b/src/qml/jsruntime/qv4arrayiterator.cpp
new file mode 100644
index 0000000000..650f58463e
--- /dev/null
+++ b/src/qml/jsruntime/qv4arrayiterator.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qv4iterator_p.h>
+#include <private/qv4arrayiterator_p.h>
+#include <private/qv4typedarray_p.h>
+#include <private/qv4symbol_p.h>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(ArrayIteratorObject);
+
+void ArrayIteratorPrototype::init(ExecutionEngine *e)
+{
+ defineDefaultProperty(QStringLiteral("next"), method_next, 0);
+
+ Scope scope(e);
+ ScopedString val(scope, e->newString(QLatin1String("Array Iterator")));
+ defineReadonlyConfigurableProperty(e->symbol_toStringTag(), val);
+}
+
+ReturnedValue ArrayIteratorPrototype::method_next(const FunctionObject *b, const Value *that, const Value *, int)
+{
+ Scope scope(b);
+ const ArrayIteratorObject *thisObject = that->as<ArrayIteratorObject>();
+ if (!thisObject)
+ return scope.engine->throwTypeError(QLatin1String("Not an Array Iterator instance"));
+
+ ScopedObject a(scope, thisObject->d()->iteratedObject);
+ if (!a) {
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+ }
+
+ quint32 index = thisObject->d()->nextIndex;
+ IteratorKind itemKind = thisObject->d()->iterationKind;
+
+ Scoped<TypedArray> ta(scope, a->as<TypedArray>());
+ quint32 len = a->getLength();
+
+ if (index >= len) {
+ thisObject->d()->iteratedObject.set(scope.engine, nullptr);
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+ }
+
+ thisObject->d()->nextIndex = index + 1;
+ if (itemKind == KeyIteratorKind) {
+ return IteratorPrototype::createIterResultObject(scope.engine, Primitive::fromInt32(index), false);
+ }
+
+ ReturnedValue elementValue = a->get(index);
+ CHECK_EXCEPTION();
+
+ if (itemKind == ValueIteratorKind) {
+ return IteratorPrototype::createIterResultObject(scope.engine, Value::fromReturnedValue(elementValue), false);
+ } else {
+ Q_ASSERT(itemKind == KeyValueIteratorKind);
+
+ ScopedArrayObject resultArray(scope, scope.engine->newArrayObject());
+ resultArray->arrayReserve(2);
+ resultArray->arrayPut(0, Primitive::fromInt32(index));
+ resultArray->arrayPut(1, Value::fromReturnedValue(elementValue));
+ resultArray->setArrayLengthUnchecked(2);
+
+ return IteratorPrototype::createIterResultObject(scope.engine, resultArray, false);
+ }
+}
+
diff --git a/src/qml/jsruntime/qv4arrayiterator_p.h b/src/qml/jsruntime/qv4arrayiterator_p.h
new file mode 100644
index 0000000000..6d6bb466f1
--- /dev/null
+++ b/src/qml/jsruntime/qv4arrayiterator_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4ARRAYITERATOR_P_H
+#define QV4ARRAYITERATOR_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 "qv4object_p.h"
+#include "qv4iterator_p.h"
+#include "qv4arraydata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+namespace QV4 {
+
+namespace Heap {
+
+#define ArrayIteratorObjectMembers(class, Member) \
+ Member(class, Pointer, Object *, iteratedObject) \
+ Member(class, NoMark, IteratorKind, iterationKind) \
+ Member(class, NoMark, quint32, nextIndex)
+
+DECLARE_HEAP_OBJECT(ArrayIteratorObject, Object) {
+ DECLARE_MARKOBJECTS(ArrayIteratorObject);
+ void init(Object *obj, QV4::ExecutionEngine *engine)
+ {
+ Object::init();
+ this->iteratedObject.set(engine, obj);
+ this->nextIndex = 0;
+ }
+};
+
+}
+
+struct ArrayIteratorPrototype : Object
+{
+ V4_PROTOTYPE(iteratorPrototype)
+ void init(ExecutionEngine *engine);
+
+ static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct ArrayIteratorObject : Object
+{
+ V4_OBJECT2(ArrayIteratorObject, Object)
+ Q_MANAGED_TYPE(ArrayIteratorObject)
+ V4_PROTOTYPE(arrayIteratorPrototype)
+
+ void init(ExecutionEngine *engine);
+};
+
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4ARRAYITERATOR_P_H
+
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index bd019d3bcb..05f6b7dfec 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -38,12 +39,15 @@
****************************************************************************/
#include "qv4arrayobject_p.h"
+#include "qv4objectiterator_p.h"
+#include "qv4arrayiterator_p.h"
#include "qv4sparsearray_p.h"
#include "qv4objectproto_p.h"
#include "qv4jscall_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4runtime_p.h"
#include "qv4string_p.h"
+#include "qv4symbol_p.h"
#include <QtCore/qscopedvaluerollback.h>
using namespace QV4;
@@ -55,7 +59,7 @@ void Heap::ArrayCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Array"));
}
-ReturnedValue ArrayCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue ArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
ExecutionEngine *v4 = static_cast<const ArrayCtor *>(f)->engine();
Scope scope(v4);
@@ -80,22 +84,28 @@ ReturnedValue ArrayCtor::callAsConstructor(const FunctionObject *f, const Value
return a.asReturnedValue();
}
-ReturnedValue ArrayCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue ArrayCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
- return callAsConstructor(f, argv, argc);
+ return virtualCallAsConstructor(f, argv, argc, f);
}
void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
+ ctor->defineDefaultProperty(QStringLiteral("of"), method_of, 0);
+ ctor->defineDefaultProperty(QStringLiteral("from"), method_from, 1);
+ ctor->addSymbolSpecies();
+
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
+ defineDefaultProperty(QStringLiteral("copyWithin"), method_copyWithin, 2);
+ defineDefaultProperty(QStringLiteral("entries"), method_entries, 0);
defineDefaultProperty(QStringLiteral("find"), method_find, 1);
defineDefaultProperty(QStringLiteral("findIndex"), method_findIndex, 1);
defineDefaultProperty(QStringLiteral("join"), method_join, 1);
@@ -107,15 +117,23 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
defineDefaultProperty(QStringLiteral("splice"), method_splice, 2);
defineDefaultProperty(QStringLiteral("unshift"), method_unshift, 1);
+ defineDefaultProperty(QStringLiteral("includes"), method_includes, 1);
defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1);
+ defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1);
defineDefaultProperty(QStringLiteral("every"), method_every, 1);
+ defineDefaultProperty(QStringLiteral("fill"), method_fill, 1);
defineDefaultProperty(QStringLiteral("some"), method_some, 1);
defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
defineDefaultProperty(QStringLiteral("map"), method_map, 1);
defineDefaultProperty(QStringLiteral("filter"), method_filter, 1);
defineDefaultProperty(QStringLiteral("reduce"), method_reduce, 1);
defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1);
+ ScopedString valuesString(scope, engine->newIdentifier(QStringLiteral("values")));
+ ScopedObject values(scope, FunctionObject::createBuiltinFunction(engine, valuesString, method_values, 0));
+ engine->jsObjects[ExecutionEngine::ArrayProtoValues] = values;
+ defineDefaultProperty(QStringLiteral("values"), values);
+ defineDefaultProperty(engine->symbol_iterator(), values);
}
ReturnedValue ArrayPrototype::method_isArray(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -124,6 +142,200 @@ ReturnedValue ArrayPrototype::method_isArray(const FunctionObject *, const Value
return Encode(isArray);
}
+ScopedObject createObjectFromCtorOrArray(Scope &scope, ScopedFunctionObject ctor, bool useLen, int len)
+{
+ ScopedObject a(scope, Primitive::undefinedValue());
+
+ if (ctor) {
+ // ### the spec says that we should only call constructors if
+ // IsConstructor(that), but we have no way of knowing if a builtin is a
+ // constructor. so for the time being, just try call it, and silence any
+ // exceptions-- this is not ideal, as the spec also says that we should
+ // return on exception.
+ //
+ // this also isn't completely kosher. for instance:
+ // Array.from.call(Object, []).constructor == Object
+ // is expected by the tests, but naturally, we get Number.
+ ScopedValue argument(scope, useLen ? QV4::Encode(len) : Primitive::undefinedValue());
+ a = ctor->callAsConstructor(argument, useLen ? 1 : 0);
+ if (scope.engine->hasException)
+ scope.engine->catchException(); // probably not a constructor, then.
+ }
+
+ if (!a) {
+ a = scope.engine->newArrayObject(len);
+ }
+
+ return a;
+}
+
+ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(builtin);
+ ScopedFunctionObject thatCtor(scope, thisObject);
+ ScopedObject itemsObject(scope, argv[0]);
+ bool usingIterator = false;
+
+ if (itemsObject) {
+ // If the object claims to support iterators, then let's try use them.
+ ScopedValue it(scope, itemsObject->get(scope.engine->symbol_iterator()));
+ if (!it->isNullOrUndefined()) {
+ ScopedFunctionObject itfunc(scope, it);
+ if (!itfunc)
+ return scope.engine->throwTypeError();
+ usingIterator = true;
+ }
+ }
+
+ ScopedFunctionObject mapfn(scope, Primitive::undefinedValue());
+ Value *mapArguments = nullptr;
+ if (argc > 1) {
+ mapfn = ScopedFunctionObject(scope, argv[1]);
+ if (!mapfn)
+ return scope.engine->throwTypeError(QString::fromLatin1("%1 is not a function").arg(argv[1].toQStringNoThrow()));
+ mapArguments = scope.alloc(2);
+ }
+
+ ScopedValue thisArg(scope);
+ if (argc > 2)
+ thisArg = argv[2];
+
+ if (usingIterator) {
+ // Item iteration supported, so let's go ahead and try use that.
+ ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, false, 0));
+ CHECK_EXCEPTION();
+ ScopedObject iterator(scope, Runtime::method_getIterator(scope.engine, itemsObject, true));
+ CHECK_EXCEPTION(); // symbol_iterator threw; whoops.
+ if (!iterator) {
+ return scope.engine->throwTypeError(); // symbol_iterator wasn't an object.
+ }
+
+ qint64 k = 0;
+ ScopedValue mappedValue(scope);
+ Value *nextValue = scope.alloc(1);
+ ScopedValue done(scope);
+
+ // The loop below pulls out all the properties using the iterator, and
+ // sets them into the created array.
+ forever {
+ if (k > (static_cast<qint64>(1) << 53) - 1) {
+ ScopedValue falsey(scope, Encode(false));
+ ScopedValue error(scope, scope.engine->throwTypeError());
+ return Runtime::method_iteratorClose(scope.engine, iterator, falsey);
+ }
+
+ // Retrieve the next value. If the iteration ends, we're done here.
+ done = Value::fromReturnedValue(Runtime::method_iteratorNext(scope.engine, iterator, nextValue));
+ CHECK_EXCEPTION();
+ if (done->toBoolean()) {
+ if (ArrayObject *ao = a->as<ArrayObject>()) {
+ ao->setArrayLengthUnchecked(k);
+ } else {
+ a->set(scope.engine->id_length(), Primitive::fromDouble(k), QV4::Object::DoThrowOnRejection);
+ CHECK_EXCEPTION();
+ }
+ return a.asReturnedValue();
+ }
+
+ if (mapfn) {
+ mapArguments[0] = *nextValue;
+ mapArguments[1] = Primitive::fromDouble(k);
+ mappedValue = mapfn->call(thisArg, mapArguments, 2);
+ if (scope.engine->hasException)
+ return Runtime::method_iteratorClose(scope.engine, iterator, Primitive::fromBoolean(false));
+ } else {
+ mappedValue = *nextValue;
+ }
+
+ if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) == Attr_Invalid) {
+ a->arraySet(k, mappedValue);
+ } else {
+ // Don't return: we need to close the iterator.
+ scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
+ }
+
+ if (scope.engine->hasException) {
+ ScopedValue falsey(scope, Encode(false));
+ return Runtime::method_iteratorClose(scope.engine, iterator, falsey);
+ }
+
+ k++;
+ }
+
+ // the return is hidden up in the loop above, when iteration finishes.
+ } else {
+ // Array-like fallback. We request properties by index, and set them on
+ // the return object.
+ ScopedObject arrayLike(scope, argv[0].toObject(scope.engine));
+ if (!arrayLike)
+ return scope.engine->throwTypeError(QString::fromLatin1("Cannot convert %1 to object").arg(argv[0].toQStringNoThrow()));
+ qint64 len = arrayLike->getLength();
+ ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, true, len));
+ CHECK_EXCEPTION();
+
+ qint64 k = 0;
+ ScopedValue mappedValue(scope, Primitive::undefinedValue());
+ ScopedValue kValue(scope);
+ while (k < len) {
+ kValue = arrayLike->get(k);
+ CHECK_EXCEPTION();
+
+ if (mapfn) {
+ mapArguments[0] = kValue;
+ mapArguments[1] = Primitive::fromDouble(k);
+ mappedValue = mapfn->call(thisArg, mapArguments, 2);
+ CHECK_EXCEPTION();
+ } else {
+ mappedValue = kValue;
+ }
+
+ if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) != Attr_Invalid)
+ return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
+
+ a->arraySet(k, mappedValue);
+ CHECK_EXCEPTION();
+
+ k++;
+ }
+
+ if (ArrayObject *ao = a->as<ArrayObject>()) {
+ ao->setArrayLengthUnchecked(k);
+ } else {
+ a->set(scope.engine->id_length(), Primitive::fromDouble(k), QV4::Object::DoThrowOnRejection);
+ CHECK_EXCEPTION();
+ }
+ return a.asReturnedValue();
+ }
+
+}
+
+ReturnedValue ArrayPrototype::method_of(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(builtin);
+ ScopedFunctionObject that(scope, thisObject);
+ ScopedObject a(createObjectFromCtorOrArray(scope, that, true, argc));
+ CHECK_EXCEPTION();
+
+ int k = 0;
+ while (k < argc) {
+ if (a->getOwnProperty(PropertyKey::fromArrayIndex(k)) != Attr_Invalid) {
+ return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
+ }
+ a->arraySet(k, argv[k]);
+ CHECK_EXCEPTION();
+
+ k++;
+ }
+
+ // ArrayObject updates its own length, and will throw if we try touch it.
+ if (!a->as<ArrayObject>()) {
+ a->set(scope.engine->id_length(), Primitive::fromDouble(argc), QV4::Object::DoThrowOnRejection);
+ CHECK_EXCEPTION();
+ }
+
+ return a.asReturnedValue();
+}
+
ReturnedValue ArrayPrototype::method_toString(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(builtin);
@@ -171,9 +383,9 @@ ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value
} else if (eltAsObj && eltAsObj->isListType()) {
const uint startIndex = result->getLength();
for (int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
- entry = eltAsObj->getIndexed(i);
+ entry = eltAsObj->get(i);
// spec says not to throw if this fails
- result->putIndexed(startIndex + i, entry);
+ result->put(startIndex + i, entry);
}
} else {
result->arraySet(result->getLength(), argv[i]);
@@ -183,6 +395,88 @@ ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value
return result.asReturnedValue();
}
+ReturnedValue ArrayPrototype::method_copyWithin(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ ScopedObject instance(scope, thisObject->toObject(scope.engine));
+ if (!instance)
+ RETURN_UNDEFINED();
+
+ double len = instance->getLength();
+ double target = argv[0].toInteger();
+ double start = argv[1].toInteger();
+ double end = len;
+
+ if (argc > 2 && !argv[2].isUndefined()) {
+ end = argv[2].toInteger();
+ }
+
+ double relativeTarget = target;
+ double relativeStart = start;
+ double relativeEnd = end;
+ double from = 0;
+ double to = 0;
+
+ if (relativeTarget < 0) {
+ to = std::max(len+relativeTarget, 0.0);
+ } else {
+ to = std::min(relativeTarget, len);
+ }
+ if (relativeStart < 0) {
+ from = std::max(len+relativeStart, 0.0);
+ } else {
+ from = std::min(relativeStart, len);
+ }
+
+ double fin = 0;
+ if (relativeEnd < 0) {
+ fin = std::max(len+relativeEnd, 0.0);
+ } else {
+ fin = std::min(relativeEnd, len);
+ }
+ double count = std::min(fin-from, len-to);
+ double direction = 1;
+ if (from < to && to < from+count) {
+ direction = -1;
+ from = from + count - 1;
+ to = to + count - 1;
+ }
+
+ while (count > 0) {
+ bool fromPresent = false;
+ ScopedValue fromVal(scope, instance->get(from, &fromPresent));
+
+ if (fromPresent) {
+ instance->setIndexed(to, fromVal, QV4::Object::DoThrowOnRejection);
+ CHECK_EXCEPTION();
+ } else {
+ bool didDelete = instance->deleteProperty(PropertyKey::fromArrayIndex(to));
+ CHECK_EXCEPTION();
+ if (!didDelete) {
+ return scope.engine->throwTypeError();
+ }
+ }
+
+ from = from + direction;
+ to = to + direction;
+ count = count - 1;
+ }
+
+ return instance.asReturnedValue();
+}
+
+ReturnedValue ArrayPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ ScopedObject O(scope, thisObject->toObject(scope.engine));
+ if (!O)
+ RETURN_UNDEFINED();
+
+ Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
+ ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
ReturnedValue ArrayPrototype::method_find(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
@@ -202,7 +496,7 @@ ReturnedValue ArrayPrototype::method_find(const FunctionObject *b, const Value *
ScopedValue that(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
for (uint k = 0; k < len; ++k) {
- arguments[0] = instance->getIndexed(k);
+ arguments[0] = instance->get(k);
CHECK_EXCEPTION();
arguments[1] = Primitive::fromDouble(k);
@@ -236,7 +530,7 @@ ReturnedValue ArrayPrototype::method_findIndex(const FunctionObject *b, const Va
ScopedValue that(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
for (uint k = 0; k < len; ++k) {
- arguments[0] = instance->getIndexed(k);
+ arguments[0] = instance->get(k);
CHECK_EXCEPTION();
arguments[1] = Primitive::fromDouble(k);
@@ -282,7 +576,7 @@ ReturnedValue ArrayPrototype::method_join(const FunctionObject *b, const Value *
if (i)
R += r4;
- e = a->getIndexed(i);
+ e = a->get(i);
CHECK_EXCEPTION();
if (!e->isNullOrUndefined())
R += e->toQString();
@@ -327,10 +621,10 @@ ReturnedValue ArrayPrototype::method_pop(const FunctionObject *b, const Value *t
RETURN_UNDEFINED();
}
- ScopedValue result(scope, instance->getIndexed(len - 1));
+ ScopedValue result(scope, instance->get(len - 1));
CHECK_EXCEPTION();
- if (!instance->deleteIndexedProperty(len - 1))
+ if (!instance->deleteProperty(PropertyKey::fromArrayIndex(len - 1)))
return scope.engine->throwTypeError();
if (instance->isArrayObject())
@@ -352,9 +646,9 @@ ReturnedValue ArrayPrototype::method_push(const FunctionObject *b, const Value *
instance->arrayCreate();
Q_ASSERT(instance->arrayData());
- uint len = instance->getLength();
+ qint64 len = instance->getLength();
- if (len + argc < len) {
+ if (len + quint64(argc) >= UINT_MAX) {
// ughh... this goes beyond UINT_MAX
double l = len;
ScopedString s(scope);
@@ -381,7 +675,7 @@ ReturnedValue ArrayPrototype::method_push(const FunctionObject *b, const Value *
len = instance->arrayData()->length();
} else {
for (int i = 0, ei = argc; i < ei; ++i) {
- if (!instance->putIndexed(len + i, argv[i]))
+ if (!instance->put(len + i, argv[i]))
return scope.engine->throwTypeError();
}
len += argc;
@@ -393,7 +687,7 @@ ReturnedValue ArrayPrototype::method_push(const FunctionObject *b, const Value *
return scope.engine->throwTypeError();
}
- return Encode(len);
+ return Encode(uint(len));
}
ReturnedValue ArrayPrototype::method_reverse(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -403,7 +697,10 @@ ReturnedValue ArrayPrototype::method_reverse(const FunctionObject *b, const Valu
if (!instance)
RETURN_UNDEFINED();
- uint length = instance->getLength();
+ qint64 length = instance->getLength();
+ // ### FIXME
+ if (length >= UINT_MAX)
+ return scope.engine->throwRangeError(QLatin1String("Array.prototype.reverse: Length out of range."));
int lo = 0, hi = length - 1;
@@ -411,19 +708,19 @@ ReturnedValue ArrayPrototype::method_reverse(const FunctionObject *b, const Valu
ScopedValue hval(scope);
for (; lo < hi; ++lo, --hi) {
bool loExists, hiExists;
- lval = instance->getIndexed(lo, &loExists);
- hval = instance->getIndexed(hi, &hiExists);
+ lval = instance->get(lo, &loExists);
+ hval = instance->get(hi, &hiExists);
CHECK_EXCEPTION();
bool ok;
if (hiExists)
- ok = instance->putIndexed(lo, hval);
+ ok = instance->put(lo, hval);
else
- ok = instance->deleteIndexedProperty(lo);
+ ok = instance->deleteProperty(PropertyKey::fromArrayIndex(lo));
if (ok) {
if (loExists)
- ok = instance->putIndexed(hi, lval);
+ ok = instance->put(hi, lval);
else
- ok = instance->deleteIndexedProperty(hi);
+ ok = instance->deleteProperty(PropertyKey::fromArrayIndex(hi));
}
if (!ok)
return scope.engine->throwTypeError();
@@ -454,23 +751,23 @@ ReturnedValue ArrayPrototype::method_shift(const FunctionObject *b, const Value
if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) {
result = instance->arrayData()->vtable()->pop_front(instance);
} else {
- result = instance->getIndexed(0);
+ result = instance->get(uint(0));
CHECK_EXCEPTION();
ScopedValue v(scope);
// do it the slow way
for (uint k = 1; k < len; ++k) {
bool exists;
- v = instance->getIndexed(k, &exists);
+ v = instance->get(k, &exists);
CHECK_EXCEPTION();
bool ok;
if (exists)
- ok = instance->putIndexed(k - 1, v);
+ ok = instance->put(k - 1, v);
else
- ok = instance->deleteIndexedProperty(k - 1);
+ ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k - 1));
if (!ok)
return scope.engine->throwTypeError();
}
- bool ok = instance->deleteIndexedProperty(len - 1);
+ bool ok = instance->deleteProperty(PropertyKey::fromArrayIndex(len - 1));
if (!ok)
return scope.engine->throwTypeError();
}
@@ -518,7 +815,7 @@ ReturnedValue ArrayPrototype::method_slice(const FunctionObject *b, const Value
uint n = 0;
for (uint i = start; i < end; ++i) {
bool exists;
- v = o->getIndexed(i, &exists);
+ v = o->get(i, &exists);
CHECK_EXCEPTION();
if (exists)
result->arraySet(n, v);
@@ -548,60 +845,71 @@ ReturnedValue ArrayPrototype::method_splice(const FunctionObject *b, const Value
if (!instance)
RETURN_UNDEFINED();
- uint len = instance->getLength();
-
- ScopedArrayObject newArray(scope, scope.engine->newArrayObject());
+ qint64 len = instance->getLength();
double rs = (argc ? argv[0] : Primitive::undefinedValue()).toInteger();
- uint start;
+ qint64 start;
if (rs < 0)
- start = (uint) qMax(0., len + rs);
+ start = static_cast<qint64>(qMax(0., len + rs));
else
- start = (uint) qMin(rs, (double)len);
+ start = static_cast<qint64>(qMin(rs, static_cast<double>(len)));
+
+ qint64 deleteCount = 0;
+ qint64 itemCount = 0;
+ if (argc == 1) {
+ deleteCount = len - start;
+ } else if (argc > 1){
+ itemCount = argc - 2;
+ double dc = argv[1].toInteger();
+ deleteCount = static_cast<qint64>(qMin(qMax(dc, 0.), double(len - start)));
+ }
- uint deleteCount = (uint)qMin(qMax((argc > 1 ? argv[1] : Primitive::undefinedValue()).toInteger(), 0.), (double)(len - start));
+ if (len + itemCount - deleteCount > /*(static_cast<qint64>(1) << 53) - 1*/ UINT_MAX - 1)
+ return scope.engine->throwTypeError();
+ if (deleteCount > /*(static_cast<qint64>(1) << 53) - 1*/ UINT_MAX - 1)
+ return scope.engine->throwRangeError(QString::fromLatin1("Array length out of range."));
+ ScopedArrayObject newArray(scope, scope.engine->newArrayObject());
newArray->arrayReserve(deleteCount);
ScopedValue v(scope);
for (uint i = 0; i < deleteCount; ++i) {
bool exists;
- v = instance->getIndexed(start + i, &exists);
+ v = instance->get(start + i, &exists);
CHECK_EXCEPTION();
if (exists)
newArray->arrayPut(i, v);
}
newArray->setArrayLengthUnchecked(deleteCount);
- uint itemCount = argc < 2 ? 0 : argc - 2;
if (itemCount < deleteCount) {
for (uint k = start; k < len - deleteCount; ++k) {
bool exists;
- v = instance->getIndexed(k + deleteCount, &exists);
+ v = instance->get(k + deleteCount, &exists);
CHECK_EXCEPTION();
bool ok;
if (exists)
- ok = instance->putIndexed(k + itemCount, v);
+ ok = instance->put(k + itemCount, v);
else
- ok = instance->deleteIndexedProperty(k + itemCount);
+ ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + itemCount));
if (!ok)
return scope.engine->throwTypeError();
}
for (uint k = len; k > len - deleteCount + itemCount; --k) {
- if (!instance->deleteIndexedProperty(k - 1))
+ if (!instance->deleteProperty(PropertyKey::fromArrayIndex(k - 1)))
return scope.engine->throwTypeError();
}
} else if (itemCount > deleteCount) {
uint k = len - deleteCount;
while (k > start) {
bool exists;
- v = instance->getIndexed(k + deleteCount - 1, &exists);
+ v = instance->get(k + deleteCount - 1, &exists);
CHECK_EXCEPTION();
bool ok;
if (exists)
- ok = instance->putIndexed(k + itemCount - 1, v);
+ ok = instance->put(k + itemCount - 1, v);
else
- ok = instance->deleteIndexedProperty(k + itemCount - 1);
+ ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + itemCount - 1));
if (!ok)
return scope.engine->throwTypeError();
--k;
@@ -609,7 +917,7 @@ ReturnedValue ArrayPrototype::method_splice(const FunctionObject *b, const Value
}
for (uint i = 0; i < itemCount; ++i)
- instance->putIndexed(start + i, argv[i + 2]);
+ instance->put(start + i, argv[i + 2]);
if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))))
return scope.engine->throwTypeError();
@@ -636,17 +944,17 @@ ReturnedValue ArrayPrototype::method_unshift(const FunctionObject *b, const Valu
ScopedValue v(scope);
for (uint k = len; k > 0; --k) {
bool exists;
- v = instance->getIndexed(k - 1, &exists);
+ v = instance->get(k - 1, &exists);
bool ok;
if (exists)
- ok = instance->putIndexed(k + argc - 1, v);
+ ok = instance->put(k + argc - 1, v);
else
- ok = instance->deleteIndexedProperty(k + argc - 1);
+ ok = instance->deleteProperty(PropertyKey::fromArrayIndex(k + argc - 1));
if (!ok)
return scope.engine->throwTypeError();
}
for (int i = 0, ei = argc; i < ei; ++i) {
- bool ok = instance->putIndexed(i, argv[i]);
+ bool ok = instance->put(i, argv[i]);
if (!ok)
return scope.engine->throwTypeError();
}
@@ -663,6 +971,44 @@ ReturnedValue ArrayPrototype::method_unshift(const FunctionObject *b, const Valu
return Encode(newLen);
}
+ReturnedValue ArrayPrototype::method_includes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ ScopedObject instance(scope, thisObject->toObject(scope.engine));
+ if (!instance)
+ RETURN_UNDEFINED();
+
+ qint64 len = instance->getLength();
+ if (len == 0) {
+ return Encode(false);
+ }
+
+ double n = 0;
+ if (argc > 1 && !argv[1].isUndefined()) {
+ n = argv[1].toInteger();
+ }
+
+ double k = 0;
+ if (n >= 0) {
+ k = n;
+ } else {
+ k = len + n;
+ if (k < 0) {
+ k = 0;
+ }
+ }
+
+ while (k < len) {
+ ScopedValue val(scope, instance->get(k));
+ if (val->sameValueZero(argv[0])) {
+ return Encode(true);
+ }
+ k++;
+ }
+
+ return Encode(false);
+}
+
ReturnedValue ArrayPrototype::method_indexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
@@ -691,7 +1037,7 @@ ReturnedValue ArrayPrototype::method_indexOf(const FunctionObject *b, const Valu
ScopedValue v(scope);
for (uint k = fromIndex; k < len; ++k) {
bool exists;
- v = instance->getIndexed(k, &exists);
+ v = instance->get(k, &exists);
if (exists && RuntimeHelpers::strictEqual(v, searchValue))
return Encode(k);
}
@@ -705,7 +1051,7 @@ ReturnedValue ArrayPrototype::method_indexOf(const FunctionObject *b, const Valu
// lets be safe and slow
for (uint i = fromIndex; i < len; ++i) {
bool exists;
- value = instance->getIndexed(i, &exists);
+ value = instance->get(i, &exists);
CHECK_EXCEPTION();
if (exists && RuntimeHelpers::strictEqual(value, searchValue))
return Encode(i);
@@ -729,6 +1075,18 @@ ReturnedValue ArrayPrototype::method_indexOf(const FunctionObject *b, const Valu
return Encode(-1);
}
+ReturnedValue ArrayPrototype::method_keys(const FunctionObject *f, const Value *thisObject, const Value *, int)
+{
+ Scope scope(f);
+ ScopedObject O(scope, thisObject->toObject(scope.engine));
+ if (!O)
+ RETURN_UNDEFINED();
+
+ Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
+ ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
+ return ao->asReturnedValue();
+}
+
ReturnedValue ArrayPrototype::method_lastIndexOf(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
@@ -765,7 +1123,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(const FunctionObject *b, const
for (uint k = fromIndex; k > 0;) {
--k;
bool exists;
- v = instance->getIndexed(k, &exists);
+ v = instance->get(k, &exists);
CHECK_EXCEPTION();
if (exists && RuntimeHelpers::strictEqual(v, searchValue))
return Encode(k);
@@ -793,7 +1151,7 @@ ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value
bool ok = true;
for (uint k = 0; ok && k < len; ++k) {
bool exists;
- arguments[0] = instance->getIndexed(k, &exists);
+ arguments[0] = instance->get(k, &exists);
if (!exists)
continue;
@@ -805,6 +1163,42 @@ ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value
return Encode(ok);
}
+ReturnedValue ArrayPrototype::method_fill(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ ScopedObject instance(scope, thisObject->toObject(scope.engine));
+ if (!instance)
+ RETURN_UNDEFINED();
+
+ uint len = instance->getLength();
+ int relativeStart = argc > 1 ? argv[1].toInteger() : 0;
+ int relativeEnd = len;
+ if (argc > 2 && !argv[2].isUndefined()) {
+ relativeEnd = argv[2].toInteger();
+ }
+ uint k = 0;
+ uint fin = 0;
+
+ if (relativeStart < 0) {
+ k = std::max(len+relativeStart, uint(0));
+ } else {
+ k = std::min(uint(relativeStart), len);
+ }
+
+ if (relativeEnd < 0) {
+ fin = std::max(len + relativeEnd, uint(0));
+ } else {
+ fin = std::min(uint(relativeEnd), len);
+ }
+
+ while (k < fin) {
+ instance->setIndexed(k, argv[0], QV4::Object::DoThrowOnRejection);
+ k++;
+ }
+
+ return instance.asReturnedValue();
+}
+
ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
@@ -824,7 +1218,7 @@ ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value *
for (uint k = 0; k < len; ++k) {
bool exists;
- arguments[0] = instance->getIndexed(k, &exists);
+ arguments[0] = instance->get(k, &exists);
if (!exists)
continue;
@@ -855,7 +1249,7 @@ ReturnedValue ArrayPrototype::method_forEach(const FunctionObject *b, const Valu
for (uint k = 0; k < len; ++k) {
bool exists;
- arguments[0] = instance->getIndexed(k, &exists);
+ arguments[0] = instance->get(k, &exists);
if (!exists)
continue;
@@ -873,12 +1267,15 @@ ReturnedValue ArrayPrototype::method_map(const FunctionObject *b, const Value *t
if (!instance)
RETURN_UNDEFINED();
- uint len = instance->getLength();
+ qint64 len = instance->getLength();
if (!argc || !argv->isFunctionObject())
THROW_TYPE_ERROR();
const FunctionObject *callback = static_cast<const FunctionObject *>(argv);
+ if (len > UINT_MAX - 1)
+ return scope.engine->throwRangeError(QString::fromLatin1("Array length out of range."));
+
ScopedArrayObject a(scope, scope.engine->newArrayObject());
a->arrayReserve(len);
a->setArrayLengthUnchecked(len);
@@ -890,7 +1287,7 @@ ReturnedValue ArrayPrototype::method_map(const FunctionObject *b, const Value *t
for (uint k = 0; k < len; ++k) {
bool exists;
- arguments[0] = instance->getIndexed(k, &exists);
+ arguments[0] = instance->get(k, &exists);
if (!exists)
continue;
@@ -925,7 +1322,7 @@ ReturnedValue ArrayPrototype::method_filter(const FunctionObject *b, const Value
uint to = 0;
for (uint k = 0; k < len; ++k) {
bool exists;
- arguments[0] = instance->getIndexed(k, &exists);
+ arguments[0] = instance->get(k, &exists);
if (!exists)
continue;
@@ -962,7 +1359,7 @@ ReturnedValue ArrayPrototype::method_reduce(const FunctionObject *b, const Value
} else {
bool kPresent = false;
while (k < len && !kPresent) {
- v = instance->getIndexed(k, &kPresent);
+ v = instance->get(k, &kPresent);
if (kPresent)
acc = v;
++k;
@@ -975,7 +1372,7 @@ ReturnedValue ArrayPrototype::method_reduce(const FunctionObject *b, const Value
while (k < len) {
bool kPresent;
- v = instance->getIndexed(k, &kPresent);
+ v = instance->get(k, &kPresent);
if (kPresent) {
arguments[0] = acc;
arguments[1] = v;
@@ -1015,7 +1412,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const
} else {
bool kPresent = false;
while (k > 0 && !kPresent) {
- v = instance->getIndexed(k - 1, &kPresent);
+ v = instance->get(k - 1, &kPresent);
if (kPresent)
acc = v;
--k;
@@ -1028,7 +1425,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const
while (k > 0) {
bool kPresent;
- v = instance->getIndexed(k - 1, &kPresent);
+ v = instance->get(k - 1, &kPresent);
if (kPresent) {
arguments[0] = acc;
arguments[1] = v;
@@ -1041,3 +1438,20 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const
return acc->asReturnedValue();
}
+ReturnedValue ArrayPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ ScopedObject O(scope, thisObject->toObject(scope.engine));
+ if (!O)
+ RETURN_UNDEFINED();
+
+ Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
+ ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue ArrayPrototype::method_get_species(const FunctionObject *, const Value *thisObject, const Value *, int)
+{
+ return thisObject->asReturnedValue();
+}
+
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 3825a600a2..04ec7e1607 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -70,8 +70,8 @@ struct ArrayCtor: FunctionObject
{
V4_OBJECT2(ArrayCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct ArrayPrototype: ArrayObject
@@ -79,9 +79,13 @@ struct ArrayPrototype: ArrayObject
void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_isArray(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_from(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_of(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toLocaleString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_concat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_copyWithin(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_find(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_findIndex(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_join(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
@@ -93,15 +97,23 @@ struct ArrayPrototype: ArrayObject
static ReturnedValue method_sort(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_splice(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_unshift(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_includes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_indexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_lastIndexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_every(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_fill(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_some(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_forEach(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_map(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_filter(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_reduce(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_reduceRight(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ // while this function is implemented here, it's the same for many other JS classes, so the corresponding JS function
+ // is instantiated in the engine, and it can be added to any JS object through Object::addSymbolSpecies()
+ static ReturnedValue method_get_species(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index eb83f902db..f00abad871 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -50,13 +50,13 @@ void Heap::BooleanCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Boolean"));
}
-ReturnedValue BooleanCtor::callAsConstructor(const FunctionObject *that, const Value *argv, int argc)
+ReturnedValue BooleanCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *)
{
bool n = argc ? argv[0].toBoolean() : false;
return Encode(that->engine()->newBooleanObject(n));
}
-ReturnedValue BooleanCtor::call(const FunctionObject *, const Value *, const Value *argv, int argc)
+ReturnedValue BooleanCtor::virtualCall(const FunctionObject *, const Value *, const Value *argv, int argc)
{
bool value = argc ? argv[0].toBoolean() : 0;
return Encode(value);
@@ -66,7 +66,7 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString);
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 3cf09b2667..276ec8393b 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -70,8 +70,8 @@ struct BooleanCtor: FunctionObject
{
V4_OBJECT2(BooleanCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct BooleanPrototype: BooleanObject
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 020e519e74..bb08d2786d 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -48,12 +48,48 @@
#include "qv4errorobject_p.h"
#include "qv4string_p.h"
#include "qv4qmlcontext_p.h"
+#include "qv4stackframe_p.h"
using namespace QV4;
DEFINE_MANAGED_VTABLE(ExecutionContext);
DEFINE_MANAGED_VTABLE(CallContext);
-DEFINE_MANAGED_VTABLE(CatchContext);
+
+Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int blockIndex)
+{
+ Function *function = frame->v4Function;
+
+ Heap::InternalClass *ic = function->compilationUnit->runtimeBlocks.at(blockIndex);
+ uint nLocals = ic->size;
+ size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
+
+ ExecutionEngine *v4 = function->internalClass->engine;
+ Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, ic);
+ c->init();
+ c->type = Heap::ExecutionContext::Type_BlockContext;
+
+ Heap::ExecutionContext *outer = static_cast<Heap::ExecutionContext *>(frame->context()->m());
+ c->outer.set(v4, outer);
+ c->function.set(v4, static_cast<Heap::FunctionObject *>(frame->jsFrame->function.m()));
+
+ c->locals.size = nLocals;
+ c->locals.alloc = nLocals;
+
+ return c;
+}
+
+Heap::CallContext *ExecutionContext::cloneBlockContext(Heap::CallContext *context)
+{
+ uint nLocals = context->locals.alloc;
+ size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
+
+ ExecutionEngine *v4 = context->internalClass->engine;
+ Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, context->internalClass);
+ memcpy(c, context, requiredMemory);
+
+ return c;
+
+}
Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
{
@@ -75,7 +111,7 @@ Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
uint nLocals = compiledFunction->nLocals;
c->locals.size = nLocals;
c->locals.alloc = localsAndFormals;
- // memory allocated from the JS heap is 0 initialized, so check if undefined is 0
+ // memory allocated from the JS heap is 0 initialized, so check if empty is 0
Q_ASSERT(Primitive::undefinedValue().asReturnedValue() == 0);
Value *args = c->locals.values + nLocals;
@@ -96,11 +132,14 @@ Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with)
return c;
}
-Heap::CatchContext *ExecutionContext::newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue)
+Heap::ExecutionContext *ExecutionContext::newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName)
{
- Scope scope(this);
- ScopedValue e(scope, exceptionValue);
- return engine()->memoryManager->alloc<CatchContext>(d(), exceptionVarName, e);
+ Scope scope(frame->context());
+ ScopedString name(scope, exceptionVarName);
+ ScopedValue val(scope, scope.engine->catchException(nullptr));
+ ScopedContext ctx(scope, newBlockContext(frame, blockIndex));
+ ctx->setProperty(name, val);
+ return ctx->d();
}
void ExecutionContext::createMutableBinding(String *name, bool deletable)
@@ -132,44 +171,32 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
activation = ctx->d()->activation;
break;
}
+ case Heap::ExecutionContext::Type_BlockContext:
+ // never create activation records on block contexts
default:
break;
}
ctx = ctx->d()->outer;
}
- if (activation->hasOwnProperty(name))
+ PropertyKey id = name->toPropertyKey();
+ if (activation->getOwnProperty(id) != Attr_Invalid)
return;
ScopedProperty desc(scope);
PropertyAttributes attrs(Attr_Data);
attrs.setConfigurable(deletable);
- activation->__defineOwnProperty__(scope.engine, name, desc, attrs);
-}
-
-void Heap::CatchContext::init(ExecutionContext *outerContext, String *exceptionVarName,
- const Value &exceptionValue)
-{
- Heap::ExecutionContext::init(Heap::ExecutionContext::Type_CatchContext);
- outer.set(internalClass->engine, outerContext);
-
- this->exceptionVarName.set(internalClass->engine, exceptionVarName);
- this->exceptionValue.set(internalClass->engine, exceptionValue);
+ if (!activation->defineOwnProperty(id, desc, attrs))
+ scope.engine->throwTypeError();
}
bool ExecutionContext::deleteProperty(String *name)
{
- name->makeIdentifier();
- Identifier *id = name->identifier();
+ PropertyKey id = name->toPropertyKey();
Heap::ExecutionContext *ctx = d();
for (; ctx; ctx = ctx->outer) {
switch (ctx->type) {
- case Heap::ExecutionContext::Type_CatchContext: {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name->d()))
- return false;
- break;
- }
+ case Heap::ExecutionContext::Type_BlockContext:
case Heap::ExecutionContext::Type_CallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
uint index = c->internalClass->find(id);
@@ -183,8 +210,8 @@ bool ExecutionContext::deleteProperty(String *name)
if (ctx->activation) {
Scope scope(this);
ScopedObject object(scope, ctx->activation);
- if (object && object->hasProperty(name))
- return object->deleteProperty(name);
+ if (object && object->hasProperty(name->toPropertyKey()))
+ return object->deleteProperty(name->toPropertyKey());
}
break;
}
@@ -199,32 +226,24 @@ bool ExecutionContext::deleteProperty(String *name)
ExecutionContext::Error ExecutionContext::setProperty(String *name, const Value &value)
{
- name->makeIdentifier();
- Identifier *id = name->identifier();
+ PropertyKey id = name->toPropertyKey();
QV4::ExecutionEngine *v4 = engine();
Heap::ExecutionContext *ctx = d();
for (; ctx; ctx = ctx->outer) {
switch (ctx->type) {
- case Heap::ExecutionContext::Type_CatchContext: {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name->d())) {
- c->exceptionValue.set(v4, value);
- return NoError;
- }
- break;
- }
case Heap::ExecutionContext::Type_WithContext: {
Scope scope(v4);
ScopedObject w(scope, ctx->activation);
- if (w->hasProperty(name)) {
+ if (w->hasProperty(name->toPropertyKey())) {
if (!w->put(name, value))
return TypeError;
return NoError;
}
break;
}
+ case Heap::ExecutionContext::Type_BlockContext:
case Heap::ExecutionContext::Type_CallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
uint index = c->internalClass->find(id);
@@ -262,20 +281,14 @@ ExecutionContext::Error ExecutionContext::setProperty(String *name, const Value
ReturnedValue ExecutionContext::getProperty(String *name)
{
- name->makeIdentifier();
+ PropertyKey id = name->toPropertyKey();
Heap::ExecutionContext *ctx = d();
for (; ctx; ctx = ctx->outer) {
switch (ctx->type) {
- case Heap::ExecutionContext::Type_CatchContext: {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name->d()))
- return c->exceptionValue.asReturnedValue();
- break;
- }
+ case Heap::ExecutionContext::Type_BlockContext:
case Heap::ExecutionContext::Type_CallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
- Identifier *id = name->identifier();
uint index = c->internalClass->find(id);
if (index < UINT_MAX)
@@ -289,7 +302,7 @@ ReturnedValue ExecutionContext::getProperty(String *name)
Scope scope(this);
ScopedObject activation(scope, ctx->activation);
bool hasProperty = false;
- ReturnedValue v = activation->get(name, &hasProperty);
+ ReturnedValue v = activation->get(id, nullptr, &hasProperty);
if (hasProperty)
return v;
}
@@ -303,21 +316,14 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
{
base->setM(nullptr);
- name->makeIdentifier();
+ PropertyKey id = name->toPropertyKey();
Heap::ExecutionContext *ctx = d();
for (; ctx; ctx = ctx->outer) {
switch (ctx->type) {
- case Heap::ExecutionContext::Type_CatchContext: {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name->d()))
- return c->exceptionValue.asReturnedValue();
- break;
- }
+ case Heap::ExecutionContext::Type_BlockContext:
case Heap::ExecutionContext::Type_CallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
- name->makeIdentifier();
- Identifier *id = name->identifier();
uint index = c->internalClass->find(id);
if (index < UINT_MAX)
@@ -340,7 +346,7 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
Scope scope(this);
ScopedObject o(scope, ctx->activation);
bool hasProperty = false;
- ReturnedValue v = o->get(name, &hasProperty);
+ ReturnedValue v = o->get(id, nullptr, &hasProperty);
if (hasProperty) {
base->setM(o->d());
return v;
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 512bfa06d8..fbb4168e9b 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -55,66 +55,11 @@
QT_BEGIN_NAMESPACE
-class QObject;
-class QQmlContextData;
-
namespace QV4 {
-namespace CompiledData {
-struct CompilationUnitBase;
-struct Function;
-}
-
-struct Function;
-struct Identifier;
-struct CallContext;
-struct CatchContext;
-struct QmlContext;
-struct QQmlContextWrapper;
-
-struct CallData
-{
- enum Offsets {
- Function = 0,
- Context = 1,
- Accumulator = 2,
- This = 3,
- Argc = 4
- };
-
- Value function;
- Value context;
- Value accumulator;
- Value thisObject;
- Value _argc;
-
- int argc() const {
- Q_ASSERT(_argc.isInteger());
- return _argc.int_32();
- }
-
- void setArgc(int argc) {
- Q_ASSERT(argc >= 0);
- _argc.setInt_32(argc);
- }
-
- inline ReturnedValue argument(int i) const {
- return i < argc() ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
- }
-
- Value args[1];
-
- static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); }
-};
-
-Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
-Q_STATIC_ASSERT(offsetof(CallData, thisObject) == CallData::This*sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, args) == 5*sizeof(Value));
namespace Heap {
-struct QmlContext;
-
#define ExecutionContextMembers(class, Member) \
Member(class, Pointer, ExecutionContext *, outer) \
Member(class, Pointer, Object *, activation)
@@ -124,9 +69,9 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
enum ContextType {
Type_GlobalContext = 0x1,
- Type_CatchContext = 0x2,
- Type_WithContext = 0x3,
- Type_QmlContext = 0x4,
+ Type_WithContext = 0x2,
+ Type_QmlContext = 0x3,
+ Type_BlockContext = 0x4,
Type_CallContext = 0x5
};
@@ -137,6 +82,10 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
type = t;
}
+ const VTable *vtable() const {
+ return internalClass->vtable;
+ }
+
quint32 type : 8;
quint32 nArgs : 24;
#if QT_POINTER_SIZE == 8
@@ -181,16 +130,6 @@ Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0);
//Q_STATIC_ASSERT(sizeof(CallContext) == sizeof(ExecutionContext) + sizeof(CallContextData));
//#endif
-#define CatchContextMembers(class, Member) \
- Member(class, Pointer, String *, exceptionVarName) \
- Member(class, HeapValue, HeapValue, exceptionValue)
-
-DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) {
- DECLARE_MARKOBJECTS(CatchContext);
-
- void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
-};
-Q_STATIC_ASSERT(std::is_trivial< CatchContext >::value);
}
@@ -204,9 +143,11 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
Q_MANAGED_TYPE(ExecutionContext)
V4_INTERNALCLASS(ExecutionContext)
+ static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex);
+ static Heap::CallContext *cloneBlockContext(Heap::CallContext *context);
static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame);
Heap::ExecutionContext *newWithContext(Heap::Object *with);
- Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue);
+ static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName);
void createMutableBinding(String *name, bool deletable);
@@ -224,6 +165,12 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
inline CallContext *asCallContext();
inline const CallContext *asCallContext() const;
+
+protected:
+ // vtable method required for compilation
+ static bool virtualDeleteProperty(Managed *, PropertyKey) {
+ Q_UNREACHABLE();
+ }
};
struct Q_QML_EXPORT CallContext : public ExecutionContext
@@ -239,11 +186,6 @@ struct Q_QML_EXPORT CallContext : public ExecutionContext
}
};
-struct CatchContext : public ExecutionContext
-{
- V4_MANAGED(CatchContext, ExecutionContext)
-};
-
inline CallContext *ExecutionContext::asCallContext()
{
return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<CallContext *>(this) : nullptr;
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index d894d909ff..d550e559d3 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -40,6 +40,7 @@
#include "qv4dataview_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4string_p.h"
+#include "qv4symbol_p.h"
#include <QtCore/private/qnumeric_p.h>
#include "qendian.h"
@@ -54,7 +55,7 @@ void Heap::DataViewCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("DataView"));
}
-ReturnedValue DataViewCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue DataViewCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Scope scope(f->engine());
Scoped<ArrayBuffer> buffer(scope, argc ? argv[0] : Primitive::undefinedValue());
@@ -69,54 +70,57 @@ ReturnedValue DataViewCtor::callAsConstructor(const FunctionObject *f, const Val
if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength)
return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range"));
- Scoped<DataView> a(scope, scope.engine->memoryManager->allocObject<DataView>());
+ Scoped<DataView> a(scope, scope.engine->memoryManager->allocate<DataView>());
a->d()->buffer.set(scope.engine, buffer->d());
a->d()->byteLength = byteLength;
a->d()->byteOffset = byteOffset;
return a.asReturnedValue();
}
-ReturnedValue DataViewCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue DataViewCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
- return callAsConstructor(f, argv, argc);
+ return virtualCallAsConstructor(f, argv, argc, f);
}
void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(3));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, nullptr);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, nullptr);
- defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("getUint8"), method_getChar<unsigned char>, 0);
- defineDefaultProperty(QStringLiteral("getInt16"), method_get<short>, 0);
- defineDefaultProperty(QStringLiteral("getUint16"), method_get<unsigned short>, 0);
- defineDefaultProperty(QStringLiteral("getInt32"), method_get<int>, 0);
- defineDefaultProperty(QStringLiteral("getUint32"), method_get<unsigned int>, 0);
- defineDefaultProperty(QStringLiteral("getFloat32"), method_getFloat<float>, 0);
- defineDefaultProperty(QStringLiteral("getFloat64"), method_getFloat<double>, 0);
-
- defineDefaultProperty(QStringLiteral("setInt8"), method_setChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("setUint8"), method_setChar<unsigned char>, 0);
- defineDefaultProperty(QStringLiteral("setInt16"), method_set<short>, 0);
- defineDefaultProperty(QStringLiteral("setUint16"), method_set<unsigned short>, 0);
- defineDefaultProperty(QStringLiteral("setInt32"), method_set<int>, 0);
- defineDefaultProperty(QStringLiteral("setUint32"), method_set<unsigned int>, 0);
- defineDefaultProperty(QStringLiteral("setFloat32"), method_setFloat<float>, 0);
- defineDefaultProperty(QStringLiteral("setFloat64"), method_setFloat<double>, 0);
+ defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 1);
+ defineDefaultProperty(QStringLiteral("getUint8"), method_getChar<unsigned char>, 1);
+ defineDefaultProperty(QStringLiteral("getInt16"), method_get<short>, 1);
+ defineDefaultProperty(QStringLiteral("getUint16"), method_get<unsigned short>, 1);
+ defineDefaultProperty(QStringLiteral("getInt32"), method_get<int>, 1);
+ defineDefaultProperty(QStringLiteral("getUint32"), method_get<unsigned int>, 1);
+ defineDefaultProperty(QStringLiteral("getFloat32"), method_getFloat<float>, 1);
+ defineDefaultProperty(QStringLiteral("getFloat64"), method_getFloat<double>, 1);
+
+ defineDefaultProperty(QStringLiteral("setInt8"), method_setChar<signed char>, 2);
+ defineDefaultProperty(QStringLiteral("setUint8"), method_setChar<unsigned char>, 2);
+ defineDefaultProperty(QStringLiteral("setInt16"), method_set<short>, 2);
+ defineDefaultProperty(QStringLiteral("setUint16"), method_set<unsigned short>, 2);
+ defineDefaultProperty(QStringLiteral("setInt32"), method_set<int>, 2);
+ defineDefaultProperty(QStringLiteral("setUint32"), method_set<unsigned int>, 2);
+ defineDefaultProperty(QStringLiteral("setFloat32"), method_setFloat<float>, 2);
+ defineDefaultProperty(QStringLiteral("setFloat64"), method_setFloat<double>, 2);
+
+ ScopedString name(scope, engine->newString(QStringLiteral("DataView")));
+ defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name);
// For backword compatibility
- defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
- defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
- defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
- defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
- defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
- defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 1);
+ defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 1);
+ defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 1);
+ defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 1);
+ defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 1);
+ defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 1);
}
ReturnedValue DataViewPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int)
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 1e07d85118..6a9f865c0f 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -79,8 +79,8 @@ struct DataViewCtor: FunctionObject
{
V4_OBJECT2(DataViewCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct DataView : Object
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 5bbe312146..3efd626685 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -44,6 +44,7 @@
#include "qv4runtime_p.h"
#include "qv4string_p.h"
#include "qv4jscall_p.h"
+#include "qv4symbol_p.h"
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
@@ -89,9 +90,6 @@ static const double msPerMinute = 60000.0;
static const double msPerHour = 3600000.0;
static const double msPerDay = 86400000.0;
-// The current *standard* time offset, regardless of DST:
-static double LocalTZA = 0.0; // initialized at startup
-
static inline double TimeWithinDay(double t)
{
double r = ::fmod(t, msPerDay);
@@ -318,14 +316,14 @@ static inline double MakeDate(double day, double time)
against the ECMAScript spec is https://github.com/tc39/ecma262/issues/725
*/
-static inline double DaylightSavingTA(double t) // t is a UTC time
+static inline double DaylightSavingTA(double t, double localTZA) // t is a UTC time
{
return QTimeZone::systemTimeZone().offsetFromUtc(
- QDateTime::fromMSecsSinceEpoch(qint64(t), Qt::UTC)) * 1e3 - LocalTZA;
+ QDateTime::fromMSecsSinceEpoch(qint64(t), Qt::UTC)) * 1e3 - localTZA;
}
#else
// This implementation fails to take account of past changes in standard offset.
-static inline double DaylightSavingTA(double t)
+static inline double DaylightSavingTA(double t, double /*localTZA*/)
{
struct tm tmtm;
#if defined(Q_CC_MSVC)
@@ -348,19 +346,19 @@ static inline double DaylightSavingTA(double t)
}
#endif // USE_QTZ_SYSTEM_ZONE
-static inline double LocalTime(double t)
+static inline double LocalTime(double t, double localTZA)
{
// Flawed, yet verbatim from the spec:
- return t + LocalTZA + DaylightSavingTA(t);
+ return t + localTZA + DaylightSavingTA(t, localTZA);
}
// The spec does note [*] that UTC and LocalTime are not quite mutually inverse.
// [*] http://www.ecma-international.org/ecma-262/7.0/index.html#sec-utc-t
-static inline double UTC(double t)
+static inline double UTC(double t, double localTZA)
{
// Flawed, yet verbatim from the spec:
- return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
+ return t - localTZA - DaylightSavingTA(t - localTZA, localTZA);
}
static inline double currentTime()
@@ -377,7 +375,7 @@ static inline double TimeClip(double t)
return Primitive::toInteger(t) + 0;
}
-static inline double ParseString(const QString &s)
+static inline double ParseString(const QString &s, double localTZA)
{
/*
First, try the format defined in ECMA 262's "Date Time String Format";
@@ -533,9 +531,9 @@ static inline double ParseString(const QString &s)
if (seenZ)
t -= offset * offsetSign * 60 * 1000;
else if (seenT) // No zone specified, treat date-time as local time
- t = UTC(t);
+ t = UTC(t, localTZA);
// else: treat plain date as already in UTC
- return t;
+ return TimeClip(t);
}
QDateTime dt = QDateTime::fromString(s, Qt::TextDate);
@@ -605,7 +603,7 @@ static inline double ParseString(const QString &s)
}
if (!dt.isValid())
return qt_qnan();
- return dt.toMSecsSinceEpoch();
+ return TimeClip(dt.toMSecsSinceEpoch());
}
/*!
@@ -621,12 +619,12 @@ static inline QDateTime ToDateTime(double t, Qt::TimeSpec spec)
return QDateTime::fromMSecsSinceEpoch(t, Qt::UTC).toTimeSpec(spec);
}
-static inline QString ToString(double t)
+static inline QString ToString(double t, double localTZA)
{
if (std::isnan(t))
return QStringLiteral("Invalid Date");
QString str = ToDateTime(t, Qt::LocalTime).toString() + QLatin1String(" GMT");
- double tzoffset = LocalTZA + DaylightSavingTA(t);
+ double tzoffset = localTZA + DaylightSavingTA(t, localTZA);
if (tzoffset) {
int hours = static_cast<int>(::fabs(tzoffset) / 1000 / 60 / 60);
int mins = int(::fabs(tzoffset) / 1000 / 60) % 60;
@@ -705,7 +703,7 @@ DEFINE_OBJECT_VTABLE(DateObject);
void Heap::DateObject::init(const QDateTime &date)
{
Object::init();
- this->date = date.isValid() ? date.toMSecsSinceEpoch() : qt_qnan();
+ this->date = date.isValid() ? TimeClip(date.toMSecsSinceEpoch()) : qt_qnan();
}
void Heap::DateObject::init(const QTime &time)
@@ -730,7 +728,7 @@ void Heap::DateObject::init(const QTime &time)
*/
static const double d = MakeDay(1925, 5, 8);
double t = MakeTime(time.hour(), time.minute(), time.second(), time.msec());
- date = TimeClip(UTC(MakeDate(d, t)));
+ date = TimeClip(UTC(MakeDate(d, t), internalClass->engine->localTZA));
}
QDateTime DateObject::toQDateTime() const
@@ -745,15 +743,16 @@ void Heap::DateCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Date"));
}
-ReturnedValue DateCtor::callAsConstructor(const FunctionObject *that, const Value *argv, int argc)
+ReturnedValue DateCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv, int argc, const Value *)
{
+ ExecutionEngine *e = that->engine();
double t = 0;
if (argc == 0)
t = currentTime();
else if (argc == 1) {
- Scope scope(that->engine());
+ Scope scope(e);
ScopedValue arg(scope, argv[0]);
if (DateObject *d = arg->as<DateObject>()) {
t = d->date();
@@ -761,7 +760,7 @@ ReturnedValue DateCtor::callAsConstructor(const FunctionObject *that, const Valu
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
if (String *s = arg->stringValue())
- t = ParseString(s->toQString());
+ t = ParseString(s->toQString(), e->localTZA);
else
t = TimeClip(arg->toNumber());
}
@@ -778,16 +777,17 @@ ReturnedValue DateCtor::callAsConstructor(const FunctionObject *that, const Valu
if (year >= 0 && year <= 99)
year += 1900;
t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms));
- t = TimeClip(UTC(t));
+ t = TimeClip(UTC(t, e->localTZA));
}
- return Encode(that->engine()->newDateObject(Primitive::fromDouble(t)));
+ return Encode(e->newDateObject(Primitive::fromDouble(t)));
}
-ReturnedValue DateCtor::call(const FunctionObject *m, const Value *, const Value *, int)
+ReturnedValue DateCtor::virtualCall(const FunctionObject *m, const Value *, const Value *, int)
{
+ ExecutionEngine *e = m->engine();
double t = currentTime();
- return m->engine()->newString(ToString(t))->asReturnedValue();
+ return e->newString(ToString(t, e->localTZA))->asReturnedValue();
}
void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
@@ -796,7 +796,7 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(7));
- LocalTZA = getLocalTZA();
+ engine->localTZA = getLocalTZA();
ctor->defineDefaultProperty(QStringLiteral("parse"), method_parse, 1);
ctor->defineDefaultProperty(QStringLiteral("UTC"), method_UTC, 7);
@@ -853,15 +853,14 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
QString toGmtString(QStringLiteral("toGMTString"));
ScopedString us(scope, engine->newIdentifier(toUtcString));
ScopedString gs(scope, engine->newIdentifier(toGmtString));
- ExecutionContext *global = engine->rootContext();
- ScopedFunctionObject toUtcGmtStringFn(scope, FunctionObject::createBuiltinFunction(global, us, method_toUTCString));
- toUtcGmtStringFn->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
+ ScopedFunctionObject toUtcGmtStringFn(scope, FunctionObject::createBuiltinFunction(engine, us, method_toUTCString, 0));
defineDefaultProperty(us, toUtcGmtStringFn);
defineDefaultProperty(gs, toUtcGmtStringFn);
}
defineDefaultProperty(QStringLiteral("toISOString"), method_toISOString, 0);
defineDefaultProperty(QStringLiteral("toJSON"), method_toJSON, 1);
+ defineDefaultProperty(engine->symbol_toPrimitive(), method_symbolToPrimitive, 1, Attr_ReadOnly_ButConfigurable);
}
double DatePrototype::getThisDate(ExecutionEngine *v4, const Value *thisObject)
@@ -872,12 +871,12 @@ double DatePrototype::getThisDate(ExecutionEngine *v4, const Value *thisObject)
return 0;
}
-ReturnedValue DatePrototype::method_parse(const FunctionObject *, const Value *, const Value *argv, int argc)
+ReturnedValue DatePrototype::method_parse(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
if (!argc)
return Encode(qt_qnan());
else
- return Encode(ParseString(argv[0].toQString()));
+ return Encode(ParseString(argv[0].toQString(), f->engine()->localTZA));
}
ReturnedValue DatePrototype::method_UTC(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -909,7 +908,7 @@ ReturnedValue DatePrototype::method_toString(const FunctionObject *b, const Valu
{
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
- return Encode(v4->newString(ToString(t)));
+ return Encode(v4->newString(ToString(t, v4->localTZA)));
}
ReturnedValue DatePrototype::method_toDateString(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -966,7 +965,7 @@ ReturnedValue DatePrototype::method_getYear(const FunctionObject *b, const Value
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = YearFromTime(LocalTime(t)) - 1900;
+ t = YearFromTime(LocalTime(t, v4->localTZA)) - 1900;
return Encode(t);
}
@@ -975,7 +974,7 @@ ReturnedValue DatePrototype::method_getFullYear(const FunctionObject *b, const V
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = YearFromTime(LocalTime(t));
+ t = YearFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -993,7 +992,7 @@ ReturnedValue DatePrototype::method_getMonth(const FunctionObject *b, const Valu
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = MonthFromTime(LocalTime(t));
+ t = MonthFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1011,7 +1010,7 @@ ReturnedValue DatePrototype::method_getDate(const FunctionObject *b, const Value
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = DateFromTime(LocalTime(t));
+ t = DateFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1029,7 +1028,7 @@ ReturnedValue DatePrototype::method_getDay(const FunctionObject *b, const Value
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = WeekDay(LocalTime(t));
+ t = WeekDay(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1047,7 +1046,7 @@ ReturnedValue DatePrototype::method_getHours(const FunctionObject *b, const Valu
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = HourFromTime(LocalTime(t));
+ t = HourFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1065,7 +1064,7 @@ ReturnedValue DatePrototype::method_getMinutes(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = MinFromTime(LocalTime(t));
+ t = MinFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1083,7 +1082,7 @@ ReturnedValue DatePrototype::method_getSeconds(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = SecFromTime(LocalTime(t));
+ t = SecFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1101,7 +1100,7 @@ ReturnedValue DatePrototype::method_getMilliseconds(const FunctionObject *b, con
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = msFromTime(LocalTime(t));
+ t = msFromTime(LocalTime(t, v4->localTZA));
return Encode(t);
}
@@ -1119,7 +1118,7 @@ ReturnedValue DatePrototype::method_getTimezoneOffset(const FunctionObject *b, c
ExecutionEngine *v4 = b->engine();
double t = getThisDate(v4, thisObject);
if (!std::isnan(t))
- t = (t - LocalTime(t)) / msPerMinute;
+ t = (t - LocalTime(t, v4->localTZA)) / msPerMinute;
return Encode(t);
}
@@ -1144,13 +1143,13 @@ ReturnedValue DatePrototype::method_setMilliseconds(const FunctionObject *b, con
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
double ms = argc ? argv[0].toNumber() : qt_qnan();
if (v4->hasException)
return QV4::Encode::undefined();
- self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)), v4->localTZA)));
return Encode(self->date());
}
@@ -1178,7 +1177,7 @@ ReturnedValue DatePrototype::method_setSeconds(const FunctionObject *b, const Va
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
double sec = argc ? argv[0].toNumber() : qt_qnan();
@@ -1187,7 +1186,7 @@ ReturnedValue DatePrototype::method_setSeconds(const FunctionObject *b, const Va
double ms = (argc < 2) ? msFromTime(t) : argv[1].toNumber();
if (v4->hasException)
return QV4::Encode::undefined();
- t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
+ t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)), v4->localTZA));
self->setDate(t);
return Encode(self->date());
}
@@ -1214,7 +1213,7 @@ ReturnedValue DatePrototype::method_setMinutes(const FunctionObject *b, const Va
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
double min = argc ? argv[0].toNumber() : qt_qnan();
@@ -1226,7 +1225,7 @@ ReturnedValue DatePrototype::method_setMinutes(const FunctionObject *b, const Va
double ms = (argc < 3) ? msFromTime(t) : argv[2].toNumber();
if (v4->hasException)
return QV4::Encode::undefined();
- t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
+ t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)), v4->localTZA));
self->setDate(t);
return Encode(self->date());
}
@@ -1254,7 +1253,7 @@ ReturnedValue DatePrototype::method_setHours(const FunctionObject *b, const Valu
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
double hour = argc ? argv[0].toNumber() : qt_qnan();
@@ -1269,7 +1268,7 @@ ReturnedValue DatePrototype::method_setHours(const FunctionObject *b, const Valu
double ms = (argc < 4) ? msFromTime(t) : argv[3].toNumber();
if (v4->hasException)
return QV4::Encode::undefined();
- t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
+ t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)), v4->localTZA));
self->setDate(t);
return Encode(self->date());
}
@@ -1298,13 +1297,13 @@ ReturnedValue DatePrototype::method_setDate(const FunctionObject *b, const Value
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
double date = argc ? argv[0].toNumber() : qt_qnan();
if (v4->hasException)
return QV4::Encode::undefined();
- t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
+ t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)), v4->localTZA));
self->setDate(t);
return Encode(self->date());
}
@@ -1334,7 +1333,7 @@ ReturnedValue DatePrototype::method_setMonth(const FunctionObject *b, const Valu
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
double month = argc ? argv[0].toNumber() : qt_qnan();
@@ -1343,7 +1342,7 @@ ReturnedValue DatePrototype::method_setMonth(const FunctionObject *b, const Valu
double date = (argc < 2) ? DateFromTime(t) : argv[1].toNumber();
if (v4->hasException)
return QV4::Encode::undefined();
- t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
+ t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)), v4->localTZA));
self->setDate(t);
return Encode(self->date());
}
@@ -1374,7 +1373,7 @@ ReturnedValue DatePrototype::method_setYear(const FunctionObject *b, const Value
if (std::isnan(t))
t = 0;
else
- t = LocalTime(t);
+ t = LocalTime(t, v4->localTZA);
double year = argc ? argv[0].toNumber() : qt_qnan();
double r;
if (std::isnan(year)) {
@@ -1383,7 +1382,7 @@ ReturnedValue DatePrototype::method_setYear(const FunctionObject *b, const Value
if ((Primitive::toInteger(year) >= 0) && (Primitive::toInteger(year) <= 99))
year += 1900;
r = MakeDay(year, MonthFromTime(t), DateFromTime(t));
- r = UTC(MakeDate(r, TimeWithinDay(t)));
+ r = UTC(MakeDate(r, TimeWithinDay(t)), v4->localTZA);
r = TimeClip(r);
}
self->setDate(r);
@@ -1413,7 +1412,7 @@ ReturnedValue DatePrototype::method_setFullYear(const FunctionObject *b, const V
if (!self)
return v4->throwTypeError();
- double t = LocalTime(self->date());
+ double t = LocalTime(self->date(), v4->localTZA);
if (v4->hasException)
return QV4::Encode::undefined();
if (std::isnan(t))
@@ -1427,7 +1426,7 @@ ReturnedValue DatePrototype::method_setFullYear(const FunctionObject *b, const V
double date = (argc < 3) ? DateFromTime(t) : argv[2].toNumber();
if (v4->hasException)
return QV4::Encode::undefined();
- t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
+ t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)), v4->localTZA));
self->setDate(t);
return Encode(self->date());
}
@@ -1471,7 +1470,7 @@ ReturnedValue DatePrototype::method_toISOString(const FunctionObject *b, const V
int year = (int)YearFromTime(t);
if (year < 0 || year > 9999) {
if (qAbs(year) >= 1000000)
- RETURN_RESULT(v4->newString(QStringLiteral("Invalid Date")));
+ RETURN_RESULT(v4->throwRangeError(*thisObject));
result += year < 0 ? QLatin1Char('-') : QLatin1Char('+');
year = qAbs(year);
addZeroPrefixedInt(result, year, 6);
@@ -1518,7 +1517,23 @@ ReturnedValue DatePrototype::method_toJSON(const FunctionObject *b, const Value
return toIso->call(O, nullptr, 0);
}
-void DatePrototype::timezoneUpdated()
+ReturnedValue DatePrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *e = f->engine();
+ if (!thisObject->isObject() || !argc || !argv->isString())
+ return e->throwTypeError();
+
+ String *hint = argv->stringValue();
+ PropertyKey id = hint->toPropertyKey();
+ if (id == e->id_default()->propertyKey())
+ hint = e->id_string();
+ else if (id != e->id_string()->propertyKey() && id != e->id_number()->propertyKey())
+ return e->throwTypeError();
+
+ return RuntimeHelpers::ordinaryToPrimitive(e, static_cast<const Object *>(thisObject), hint);
+}
+
+void DatePrototype::timezoneUpdated(ExecutionEngine *e)
{
- LocalTZA = getLocalTZA();
+ e->localTZA = getLocalTZA();
}
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 2b9a580288..5b9934282c 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -101,15 +101,15 @@ struct DateObject: Object {
template<>
inline const DateObject *Value::as() const {
- return isManaged() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr;
+ return isManaged() && m()->internalClass->vtable->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr;
}
struct DateCtor: FunctionObject
{
V4_OBJECT2(DateCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int);
};
struct DatePrototype: Object
@@ -169,8 +169,9 @@ struct DatePrototype: Object
static ReturnedValue method_toUTCString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toISOString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toJSON(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int);
- static void timezoneUpdated();
+ static void timezoneUpdated(ExecutionEngine *e);
};
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 0ed0df89a9..f9ef6b45a1 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -42,6 +42,9 @@
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
+#include <qv4setiterator_p.h>
+#include <qv4mapiterator_p.h>
+#include <qv4arrayiterator_p.h>
#include <qv4arrayobject_p.h>
#include <qv4booleanobject_p.h>
#include <qv4globalobject_p.h>
@@ -52,6 +55,9 @@
#include <qv4numberobject_p.h>
#include <qv4regexpobject_p.h>
#include <qv4regexp_p.h>
+#include "qv4symbol_p.h"
+#include "qv4setobject_p.h"
+#include "qv4mapobject_p.h"
#include <qv4variantobject_p.h>
#include <qv4runtime_p.h>
#include <private/qv4mm_p.h>
@@ -63,7 +69,17 @@
#include "qv4debugging_p.h"
#include "qv4profiling_p.h"
#include "qv4executableallocator_p.h"
+#include "qv4iterator_p.h"
+#include "qv4stringiterator_p.h"
+#include "qv4generatorobject_p.h"
+#include "qv4reflect_p.h"
+#include "qv4proxy_p.h"
+#include "qv4stackframe_p.h"
+
+#if QT_CONFIG(qml_sequence_object)
#include "qv4sequenceobject_p.h"
+#endif
+
#include "qv4qobjectwrapper_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraybuffer_p.h"
@@ -76,7 +92,9 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qqmllistwrapper_p.h>
#include <private/qqmllist_p.h>
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <QtCore/QTextStream>
#include <QDateTime>
@@ -110,7 +128,7 @@ ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const
#ifdef V4_BOOTSTRAP
QJSEngine *ExecutionEngine::jsEngine() const
{
- return v8Engine->publicEngine();
+ return publicEngine;
}
QQmlEngine *ExecutionEngine::qmlEngine() const
@@ -121,7 +139,7 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
qint32 ExecutionEngine::maxCallDepth = -1;
-ExecutionEngine::ExecutionEngine()
+ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
@@ -129,6 +147,7 @@ ExecutionEngine::ExecutionEngine()
, gcStack(new WTF::PageAllocation)
, globalCode(nullptr)
, v8Engine(nullptr)
+ , publicEngine(jsEngine)
, argumentsAccessors(nullptr)
, nArgumentsAccessors(0)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
@@ -181,27 +200,44 @@ ExecutionEngine::ExecutionEngine()
}
exceptionValue = jsAlloca(1);
+ *exceptionValue = Encode::undefined();
globalObject = static_cast<Object *>(jsAlloca(1));
jsObjects = jsAlloca(NJSObjects);
typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
jsStrings = jsAlloca(NJSStrings);
+ jsSymbols = jsAlloca(NJSSymbols);
// set up stack limits
jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);
identifierTable = new IdentifierTable(this);
- classPool = new InternalClassPool;
+ memset(classes, 0, sizeof(classes));
+ classes[Class_Empty] = memoryManager->allocIC<InternalClass>();
+ classes[Class_Empty]->init(this);
- internalClasses[Class_Empty] = new (classPool) InternalClass(this);
- internalClasses[Class_String] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::String::staticVTable());
- internalClasses[Class_MemberData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::MemberData::staticVTable());
- internalClasses[Class_SimpleArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
- internalClasses[Class_SparseArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
- internalClasses[Class_ExecutionContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
- internalClasses[Class_QmlContext] = internalClasses[EngineBase::Class_ExecutionContext]->changeVTable(QV4::QmlContext::staticVTable());
- internalClasses[Class_CallContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
+ classes[Class_MemberData] = classes[Class_Empty]->changeVTable(QV4::MemberData::staticVTable());
+ classes[Class_SimpleArrayData] = classes[Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
+ classes[Class_SparseArrayData] = classes[Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
+ classes[Class_ExecutionContext] = classes[Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
+ classes[Class_CallContext] = classes[Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
+ classes[Class_QmlContext] = classes[Class_Empty]->changeVTable(QV4::QmlContext::staticVTable());
+
+ Scope scope(this);
+ Scoped<InternalClass> ic(scope);
+ ic = classes[Class_Empty]->changeVTable(QV4::Object::staticVTable());
+ jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic->d());
+ classes[Class_Object] = ic->changePrototype(objectPrototype()->d());
+ classes[Class_QmlContextWrapper] = classes[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
+
+ ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
+ jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic->d(), /*init =*/ false);
+ classes[Class_String] = classes[Class_Empty]->changeVTable(QV4::String::staticVTable())->changePrototype(stringPrototype()->d());
+ Q_ASSERT(stringPrototype()->d() && classes[Class_String]->prototype);
+
+ jsObjects[SymbolProto] = memoryManager->allocate<SymbolPrototype>();
+ classes[Class_Symbol] = classes[EngineBase::Class_Empty]->changeVTable(QV4::Symbol::staticVTable())->changePrototype(symbolPrototype()->d());
jsStrings[String_Empty] = newIdentifier(QString());
jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
@@ -211,6 +247,8 @@ ExecutionEngine::ExecutionEngine()
jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean"));
jsStrings[String_number] = newIdentifier(QStringLiteral("number"));
jsStrings[String_string] = newIdentifier(QStringLiteral("string"));
+ jsStrings[String_default] = newIdentifier(QStringLiteral("default"));
+ jsStrings[String_symbol] = newIdentifier(QStringLiteral("symbol"));
jsStrings[String_object] = newIdentifier(QStringLiteral("object"));
jsStrings[String_function] = newIdentifier(QStringLiteral("function"));
jsStrings[String_length] = newIdentifier(QStringLiteral("length"));
@@ -239,141 +277,186 @@ ExecutionEngine::ExecutionEngine()
jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
-
- InternalClass *ic = internalClasses[Class_Empty]->changeVTable(QV4::Object::staticVTable());
- jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic);
- internalClasses[Class_Object] = ic->changePrototype(objectPrototype()->d());
- internalClasses[EngineBase::Class_QmlContextWrapper] = internalClasses[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
+ jsStrings[String_next] = newIdentifier(QStringLiteral("next"));
+ jsStrings[String_done] = newIdentifier(QStringLiteral("done"));
+ jsStrings[String_return] = newIdentifier(QStringLiteral("return"));
+
+ jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance"));
+ jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable"));
+ jsSymbols[Symbol_iterator] = Symbol::create(this, QStringLiteral("@Symbol.iterator"));
+ jsSymbols[Symbol_match] = Symbol::create(this, QStringLiteral("@Symbol.match"));
+ jsSymbols[Symbol_replace] = Symbol::create(this, QStringLiteral("@Symbol.replace"));
+ jsSymbols[Symbol_search] = Symbol::create(this, QStringLiteral("@Symbol.search"));
+ jsSymbols[Symbol_species] = Symbol::create(this, QStringLiteral("@Symbol.species"));
+ jsSymbols[Symbol_split] = Symbol::create(this, QStringLiteral("@Symbol.split"));
+ jsSymbols[Symbol_toPrimitive] = Symbol::create(this, QStringLiteral("@Symbol.toPrimitive"));
+ jsSymbols[Symbol_toStringTag] = Symbol::create(this, QStringLiteral("@Symbol.toStringTag"));
+ jsSymbols[Symbol_unscopables] = Symbol::create(this, QStringLiteral("@Symbol.unscopables"));
+ jsSymbols[Symbol_revokableProxy] = Symbol::create(this, QStringLiteral("@Proxy.revokableProxy"));
ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
- Q_ASSERT(ic->prototype);
- ic = ic->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
- Q_ASSERT(ic->prototype);
- jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(ic, objectPrototype());
- internalClasses[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d());
- jsObjects[PropertyListProto] = memoryManager->allocObject<PropertyListPrototype>();
-
- InternalClass *argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype());
- argsClass = argsClass->addMember(id_length(), Attr_NotEnumerable);
- internalClasses[EngineBase::Class_ArgumentsObject] = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
+ Q_ASSERT(ic->d()->prototype);
+ ic = ic->addMember(id_length()->propertyKey(), Attr_NotConfigurable|Attr_NotEnumerable);
+ Q_ASSERT(ic->d()->prototype);
+ jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(ic->d());
+ classes[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d());
+ jsObjects[PropertyListProto] = memoryManager->allocate<PropertyListPrototype>();
+
+ Scoped<InternalClass> argsClass(scope);
+ argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype());
+ argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
+ argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
+ classes[Class_ArgumentsObject] = argsClass->addMember(id_callee()->propertyKey(), Attr_Data|Attr_NotEnumerable);
argsClass = newInternalClass(StrictArgumentsObject::staticVTable(), objectPrototype());
- argsClass = argsClass->addMember(id_length(), Attr_NotEnumerable);
- argsClass = argsClass->addMember(id_callee(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- internalClasses[EngineBase::Class_StrictArgumentsObject] = argsClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ argsClass = argsClass->addMember(id_length()->propertyKey(), Attr_NotEnumerable);
+ argsClass = argsClass->addMember(symbol_iterator()->propertyKey(), Attr_Data|Attr_NotEnumerable);
+ classes[Class_StrictArgumentsObject] = argsClass->addMember(id_callee()->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
*static_cast<Value *>(globalObject) = newObject();
Q_ASSERT(globalObject->d()->vtable());
initRootContext();
ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype());
- ic = ic->addMember(id_length(), Attr_ReadOnly);
- jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic);
- internalClasses[Class_StringObject] = ic->changePrototype(stringPrototype()->d());
- Q_ASSERT(internalClasses[EngineBase::Class_StringObject]->find(id_length()) == Heap::StringObject::LengthPropertyIndex);
+ ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly);
+ classes[Class_StringObject] = ic->changePrototype(stringPrototype()->d());
+ Q_ASSERT(classes[Class_StringObject]->find(id_length()->propertyKey()) == Heap::StringObject::LengthPropertyIndex);
- jsObjects[NumberProto] = memoryManager->allocObject<NumberPrototype>();
- jsObjects[BooleanProto] = memoryManager->allocObject<BooleanPrototype>();
- jsObjects[DateProto] = memoryManager->allocObject<DatePrototype>();
+ classes[Class_SymbolObject] = newInternalClass(QV4::SymbolObject::staticVTable(), symbolPrototype());
+
+ jsObjects[NumberProto] = memoryManager->allocate<NumberPrototype>();
+ jsObjects[BooleanProto] = memoryManager->allocate<BooleanPrototype>();
+ jsObjects[DateProto] = memoryManager->allocate<DatePrototype>();
uint index;
ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype());
- ic = ic->addMember(id_prototype(), Attr_NotEnumerable, &index);
+ ic = ic->addMember(id_prototype()->propertyKey(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic, objectPrototype());
+ jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic->d());
ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype());
- ic = ic->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ ic = ic->addMember(id_prototype()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- internalClasses[EngineBase::Class_FunctionObject] = ic;
- ic = ic->addMember(id_name(), Attr_ReadOnly, &index);
+ classes[Class_FunctionObject] = ic->d();
+ ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::ScriptFunction::Index_Name);
ic = ic->changeVTable(ScriptFunction::staticVTable());
- internalClasses[EngineBase::Class_ScriptFunction] = ic->addMember(id_length(), Attr_ReadOnly, &index);
+ ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, &index);
Q_ASSERT(index == Heap::ScriptFunction::Index_Length);
- internalClasses[EngineBase::Class_ObjectProto] = internalClasses[Class_Object]->addMember(id_constructor(), Attr_NotEnumerable, &index);
+ classes[Class_ScriptFunction] = ic->d();
+ ic = ic->changeVTable(ConstructorFunction::staticVTable());
+ classes[Class_ConstructorFunction] = ic->d();
+ ic = ic->changeVTable(MemberFunction::staticVTable());
+ classes[Class_MemberFunction] = ic->d();
+ ic = ic->changeVTable(GeneratorFunction::staticVTable());
+ classes[Class_MemberFunction] = ic->d();
+ ic = ic->changeVTable(GeneratorFunction::staticVTable());
+ classes[Class_GeneratorFunction] = ic->d();
+ ic = ic->changeVTable(MemberGeneratorFunction::staticVTable());
+ classes[Class_MemberGeneratorFunction] = ic->d();
+ classes[Class_ObjectProto] = classes[Class_Object]->addMember(id_constructor()->propertyKey(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- Scope scope(this);
+ jsObjects[GeneratorProto] = memoryManager->allocObject<GeneratorPrototype>(classes[Class_Object]);
+ classes[Class_GeneratorObject] = newInternalClass(QV4::GeneratorObject::staticVTable(), generatorPrototype());
+
ScopedString str(scope);
- internalClasses[Class_RegExp] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::RegExp::staticVTable());
+ classes[Class_RegExp] = classes[Class_Empty]->changeVTable(QV4::RegExp::staticVTable());
ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype());
- ic = ic->addMember(id_lastIndex(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == RegExpObject::Index_LastIndex);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("source"))), Attr_ReadOnly, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("source")))->propertyKey(), Attr_ReadOnly, &index);
Q_ASSERT(index == RegExpObject::Index_Source);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("global"))), Attr_ReadOnly, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("global")))->propertyKey(), Attr_ReadOnly, &index);
Q_ASSERT(index == RegExpObject::Index_Global);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("ignoreCase"))), Attr_ReadOnly, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("ignoreCase")))->propertyKey(), Attr_ReadOnly, &index);
Q_ASSERT(index == RegExpObject::Index_IgnoreCase);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("multiline"))), Attr_ReadOnly, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("multiline")))->propertyKey(), Attr_ReadOnly, &index);
Q_ASSERT(index == RegExpObject::Index_Multiline);
- jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(ic, objectPrototype());
- internalClasses[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
+ jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(ic->d());
+ classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
- ic = internalClasses[Class_ArrayObject]->addMember(id_index(), Attr_Data, &index);
+ ic = classes[Class_ArrayObject]->addMember(id_index()->propertyKey(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
- internalClasses[EngineBase::Class_RegExpExecArray] = ic->addMember(id_input(), Attr_Data, &index);
+ classes[Class_RegExpExecArray] = ic->addMember(id_input()->propertyKey(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
ic = newInternalClass(ErrorObject::staticVTable(), nullptr);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("stack"))), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("stack")))->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorObject::Index_Stack);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName"))), Attr_Data|Attr_NotEnumerable, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorObject::Index_FileName);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber"))), Attr_Data|Attr_NotEnumerable, &index);
- internalClasses[EngineBase::Class_ErrorObject] = ic;
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
+ classes[Class_ErrorObject] = ic->d();
Q_ASSERT(index == ErrorObject::Index_LineNumber);
- internalClasses[EngineBase::Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ classes[Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorObject::Index_Message);
ic = newInternalClass(ErrorObject::staticVTable(), objectPrototype());
- ic = ic->addMember(id_constructor(), Attr_Data|Attr_NotEnumerable, &index);
+ ic = ic->addMember(id_constructor()->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorPrototype::Index_Constructor);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorPrototype::Index_Message);
- internalClasses[EngineBase::Class_ErrorProto] = ic->addMember(id_name(), Attr_Data|Attr_NotEnumerable, &index);
+ classes[Class_ErrorProto] = ic->addMember(id_name()->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorPrototype::Index_Name);
- jsObjects[GetStack_Function] = FunctionObject::createBuiltinFunction(rootContext(), str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack);
- getStackFunction()->defineReadonlyProperty(id_length(), Primitive::fromInt32(0));
+ classes[Class_ProxyObject] = classes[Class_Empty]->changeVTable(ProxyObject::staticVTable());
+
+ jsObjects[GetStack_Function] = FunctionObject::createBuiltinFunction(this, str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack, 0);
- jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto], objectPrototype());
- jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype());
- jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype());
- jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype());
- jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype());
- jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype());
- jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype());
+ jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(classes[Class_ErrorProto]);
+ ic = classes[Class_ErrorProto]->changePrototype(errorPrototype()->d());
+ jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(ic->d());
+ jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(ic->d());
+ jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(ic->d());
+ jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(ic->d());
+ jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(ic->d());
+ jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(ic->d());
- jsObjects[VariantProto] = memoryManager->allocObject<VariantPrototype>();
- Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
+ jsObjects[VariantProto] = memoryManager->allocate<VariantPrototype>();
+ Q_ASSERT(variantPrototype()->getPrototypeOf() == objectPrototype()->d());
+#if QT_CONFIG(qml_sequence_object)
ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this));
- jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(ic, SequencePrototype::defaultPrototype(this)));
+ jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(ic->d()));
+#endif
ExecutionContext *global = rootContext();
- jsObjects[Object_Ctor] = memoryManager->allocObject<ObjectCtor>(global);
- jsObjects[String_Ctor] = memoryManager->allocObject<StringCtor>(global);
- jsObjects[Number_Ctor] = memoryManager->allocObject<NumberCtor>(global);
- jsObjects[Boolean_Ctor] = memoryManager->allocObject<BooleanCtor>(global);
- jsObjects[Array_Ctor] = memoryManager->allocObject<ArrayCtor>(global);
- jsObjects[Function_Ctor] = memoryManager->allocObject<FunctionCtor>(global);
- jsObjects[Date_Ctor] = memoryManager->allocObject<DateCtor>(global);
- jsObjects[RegExp_Ctor] = memoryManager->allocObject<RegExpCtor>(global);
- jsObjects[Error_Ctor] = memoryManager->allocObject<ErrorCtor>(global);
- jsObjects[EvalError_Ctor] = memoryManager->allocObject<EvalErrorCtor>(global);
- jsObjects[RangeError_Ctor] = memoryManager->allocObject<RangeErrorCtor>(global);
- jsObjects[ReferenceError_Ctor] = memoryManager->allocObject<ReferenceErrorCtor>(global);
- jsObjects[SyntaxError_Ctor] = memoryManager->allocObject<SyntaxErrorCtor>(global);
- jsObjects[TypeError_Ctor] = memoryManager->allocObject<TypeErrorCtor>(global);
- jsObjects[URIError_Ctor] = memoryManager->allocObject<URIErrorCtor>(global);
+
+ jsObjects[Object_Ctor] = memoryManager->allocate<ObjectCtor>(global);
+ jsObjects[String_Ctor] = memoryManager->allocate<StringCtor>(global);
+ jsObjects[Symbol_Ctor] = memoryManager->allocate<SymbolCtor>(global);
+ jsObjects[Number_Ctor] = memoryManager->allocate<NumberCtor>(global);
+ jsObjects[Boolean_Ctor] = memoryManager->allocate<BooleanCtor>(global);
+ jsObjects[Array_Ctor] = memoryManager->allocate<ArrayCtor>(global);
+ jsObjects[Function_Ctor] = memoryManager->allocate<FunctionCtor>(global);
+ jsObjects[GeneratorFunction_Ctor] = memoryManager->allocate<GeneratorFunctionCtor>(global);
+ jsObjects[Date_Ctor] = memoryManager->allocate<DateCtor>(global);
+ jsObjects[RegExp_Ctor] = memoryManager->allocate<RegExpCtor>(global);
+ jsObjects[Error_Ctor] = memoryManager->allocate<ErrorCtor>(global);
+ jsObjects[EvalError_Ctor] = memoryManager->allocate<EvalErrorCtor>(global);
+ jsObjects[RangeError_Ctor] = memoryManager->allocate<RangeErrorCtor>(global);
+ jsObjects[ReferenceError_Ctor] = memoryManager->allocate<ReferenceErrorCtor>(global);
+ jsObjects[SyntaxError_Ctor] = memoryManager->allocate<SyntaxErrorCtor>(global);
+ jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(global);
+ jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global);
+ jsObjects[IteratorProto] = memoryManager->allocate<IteratorPrototype>();
+ jsObjects[ForInIteratorProto] = memoryManager->allocObject<ForInIteratorPrototype>(newInternalClass(ForInIteratorPrototype::staticVTable(), iteratorPrototype()));
+ jsObjects[MapIteratorProto] = memoryManager->allocObject<MapIteratorPrototype>(newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype()));
+ jsObjects[SetIteratorProto] = memoryManager->allocObject<SetIteratorPrototype>(newInternalClass(SetIteratorPrototype::staticVTable(), iteratorPrototype()));
+ jsObjects[ArrayIteratorProto] = memoryManager->allocObject<ArrayIteratorPrototype>(newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype()));
+ jsObjects[StringIteratorProto] = memoryManager->allocObject<StringIteratorPrototype>(newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype()));
+
+ str = newString(QStringLiteral("get [Symbol.species]"));
+ jsObjects[GetSymbolSpecies] = FunctionObject::createBuiltinFunction(this, str, ArrayPrototype::method_get_species, 0);
static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
+ static_cast<SymbolPrototype *>(symbolPrototype())->init(this, symbolCtor());
static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
static_cast<PropertyListPrototype *>(propertyListPrototype())->init(this);
static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
+ static_cast<GeneratorPrototype *>(generatorPrototype())->init(this, generatorFunctionCtor());
static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
@@ -383,25 +466,47 @@ ExecutionEngine::ExecutionEngine()
static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
+ static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
+ static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
+ static_cast<MapIteratorPrototype *>(mapIteratorPrototype())->init(this);
+ static_cast<SetIteratorPrototype *>(setIteratorPrototype())->init(this);
+ static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this);
+ static_cast<StringIteratorPrototype *>(stringIteratorPrototype())->init(this);
+
static_cast<VariantPrototype *>(variantPrototype())->init();
+
+#if QT_CONFIG(qml_sequence_object)
sequencePrototype()->cast<SequencePrototype>()->init();
+#endif
+
+ jsObjects[Map_Ctor] = memoryManager->allocate<MapCtor>(global);
+ jsObjects[MapProto] = memoryManager->allocate<MapPrototype>();
+ static_cast<MapPrototype *>(mapPrototype())->init(this, mapCtor());
+ jsObjects[Set_Ctor] = memoryManager->allocate<SetCtor>(global);
+ jsObjects[SetProto] = memoryManager->allocate<SetPrototype>();
+ static_cast<SetPrototype *>(setPrototype())->init(this, setCtor());
// typed arrays
- jsObjects[ArrayBuffer_Ctor] = memoryManager->allocObject<ArrayBufferCtor>(global);
- jsObjects[ArrayBufferProto] = memoryManager->allocObject<ArrayBufferPrototype>();
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->allocate<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->allocate<ArrayBufferPrototype>();
static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- jsObjects[DataView_Ctor] = memoryManager->allocObject<DataViewCtor>(global);
- jsObjects[DataViewProto] = memoryManager->allocObject<DataViewPrototype>();
+ jsObjects[DataView_Ctor] = memoryManager->allocate<DataViewCtor>(global);
+ jsObjects[DataViewProto] = memoryManager->allocate<DataViewPrototype>();
static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
jsObjects[ValueTypeProto] = (Heap::Base *) nullptr;
jsObjects[SignalHandlerProto] = (Heap::Base *) nullptr;
+ jsObjects[IntrinsicTypedArray_Ctor] = memoryManager->allocate<IntrinsicTypedArrayCtor>(global);
+ jsObjects[IntrinsicTypedArrayProto] = memoryManager->allocate<IntrinsicTypedArrayPrototype>();
+ static_cast<IntrinsicTypedArrayPrototype *>(intrinsicTypedArrayPrototype())
+ ->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor()));
+
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
- static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocObject<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocObject<TypedArrayPrototype>(Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i));
typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
}
@@ -413,6 +518,7 @@ ExecutionEngine::ExecutionEngine()
globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Symbol"), *symbolCtor());
FunctionObject *numberObject = numberCtor();
globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberObject);
globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
@@ -430,18 +536,23 @@ ExecutionEngine::ExecutionEngine()
globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Set"), *setCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Map"), *mapCtor());
+
for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]);
ScopedObject o(scope);
- globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocObject<MathObject>()));
- globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocObject<JsonObject>()));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocate<MathObject>()));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocate<JsonObject>()));
+ globalObject->defineDefaultProperty(QStringLiteral("Reflect"), (o = memoryManager->allocate<Reflect>()));
+ globalObject->defineDefaultProperty(QStringLiteral("Proxy"), (o = memoryManager->allocate<Proxy>(rootContext())));
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
- jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global);
+ jsObjects[Eval_Function] = memoryManager->allocate<EvalFunction>(global);
globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
// ES6: 20.1.2.12 & 20.1.2.13:
@@ -453,11 +564,8 @@ ExecutionEngine::ExecutionEngine()
Scope scope(this);
ScopedString pi(scope, newIdentifier(piString));
ScopedString pf(scope, newIdentifier(pfString));
- ExecutionContext *global = rootContext();
- ScopedFunctionObject parseIntFn(scope, FunctionObject::createBuiltinFunction(global, pi, GlobalFunctions::method_parseInt));
- ScopedFunctionObject parseFloatFn(scope, FunctionObject::createBuiltinFunction(global, pf, GlobalFunctions::method_parseFloat));
- parseIntFn->defineReadonlyConfigurableProperty(id_length(), Primitive::fromInt32(2));
- parseFloatFn->defineReadonlyConfigurableProperty(id_length(), Primitive::fromInt32(1));
+ ScopedFunctionObject parseIntFn(scope, FunctionObject::createBuiltinFunction(this, pi, GlobalFunctions::method_parseInt, 2));
+ ScopedFunctionObject parseFloatFn(scope, FunctionObject::createBuiltinFunction(this, pf, GlobalFunctions::method_parseFloat, 1));
globalObject->defineDefaultProperty(piString, parseIntFn);
globalObject->defineDefaultProperty(pfString, parseFloatFn);
numberObject->defineDefaultProperty(piString, parseIntFn);
@@ -473,8 +581,16 @@ ExecutionEngine::ExecutionEngine()
globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
- ScopedString name(scope, newString(QStringLiteral("thrower")));
- jsObjects[ThrowerObject] = FunctionObject::createBuiltinFunction(global, name, ::throwTypeError);
+ ScopedFunctionObject t(scope, memoryManager->allocate<FunctionObject>(rootContext(), nullptr, ::throwTypeError));
+ t->defineReadonlyProperty(id_length(), Primitive::fromInt32(0));
+ t->setInternalClass(t->internalClass()->frozen());
+ jsObjects[ThrowerObject] = t;
+
+ ScopedProperty pd(scope);
+ pd->value = thrower();
+ pd->set = thrower();
+ functionPrototype()->insertMember(id_caller(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
+ functionPrototype()->insertMember(id_arguments(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
}
ExecutionEngine::~ExecutionEngine()
@@ -487,8 +603,6 @@ ExecutionEngine::~ExecutionEngine()
while (!compilationUnits.isEmpty())
(*compilationUnits.begin())->unlink();
- internalClasses[Class_Empty]->destroy();
- delete classPool;
delete bumperPointerAllocator;
delete regExpCache;
delete regExpAllocator;
@@ -500,6 +614,11 @@ ExecutionEngine::~ExecutionEngine()
delete [] argumentsAccessors;
}
+ExecutionContext *ExecutionEngine::currentContext() const
+{
+ return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
+}
+
#if QT_CONFIG(qml_debug)
void ExecutionEngine::setDebugger(Debugging::Debugger *debugger)
{
@@ -521,59 +640,71 @@ void ExecutionEngine::initRootContext()
r->d_unchecked()->init(Heap::ExecutionContext::Type_GlobalContext);
r->d()->activation.set(this, globalObject->d());
jsObjects[RootContext] = r;
+ jsObjects[ScriptContext] = r;
jsObjects[IntegerNull] = Encode((int)0);
}
-InternalClass *ExecutionEngine::newClass(const InternalClass &other)
+Heap::InternalClass *ExecutionEngine::newClass(Heap::InternalClass *other)
{
- return new (classPool) InternalClass(other);
+ Heap::InternalClass *ic = memoryManager->allocIC<InternalClass>();
+ ic->init(other);
+ return ic;
}
-InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype)
+Heap::InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype)
{
- return internalClasses[EngineBase::Class_Empty]->changeVTable(vtable)->changePrototype(prototype ? prototype->d() : nullptr);
+ Scope scope(this);
+ Scoped<InternalClass> ic(scope, internalClasses(Class_Empty)->changeVTable(vtable));
+ return ic->changePrototype(prototype ? prototype->d() : nullptr);
}
Heap::Object *ExecutionEngine::newObject()
{
- return memoryManager->allocObject<Object>();
+ return memoryManager->allocate<Object>();
}
-Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype)
+Heap::Object *ExecutionEngine::newObject(Heap::InternalClass *internalClass)
{
- return memoryManager->allocObject<Object>(internalClass, prototype);
+ return memoryManager->allocObject<Object>(internalClass);
}
Heap::String *ExecutionEngine::newString(const QString &s)
{
- Scope scope(this);
- return ScopedString(scope, memoryManager->allocWithStringData<String>(s.length() * sizeof(QChar), s))->d();
+ return memoryManager->allocWithStringData<String>(s.length() * sizeof(QChar), s);
}
Heap::String *ExecutionEngine::newIdentifier(const QString &text)
{
- return identifierTable->insertString(text);
+ Scope scope(this);
+ ScopedString s(scope, memoryManager->allocWithStringData<String>(text.length() * sizeof(QChar), text));
+ s->toPropertyKey();
+ return s->d();
}
Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
- return memoryManager->allocObject<StringObject>(string);
+ return memoryManager->allocate<StringObject>(string);
+}
+
+Heap::Object *ExecutionEngine::newSymbolObject(const Symbol *symbol)
+{
+ return memoryManager->allocObject<SymbolObject>(classes[Class_SymbolObject], symbol);
}
Heap::Object *ExecutionEngine::newNumberObject(double value)
{
- return memoryManager->allocObject<NumberObject>(value);
+ return memoryManager->allocate<NumberObject>(value);
}
Heap::Object *ExecutionEngine::newBooleanObject(bool b)
{
- return memoryManager->allocObject<BooleanObject>(b);
+ return memoryManager->allocate<BooleanObject>(b);
}
Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>());
+ ScopedArrayObject object(scope, memoryManager->allocate<ArrayObject>());
if (count) {
if (count < 0x1000)
@@ -586,7 +717,7 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int length)
{
Scope scope(this);
- ScopedArrayObject a(scope, memoryManager->allocObject<ArrayObject>());
+ ScopedArrayObject a(scope, memoryManager->allocate<ArrayObject>());
if (length) {
size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
@@ -607,45 +738,41 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int leng
Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
{
- Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(list));
- return object->d();
+ return memoryManager->allocate<ArrayObject>(list);
}
-Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *internalClass, Object *prototype)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(Heap::InternalClass *internalClass)
{
- Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(internalClass, prototype));
- return object->d();
+ return memoryManager->allocObject<ArrayObject>(internalClass);
}
Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
{
- return memoryManager->allocObject<ArrayBuffer>(array);
+ return memoryManager->allocate<ArrayBuffer>(array);
}
Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(size_t length)
{
- return memoryManager->allocObject<ArrayBuffer>(length);
+ return memoryManager->allocate<ArrayBuffer>(length);
}
Heap::DateObject *ExecutionEngine::newDateObject(const Value &value)
{
- return memoryManager->allocObject<DateObject>(value);
+ return memoryManager->allocate<DateObject>(value);
}
Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
{
Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(dt));
+ Scoped<DateObject> object(scope, memoryManager->allocate<DateObject>(dt));
return object->d();
}
Heap::DateObject *ExecutionEngine::newDateObjectFromTime(const QTime &t)
{
Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(t));
+ Scoped<DateObject> object(scope, memoryManager->allocate<DateObject>(t));
return object->d();
}
@@ -662,12 +789,12 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int
Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re)
{
- return memoryManager->allocObject<RegExpObject>(re);
+ return memoryManager->allocate<RegExpObject>(re);
}
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
- return memoryManager->allocObject<RegExpObject>(re);
+ return memoryManager->allocate<RegExpObject>(re);
}
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
@@ -714,16 +841,31 @@ Heap::Object *ExecutionEngine::newURIErrorObject(const Value &message)
Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
{
- return memoryManager->allocObject<VariantObject>(v);
+ return memoryManager->allocate<VariantObject>(v);
}
-Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
+Heap::Object *ExecutionEngine::newForInIteratorObject(Object *o)
{
Scope scope(this);
- ScopedObject obj(scope, memoryManager->allocObject<ForEachIteratorObject>(o));
+ ScopedObject obj(scope, memoryManager->allocate<ForInIteratorObject>(o));
return obj->d();
}
+Heap::Object *ExecutionEngine::newMapIteratorObject(Object *o)
+{
+ return memoryManager->allocate<MapIteratorObject>(o->d(), this);
+}
+
+Heap::Object *ExecutionEngine::newSetIteratorObject(Object *o)
+{
+ return memoryManager->allocate<SetIteratorObject>(o->d(), this);
+}
+
+Heap::Object *ExecutionEngine::newArrayIteratorObject(Object *o)
+{
+ return memoryManager->allocate<ArrayIteratorObject>(o->d(), this);
+}
+
Heap::QmlContext *ExecutionEngine::qmlContext() const
{
if (!currentStackFrame)
@@ -761,37 +903,6 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const
return ctx->qml()->context->contextData();
}
-QString CppStackFrame::source() const
-{
- return v4Function ? v4Function->sourceFile() : QString();
-}
-
-QString CppStackFrame::function() const
-{
- return v4Function ? v4Function->name()->toQString() : QString();
-}
-
-int CppStackFrame::lineNumber() const
-{
- if (!v4Function)
- return -1;
-
- auto findLine = [](const CompiledData::CodeOffsetToLine &entry, uint offset) {
- return entry.codeOffset < offset;
- };
-
- const QV4::CompiledData::Function *cf = v4Function->compiledFunction;
- uint offset = instructionPointer;
- const CompiledData::CodeOffsetToLine *lineNumbers = cf->lineNumberTable();
- uint nLineNumbers = cf->nLineNumbers;
- const CompiledData::CodeOffsetToLine *line = std::lower_bound(lineNumbers, lineNumbers + nLineNumbers, offset, findLine) - 1;
- return line->line;
-}
-
-ReturnedValue CppStackFrame::thisObject() const {
- return jsFrame->thisObject.asReturnedValue();
-}
-
StackTrace ExecutionEngine::stackTrace(int frameLimit) const
{
Scope scope(const_cast<ExecutionEngine *>(this));
@@ -891,16 +1002,14 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
}
ExecutionContext *global = rootContext();
for (int i = oldSize; i < nArgumentsAccessors; ++i) {
- argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocObject<ArgumentsGetterFunction>(global, i));
- argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocObject<ArgumentsSetterFunction>(global, i));
+ argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocate<ArgumentsGetterFunction>(global, i));
+ argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocate<ArgumentsSetterFunction>(global, i));
}
}
}
void ExecutionEngine::markObjects(MarkStack *markStack)
{
- identifierTable->mark(markStack);
-
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
if (Heap::FunctionObject *getter = pd.getter())
@@ -909,9 +1018,13 @@ void ExecutionEngine::markObjects(MarkStack *markStack)
setter->mark(markStack);
}
- classPool->markObjects(markStack);
+ for (int i = 0; i < NClasses; ++i)
+ if (classes[i])
+ classes[i]->mark(markStack);
markStack->drain();
+ identifierTable->markObjects(markStack);
+
for (auto compilationUnit: compilationUnits) {
compilationUnit->markObjects(markStack);
markStack->drain();
@@ -1053,12 +1166,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
error.setColumn(frame.column);
}
QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
- if (!!errorObj && errorObj->asSyntaxError()) {
- QV4::ScopedString m(scope, newString(QStringLiteral("message")));
- QV4::ScopedValue v(scope, errorObj->get(m));
- error.setDescription(v->toQStringNoThrow());
- } else
- error.setDescription(exception->toQStringNoThrow());
+ error.setDescription(exception->toQStringNoThrow());
return error;
}
@@ -1117,8 +1225,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return v->toVariant();
} else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
return l->toVariant();
- } else if (object->isListType())
+#if QT_CONFIG(qml_sequence_object)
+ } else if (object->isListType()) {
return QV4::SequencePrototype::toVariant(object);
+#endif
+ }
}
if (value.as<ArrayObject>()) {
@@ -1128,7 +1239,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
uint length = a->getLength();
QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
for (uint ii = 0; ii < length; ++ii) {
- qobjectWrapper = a->getIndexed(ii);
+ qobjectWrapper = a->get(ii);
if (!!qobjectWrapper) {
list << qobjectWrapper->object();
} else {
@@ -1141,10 +1252,12 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QVariant::fromValue(QV4::JsonObject::toJsonArray(a));
}
+#if QT_CONFIG(qml_sequence_object)
bool succeeded = false;
QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded);
if (succeeded)
return retn;
+#endif
}
if (value.isUndefined())
@@ -1164,8 +1277,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return str.at(0);
return str;
}
+#if QT_CONFIG(qml_locale)
if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
return *ld->d()->locale;
+#endif
if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
if (const ArrayBuffer *d = value.as<ArrayBuffer>())
@@ -1211,7 +1326,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V
int length = a->getLength();
for (int ii = 0; ii < length; ++ii) {
- v = a->getIndexed(ii);
+ v = a->get(ii);
list << ::toVariant(e, v, -1, /*createJSValueForObjects*/false, visitedObjects);
}
@@ -1260,9 +1375,6 @@ static QV4::ReturnedValue objectFromVariantMap(QV4::ExecutionEngine *e, const QV
QV4::ScopedValue v(scope);
for (QVariantMap::const_iterator iter = map.begin(), cend = map.end(); iter != cend; ++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 = e->fromVariant(iter.value())));
}
return o.asReturnedValue();
@@ -1321,6 +1433,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
case QMetaType::QObjectStar:
return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
+#if QT_CONFIG(qml_sequence_object)
case QMetaType::QStringList:
{
bool succeeded = false;
@@ -1330,6 +1443,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return retn->asReturnedValue();
return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(ptr)));
}
+#endif
case QMetaType::QVariantList:
return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
case QMetaType::QVariantMap:
@@ -1340,8 +1454,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(ptr));
case QMetaType::QJsonArray:
return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(ptr));
+#if QT_CONFIG(qml_locale)
case QMetaType::QLocale:
return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
+#endif
default:
break;
}
@@ -1381,10 +1497,12 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
if (objOk)
return QV4::QObjectWrapper::wrap(this, obj);
+#if QT_CONFIG(qml_sequence_object)
bool succeeded = false;
QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(this, variant, &succeeded));
if (succeeded)
return retn->asReturnedValue();
+#endif
if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type))
return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type);
@@ -1428,11 +1546,13 @@ static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVarian
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, v4->newObject());
QV4::ScopedString s(scope);
+ QV4::ScopedPropertyKey key(scope);
QV4::ScopedValue v(scope);
for (QVariantMap::const_iterator it = vmap.constBegin(), cend = vmap.constEnd(); it != cend; ++it) {
s = v4->newIdentifier(it.key());
+ key = s->propertyKey();
v = variantToJS(v4, it.value());
- uint idx = s->asArrayIndex();
+ uint idx = key->asArrayIndex();
if (idx < UINT_MAX)
o->arraySet(idx, v);
else
@@ -1707,7 +1827,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
} else if (Object *o = value->objectValue()) {
// Look in the prototype chain.
QV4::Scope scope(this);
- QV4::ScopedObject proto(scope, o->prototype());
+ QV4::ScopedObject proto(scope, o->getPrototypeOf());
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -1728,7 +1848,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
*reinterpret_cast<void* *>(data) = var.data();
return true;
}
- proto = proto->prototype();
+ proto = proto->getPrototypeOf();
}
}
} else if (value->isNull() && name.endsWith('*')) {
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index c7fb743088..fc0c93eaad 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -56,7 +56,6 @@
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
-
#ifndef V4_BOOTSTRAP
# include "qv4function_p.h"
# include <private/qv8engine_p.h>
@@ -88,33 +87,6 @@ struct CompilationUnit;
}
struct Function;
-struct InternalClass;
-struct InternalClassPool;
-
-struct Q_QML_EXPORT CppStackFrame {
- CppStackFrame *parent;
- Function *v4Function;
- CallData *jsFrame;
- const Value *originalArguments;
- int originalArgumentsCount;
- int instructionPointer;
-
- QString source() const;
- QString function() const;
- inline QV4::ExecutionContext *context() const {
- return static_cast<ExecutionContext *>(&jsFrame->context);
- }
- int lineNumber() const;
-
- inline QV4::Heap::CallContext *callContext() const {
- Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\
- while (ctx->type != Heap::ExecutionContext::Type_CallContext)
- ctx = ctx->outer;
- return static_cast<Heap::CallContext *>(ctx);
- }
- ReturnedValue thisObject() const;
-};
-
struct Q_QML_EXPORT ExecutionEngine : public EngineBase
@@ -142,8 +114,6 @@ public:
QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) {
Value *ptr = jsStackTop;
jsStackTop = ptr + nValues;
- for (int i = 0; i < nValues; ++i)
- ptr[i] = Primitive::undefinedValue();
return ptr;
}
@@ -153,22 +123,27 @@ public:
QJSEngine *jsEngine() const;
QQmlEngine *qmlEngine() const;
#else // !V4_BOOTSTRAP
- QJSEngine *jsEngine() const { return v8Engine->publicEngine(); }
+ QJSEngine *jsEngine() const { return publicEngine; }
QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; }
#endif // V4_BOOTSTRAP
QV8Engine *v8Engine;
+ QJSEngine *publicEngine;
enum JSObjects {
RootContext,
+ ScriptContext,
IntegerNull, // Has to come after the RootContext to make the context stack safe
ObjectProto,
+ SymbolProto,
ArrayProto,
+ ArrayProtoValues,
PropertyListProto,
StringProto,
NumberProto,
BooleanProto,
DateProto,
FunctionProto,
+ GeneratorProto,
RegExpProto,
ErrorProto,
EvalErrorProto,
@@ -178,18 +153,31 @@ public:
TypeErrorProto,
URIErrorProto,
VariantProto,
+#if QT_CONFIG(qml_sequence_object)
SequenceProto,
+#endif
ArrayBufferProto,
DataViewProto,
+ SetProto,
+ MapProto,
+ IntrinsicTypedArrayProto,
ValueTypeProto,
SignalHandlerProto,
+ IteratorProto,
+ ForInIteratorProto,
+ SetIteratorProto,
+ MapIteratorProto,
+ ArrayIteratorProto,
+ StringIteratorProto,
Object_Ctor,
String_Ctor,
+ Symbol_Ctor,
Number_Ctor,
Boolean_Ctor,
Array_Ctor,
Function_Ctor,
+ GeneratorFunction_Ctor,
Date_Ctor,
RegExp_Ctor,
Error_Ctor,
@@ -201,6 +189,11 @@ public:
URIError_Ctor,
ArrayBuffer_Ctor,
DataView_Ctor,
+ Set_Ctor,
+ Map_Ctor,
+ IntrinsicTypedArray_Ctor,
+
+ GetSymbolSpecies,
Eval_Function,
GetStack_Function,
@@ -211,12 +204,16 @@ public:
enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
+ ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
+ void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
+ FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
+ FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
@@ -228,16 +225,24 @@ public:
FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
+ FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
+ FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
+ FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
FunctionObject *typedArrayCtors;
+ FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
+
Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
+ Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
+ Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
+ Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
@@ -247,16 +252,26 @@ public:
Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
+#if QT_CONFIG(qml_sequence_object)
Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
+#endif
Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
+ Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
+ Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
+ Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
Object *typedArrayPrototype;
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
+ Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
+ Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
+ Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
+ Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
+ Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
+ Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
- InternalClassPool *classPool;
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
@@ -273,6 +288,8 @@ public:
String_boolean,
String_number,
String_string,
+ String_default,
+ String_symbol,
String_object,
String_function,
String_length,
@@ -301,10 +318,31 @@ public:
String_byteOffset,
String_buffer,
String_lastIndex,
+ String_next,
+ String_done,
+ String_return,
+
NJSStrings
};
Value *jsStrings;
+ enum JSSymbols {
+ Symbol_hasInstance,
+ Symbol_isConcatSpreadable,
+ Symbol_iterator,
+ Symbol_match,
+ Symbol_replace,
+ Symbol_search,
+ Symbol_species,
+ Symbol_split,
+ Symbol_toPrimitive,
+ Symbol_toStringTag,
+ Symbol_unscopables,
+ Symbol_revokableProxy,
+ NJSSymbols
+ };
+ Value *jsSymbols;
+
String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
@@ -313,6 +351,8 @@ public:
String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
+ String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
+ String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
@@ -341,6 +381,22 @@ public:
String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
+ String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
+ String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
+ String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
+
+ Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
+ Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
+ Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
+ Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
+ Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
+ Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
+ Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
+ Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
+ Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
+ Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
+ Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
+ Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
#ifndef V4_BOOTSTRAP
QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
@@ -372,9 +428,9 @@ public:
const bool m_canAllocateExecutableMemory;
#endif
- int internalClassIdCount = 0;
+ quintptr protoIdCount = 1;
- ExecutionEngine();
+ ExecutionEngine(QJSEngine *jsEngine = nullptr);
~ExecutionEngine();
#if !QT_CONFIG(qml_debug)
@@ -391,29 +447,28 @@ public:
void setProfiler(Profiling::Profiler *profiler);
#endif // QT_CONFIG(qml_debug)
- void setCurrentContext(Heap::ExecutionContext *context);
- ExecutionContext *currentContext() const {
- return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
- }
+ ExecutionContext *currentContext() const;
- int newInternalClassId() { return ++internalClassIdCount; }
+ // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
+ quintptr newProtoId() { return (protoIdCount += 2); }
- InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
+ Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
Heap::Object *newObject();
- Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
+ Heap::Object *newObject(Heap::InternalClass *internalClass);
Heap::String *newString(const QString &s = QString());
Heap::String *newIdentifier(const QString &text);
Heap::Object *newStringObject(const String *string);
+ Heap::Object *newSymbolObject(const Symbol *symbol);
Heap::Object *newNumberObject(double value);
Heap::Object *newBooleanObject(bool b);
Heap::ArrayObject *newArrayObject(int count = 0);
Heap::ArrayObject *newArrayObject(const Value *values, int length);
Heap::ArrayObject *newArrayObject(const QStringList &list);
- Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype);
+ Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic);
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
Heap::ArrayBuffer *newArrayBuffer(size_t length);
@@ -437,7 +492,10 @@ public:
Heap::Object *newVariantObject(const QVariant &v);
- Heap::Object *newForEachIteratorObject(Object *o);
+ Heap::Object *newForInIteratorObject(Object *o);
+ Heap::Object *newSetIteratorObject(Object *o);
+ Heap::Object *newMapIteratorObject(Object *o);
+ Heap::Object *newArrayIteratorObject(Object *o);
Heap::QmlContext *qmlContext() const;
QObject *qmlScopeObject() const;
@@ -453,7 +511,7 @@ public:
void initRootContext();
- InternalClass *newClass(const InternalClass &other);
+ Heap::InternalClass *newClass(Heap::InternalClass *other);
StackTrace exceptionStackTrace;
@@ -492,7 +550,7 @@ public:
if (!m_canAllocateExecutableMemory)
return false;
if (f)
- return f->interpreterCallCount >= jitCallCountThreshold;
+ return !f->isGenerator() && f->interpreterCallCount >= jitCallCountThreshold;
return true;
#else
Q_UNUSED(f);
@@ -502,6 +560,7 @@ public:
QV4::ReturnedValue global();
+ double localTZA = 0.0; // local timezone, initialized at startup
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
@@ -521,11 +580,6 @@ struct NoThrowEngine;
#endif
-inline void ExecutionEngine::setCurrentContext(Heap::ExecutionContext *context)
-{
- currentStackFrame->jsFrame->context = context;
-}
-
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 59fb4a564a..3e89e57abb 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -88,7 +88,7 @@ struct Q_QML_EXPORT EngineBase {
// Exception handling
Value *exceptionValue = nullptr;
- enum {
+ enum InternalClassType {
Class_Empty,
Class_String,
Class_MemberData,
@@ -96,11 +96,18 @@ struct Q_QML_EXPORT EngineBase {
Class_SparseArrayData,
Class_ExecutionContext,
Class_CallContext,
+ Class_QmlContext,
Class_Object,
Class_ArrayObject,
Class_FunctionObject,
+ Class_GeneratorFunction,
+ Class_GeneratorObject,
Class_StringObject,
+ Class_SymbolObject,
Class_ScriptFunction,
+ Class_ConstructorFunction,
+ Class_MemberFunction,
+ Class_MemberGeneratorFunction,
Class_ObjectProto,
Class_RegExp,
Class_RegExpObject,
@@ -111,10 +118,12 @@ struct Q_QML_EXPORT EngineBase {
Class_ErrorObjectWithMessage,
Class_ErrorProto,
Class_QmlContextWrapper,
- Class_QmlContext,
+ Class_ProxyObject,
+ Class_Symbol,
NClasses
};
- InternalClass *internalClasses[NClasses];
+ Heap::InternalClass *classes[NClasses];
+ Heap::InternalClass *internalClasses(InternalClassType icType) { return classes[icType]; }
};
#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
#pragma pack(pop)
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 90e158ba37..e8b4e04e83 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -47,10 +47,6 @@
#include "qv4string_p.h"
#include <private/qv4mm_p.h>
-#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
#include <qv4codegen_p.h>
#ifndef Q_OS_WIN
@@ -74,7 +70,7 @@ void Heap::ErrorObject::init()
Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- if (internalClass == scope.engine->internalClasses[EngineBase::Class_ErrorProto])
+ if (internalClass == scope.engine->internalClasses(EngineBase::Class_ErrorProto))
return;
setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
@@ -233,13 +229,13 @@ void Heap::ErrorCtor::init(QV4::ExecutionContext *scope, const QString &name)
Heap::FunctionObject::init(scope, name);
}
-ReturnedValue ErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue ErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<ErrorObject>(f->engine(), v)->asReturnedValue();
}
-ReturnedValue ErrorCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue ErrorCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
return f->callAsConstructor(argv, argc);
}
@@ -249,7 +245,7 @@ void Heap::EvalErrorCtor::init(QV4::ExecutionContext *scope)
Heap::ErrorCtor::init(scope, QStringLiteral("EvalError"));
}
-ReturnedValue EvalErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue EvalErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<EvalErrorObject>(f->engine(), v)->asReturnedValue();
@@ -260,7 +256,7 @@ void Heap::RangeErrorCtor::init(QV4::ExecutionContext *scope)
Heap::ErrorCtor::init(scope, QStringLiteral("RangeError"));
}
-ReturnedValue RangeErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue RangeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<RangeErrorObject>(f->engine(), v)->asReturnedValue();
@@ -271,7 +267,7 @@ void Heap::ReferenceErrorCtor::init(QV4::ExecutionContext *scope)
Heap::ErrorCtor::init(scope, QStringLiteral("ReferenceError"));
}
-ReturnedValue ReferenceErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue ReferenceErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<ReferenceErrorObject>(f->engine(), v)->asReturnedValue();
@@ -282,7 +278,7 @@ void Heap::SyntaxErrorCtor::init(QV4::ExecutionContext *scope)
Heap::ErrorCtor::init(scope, QStringLiteral("SyntaxError"));
}
-ReturnedValue SyntaxErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue SyntaxErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<SyntaxErrorObject>(f->engine(), v)->asReturnedValue();
@@ -293,7 +289,7 @@ void Heap::TypeErrorCtor::init(QV4::ExecutionContext *scope)
Heap::ErrorCtor::init(scope, QStringLiteral("TypeError"));
}
-ReturnedValue TypeErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue TypeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<TypeErrorObject>(f->engine(), v)->asReturnedValue();
@@ -304,7 +300,7 @@ void Heap::URIErrorCtor::init(QV4::ExecutionContext *scope)
Heap::ErrorCtor::init(scope, QStringLiteral("URIError"));
}
-ReturnedValue URIErrorCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue URIErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Value v = argc ? *argv : Primitive::undefinedValue();
return ErrorObject::create<URIErrorObject>(f->engine(), v)->asReturnedValue();
@@ -316,7 +312,7 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, He
ScopedString s(scope);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
obj->setProperty(Index_Constructor, ctor->d());
obj->setProperty(Index_Message, engine->id_empty()->d());
obj->setProperty(Index_Name, engine->newString(QString::fromLatin1(ErrorObject::className(t))));
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 6b578e8c38..90ef4dd842 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -180,7 +180,7 @@ struct ErrorObject: Object {
template<>
inline const ErrorObject *Value::as() const {
- return isManaged() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : nullptr;
+ return isManaged() && m()->internalClass->vtable->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : nullptr;
}
struct EvalErrorObject: ErrorObject {
@@ -229,50 +229,50 @@ struct ErrorCtor: FunctionObject
{
V4_OBJECT2(ErrorCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct EvalErrorCtor: ErrorCtor
{
V4_OBJECT2(EvalErrorCtor, ErrorCtor)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
};
struct RangeErrorCtor: ErrorCtor
{
V4_OBJECT2(RangeErrorCtor, ErrorCtor)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
};
struct ReferenceErrorCtor: ErrorCtor
{
V4_OBJECT2(ReferenceErrorCtor, ErrorCtor)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
};
struct SyntaxErrorCtor: ErrorCtor
{
V4_OBJECT2(SyntaxErrorCtor, ErrorCtor)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
};
struct TypeErrorCtor: ErrorCtor
{
V4_OBJECT2(TypeErrorCtor, ErrorCtor)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
};
struct URIErrorCtor: ErrorCtor
{
V4_OBJECT2(URIErrorCtor, ErrorCtor)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
};
@@ -328,25 +328,26 @@ inline SyntaxErrorObject *ErrorObject::asSyntaxError()
template <typename T>
Heap::Object *ErrorObject::create(ExecutionEngine *e, const Value &message) {
- InternalClass *ic = e->internalClasses[message.isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage];
- ic = ic->changePrototype(T::defaultPrototype(e)->d());
- return e->memoryManager->allocObject<T>(ic, T::defaultPrototype(e), message);
+ EngineBase::InternalClassType klass = message.isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage;
+ Scope scope(e);
+ Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d()));
+ return e->memoryManager->allocObject<T>(ic->d(), message);
}
template <typename T>
Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message) {
Scope scope(e);
ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
- InternalClass *ic = e->internalClasses[v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage];
- ic = ic->changePrototype(T::defaultPrototype(e)->d());
- return e->memoryManager->allocObject<T>(ic, T::defaultPrototype(e), v);
+ EngineBase::InternalClassType klass = v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage;
+ Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d()));
+ return e->memoryManager->allocObject<T>(ic->d(), v);
}
template <typename T>
Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column) {
Scope scope(e);
ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
- InternalClass *ic = e->internalClasses[v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage];
- ic = ic->changePrototype(T::defaultPrototype(e)->d());
- return e->memoryManager->allocObject<T>(ic, T::defaultPrototype(e), v, filename, line, column);
+ EngineBase::InternalClassType klass = v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage;
+ Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d()));
+ return e->memoryManager->allocObject<T>(ic->d(), v, filename, line, column);
}
diff --git a/src/qml/jsruntime/qv4estable.cpp b/src/qml/jsruntime/qv4estable.cpp
new file mode 100644
index 0000000000..55b7407000
--- /dev/null
+++ b/src/qml/jsruntime/qv4estable.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4estable_p.h"
+
+using namespace QV4;
+
+// The ES spec requires that Map/Set be implemented using a data structure that
+// is a little different from most; it requires nonlinear access, and must also
+// preserve the order of insertion of items in a deterministic way.
+//
+// This class implements those requirements, except for fast access: that
+// will be addressed in a followup patch.
+
+ESTable::ESTable()
+ : m_capacity(8)
+{
+ m_keys = (Value*)malloc(m_capacity * sizeof(Value));
+ m_values = (Value*)malloc(m_capacity * sizeof(Value));
+ memset(m_keys, 0, m_capacity);
+ memset(m_values, 0, m_capacity);
+}
+
+ESTable::~ESTable()
+{
+ free(m_keys);
+ free(m_values);
+ m_size = 0;
+ m_capacity = 0;
+ m_keys = nullptr;
+ m_values = nullptr;
+}
+
+void ESTable::markObjects(MarkStack *s)
+{
+ for (uint i = 0; i < m_size; ++i) {
+ m_keys[i].mark(s);
+ m_values[i].mark(s);
+ }
+}
+
+// Pretends that there's nothing in the table. Doesn't actually free memory, as
+// it will almost certainly be reused again anyway.
+void ESTable::clear()
+{
+ m_size = 0;
+}
+
+// Update the table to contain \a value for a given \a key. The key is
+// normalized, as required by the ES spec.
+void ESTable::set(const Value &key, const Value &value)
+{
+ for (uint i = 0; i < m_size; ++i) {
+ if (m_keys[i].sameValueZero(key)) {
+ m_values[i] = value;
+ return;
+ }
+ }
+
+ if (m_capacity == m_size) {
+ uint oldCap = m_capacity;
+ m_capacity *= 2;
+ m_keys = (Value*)realloc(m_keys, m_capacity * sizeof(Value));
+ m_values = (Value*)realloc(m_values, m_capacity * sizeof(Value));
+ memset(m_keys + oldCap, 0, m_capacity - oldCap);
+ memset(m_values + oldCap, 0, m_capacity - oldCap);
+ }
+
+ Value nk = key;
+ if (nk.isDouble()) {
+ if (nk.doubleValue() == 0 && std::signbit(nk.doubleValue()))
+ nk = Primitive::fromDouble(+0);
+ }
+
+ m_keys[m_size] = nk;
+ m_values[m_size] = value;
+
+ m_size++;
+}
+
+// Returns true if the table contains \a key, false otherwise.
+bool ESTable::has(const Value &key) const
+{
+ for (uint i = 0; i < m_size; ++i) {
+ if (m_keys[i].sameValueZero(key))
+ return true;
+ }
+
+ return false;
+}
+
+// Fetches the value for the given \a key, and if \a hasValue is passed in,
+// it is set depending on whether or not the given key was found.
+ReturnedValue ESTable::get(const Value &key, bool *hasValue) const
+{
+ for (uint i = 0; i < m_size; ++i) {
+ if (m_keys[i].sameValueZero(key)) {
+ if (hasValue)
+ *hasValue = true;
+ return m_values[i].asReturnedValue();
+ }
+ }
+
+ if (hasValue)
+ *hasValue = false;
+ return Encode::undefined();
+}
+
+// Removes the given \a key from the table
+bool ESTable::remove(const Value &key)
+{
+ bool found = false;
+ uint idx = 0;
+ for (; idx < m_size; ++idx) {
+ if (m_keys[idx].sameValueZero(key)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found == true) {
+ memmove(m_keys + idx, m_keys + idx + 1, m_size - idx);
+ memmove(m_values + idx, m_values + idx + 1, m_size - idx);
+ m_size--;
+ }
+ return found;
+}
+
+// Returns the size of the table. Note that the size may not match the underlying allocation.
+uint ESTable::size() const
+{
+ return m_size;
+}
+
+// Retrieves a key and value for a given \a idx, and places them in \a key and
+// \a value. They must be valid pointers.
+void ESTable::iterate(uint idx, Value *key, Value *value)
+{
+ Q_ASSERT(idx < m_size);
+ Q_ASSERT(key);
+ Q_ASSERT(value);
+ *key = m_keys[idx];
+ *value = m_values[idx];
+}
+
diff --git a/src/qml/jsruntime/qv4estable_p.h b/src/qml/jsruntime/qv4estable_p.h
new file mode 100644
index 0000000000..c665467760
--- /dev/null
+++ b/src/qml/jsruntime/qv4estable_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+#ifndef QV4ESTABLE_P_H
+#define QV4ESTABLE_P_H
+
+#include "qv4value_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4
+{
+
+class ESTable
+{
+public:
+ ESTable();
+ ~ESTable();
+
+ void markObjects(MarkStack *s);
+ void clear();
+ void set(const Value &k, const Value &v);
+ bool has(const Value &k) const;
+ ReturnedValue get(const Value &k, bool *hasValue = nullptr) const;
+ bool remove(const Value &k);
+ uint size() const;
+ void iterate(uint idx, Value *k, Value *v);
+
+private:
+ Value *m_keys = nullptr;
+ Value *m_values = nullptr;
+ uint m_size = 0;
+ uint m_capacity = 0;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 6fca9ecd45..5e3860a660 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -47,32 +47,51 @@
#include <private/qv4mm_p.h>
#include <private/qv4identifiertable_p.h>
#include <assembler/MacroAssemblerCodeRef.h>
+#include <private/qv4vme_moth_p.h>
+#include <private/qqmlglobal_p.h>
QT_BEGIN_NAMESPACE
using namespace QV4;
-Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, Code codePtr)
- : compiledFunction(function)
- , compilationUnit(unit)
- , code(codePtr)
- , codeData(function->code())
+ReturnedValue Function::call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
+ ExecutionEngine *engine = context->engine();
+ CppStackFrame frame;
+ frame.init(engine, this, argv, argc);
+ frame.setupJSFrame(engine->jsStackTop, Primitive::undefinedValue(), context->d(),
+ thisObject ? *thisObject : Primitive::undefinedValue(),
+ Primitive::undefinedValue());
+
+ frame.push();
+ engine->jsStackTop += frame.requiredJSStackFrameSize();
+
+ ReturnedValue result = Moth::VME::exec(&frame, engine);
+
+ frame.pop();
+
+ return result;
+}
+
+Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
+ : compiledFunction(function)
+ , compilationUnit(unit)
+ , codeData(function->code())
, jittedCode(nullptr)
, codeRef(nullptr)
, hasQmlDependencies(function->hasQmlDependencies())
{
- Q_UNUSED(engine);
-
- internalClass = engine->internalClasses[EngineBase::Class_CallContext];
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope, engine->internalClasses(EngineBase::Class_CallContext));
// first locals
const quint32_le *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
- internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
+ ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
const quint32_le *formalsIndices = compiledFunction->formalsTable();
for (quint32 i = 0; i < compiledFunction->nFormals; ++i)
- internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[formalsIndices[i]]), Attr_NotConfigurable);
+ ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[formalsIndices[i]]), Attr_NotConfigurable);
+ internalClass = ic->d();
nFormals = compiledFunction->nFormals;
}
@@ -110,20 +129,25 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
}
- internalClass = engine->internalClasses[EngineBase::Class_CallContext];
+ internalClass = engine->internalClasses(EngineBase::Class_CallContext);
// first locals
const quint32_le *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
- internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
+ internalClass = internalClass->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
Scope scope(engine);
ScopedString arg(scope);
for (const QString &parameterName : parameterNames) {
- arg = engine->newString(parameterName);
- internalClass = internalClass->addMember(arg, Attr_NotConfigurable);
+ arg = engine->newIdentifier(parameterName);
+ internalClass = internalClass->addMember(arg->propertyKey(), Attr_NotConfigurable);
}
nFormals = parameters.size();
}
+QQmlSourceLocation Function::sourceLocation() const
+{
+ return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column);
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 59a94e5dde..d542ce752f 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -51,10 +51,8 @@
//
#include "qv4global_p.h"
-#include <private/qqmlglobal_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4context_p.h>
-#include <private/qv4vme_moth_p.h>
namespace JSC {
class MacroAssemblerCodeRef;
@@ -62,31 +60,29 @@ class MacroAssemblerCodeRef;
QT_BEGIN_NAMESPACE
+struct QQmlSourceLocation;
+
namespace QV4 {
struct Q_QML_EXPORT Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- ReturnedValue call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
- return Moth::VME::exec(this, thisObject, argv, argc, context);
- }
+ ReturnedValue call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context);
- typedef ReturnedValue (*Code)(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc);
- Code code;
- const uchar *codeData;
+ const char *codeData;
typedef ReturnedValue (*JittedCode)(CppStackFrame *, ExecutionEngine *);
JittedCode jittedCode;
JSC::MacroAssemblerCodeRef *codeRef;
// first nArguments names in internalClass are the actual arguments
- InternalClass *internalClass;
+ Heap::InternalClass *internalClass;
uint nFormals;
int interpreterCallCount = 0;
bool hasQmlDependencies;
- Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, Code codePtr);
+ Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function);
~Function();
// used when dynamically assigning signal handlers (QQmlConnection)
@@ -98,13 +94,11 @@ struct Q_QML_EXPORT Function {
inline QString sourceFile() const { return compilationUnit->fileName(); }
inline QUrl finalUrl() const { return compilationUnit->finalUrl(); }
- inline bool usesArgumentsObject() const { return compiledFunction->flags & CompiledData::Function::UsesArgumentsObject; }
inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; }
+ inline bool isArrowFunction() const { return compiledFunction->flags & CompiledData::Function::IsArrowFunction; }
+ inline bool isGenerator() const { return compiledFunction->flags & CompiledData::Function::IsGenerator; }
- QQmlSourceLocation sourceLocation() const
- {
- return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column);
- }
+ QQmlSourceLocation sourceLocation() const;
Function *nestedFunction() const
{
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 83608070ec..2aca7c2849 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -41,6 +41,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4function_p.h"
+#include "qv4symbol_p.h"
#include <private/qv4mm_p.h>
#include "qv4arrayobject_p.h"
@@ -57,6 +58,7 @@
#include "private/qlocale_tools_p.h"
#include "private/qqmlbuiltinfunctions_p.h"
#include <private/qv4jscall_p.h>
+#include <private/qv4vme_moth_p.h>
#include <QtCore/QDebug>
#include <algorithm>
@@ -72,31 +74,38 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name,
ReturnedValue (*code)(const QV4::FunctionObject *, const Value *thisObject, const Value *argv, int argc))
{
jsCall = code;
- jsConstruct = QV4::FunctionObject::callAsConstructor;
+ jsConstruct = QV4::FunctionObject::virtualCallAsConstructor;
Object::init();
this->scope.set(scope->engine(), scope->d());
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
- f->init(name, false);
+ if (name)
+ f->setName(name);
}
void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
{
- jsCall = reinterpret_cast<const ObjectVTable *>(vtable())->call;
- jsConstruct = reinterpret_cast<const ObjectVTable *>(vtable())->callAsConstructor;
+ jsCall = vtable()->call;
+ jsConstruct = vtable()->callAsConstructor;
Object::init();
this->scope.set(scope->engine(), scope->d());
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
- f->init(name, createProto);
+ if (name)
+ f->setName(name);
+
+ if (createProto)
+ f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor);
}
+
+
void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, bool createProto)
{
- jsCall = reinterpret_cast<const ObjectVTable *>(vtable())->call;
- jsConstruct = reinterpret_cast<const ObjectVTable *>(vtable())->callAsConstructor;
+ jsCall = vtable()->call;
+ jsConstruct = vtable()->callAsConstructor;
Object::init();
setFunction(function);
@@ -104,7 +113,11 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function
Scope s(scope->engine());
ScopedString name(s, function->name());
ScopedFunctionObject f(s, this);
- f->init(name, createProto);
+ if (name)
+ f->setName(name);
+
+ if (createProto)
+ f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor);
}
void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name, bool createProto)
@@ -116,12 +129,12 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &nam
void Heap::FunctionObject::init()
{
- jsCall = reinterpret_cast<const ObjectVTable *>(vtable())->call;
- jsConstruct = reinterpret_cast<const ObjectVTable *>(vtable())->callAsConstructor;
+ jsCall = vtable()->call;
+ jsConstruct = vtable()->callAsConstructor;
Object::init();
this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d());
- Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
+ Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()->propertyKey()) == Index_Prototype);
setProperty(internalClass->engine, Index_Prototype, Primitive::undefinedValue());
}
@@ -139,23 +152,16 @@ void Heap::FunctionObject::destroy()
Object::destroy();
}
-void FunctionObject::init(String *n, bool createProto)
+void FunctionObject::createDefaultPrototypeProperty(uint protoSlot, uint protoConstructorSlot)
{
- Scope s(internalClass()->engine);
- ScopedValue protectThis(s, this);
+ Scope s(this);
- Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()) == Heap::FunctionObject::Index_Prototype);
- if (createProto) {
- ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses[EngineBase::Class_ObjectProto], s.engine->objectPrototype()));
- Q_ASSERT(s.engine->internalClasses[EngineBase::Class_ObjectProto]->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor);
- proto->setProperty(Heap::FunctionObject::Index_ProtoConstructor, d());
- setProperty(Heap::FunctionObject::Index_Prototype, proto);
- } else {
- setProperty(Heap::FunctionObject::Index_Prototype, Primitive::undefinedValue());
- }
+ Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()->propertyKey()) == protoSlot);
+ Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->find(s.engine->id_constructor()->propertyKey()) == protoConstructorSlot);
- if (n)
- defineReadonlyConfigurableProperty(s.engine->id_name(), *n);
+ ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto)));
+ proto->setProperty(protoConstructorSlot, d());
+ setProperty(protoSlot, proto);
}
ReturnedValue FunctionObject::name() const
@@ -163,19 +169,48 @@ ReturnedValue FunctionObject::name() const
return get(scope()->internalClass->engine->id_name());
}
-ReturnedValue FunctionObject::callAsConstructor(const FunctionObject *f, const Value *, int)
+ReturnedValue FunctionObject::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
{
return f->engine()->throwTypeError();
}
-ReturnedValue FunctionObject::call(const FunctionObject *, const Value *, const Value *, int)
+ReturnedValue FunctionObject::virtualCall(const FunctionObject *, const Value *, const Value *, int)
{
return Encode::undefined();
}
Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function)
{
- return scope->engine()->memoryManager->allocObject<ScriptFunction>(scope, function);
+ return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function);
+}
+
+Heap::FunctionObject *FunctionObject::createConstructorFunction(ExecutionContext *scope, Function *function, bool isDerivedConstructor)
+{
+ if (!function) {
+ Heap::DefaultClassConstructorFunction *c = scope->engine()->memoryManager->allocate<DefaultClassConstructorFunction>(scope);
+ c->isDerivedConstructor = isDerivedConstructor;
+ return c;
+ }
+ Heap::ConstructorFunction *c = scope->engine()->memoryManager->allocate<ConstructorFunction>(scope, function);
+ c->isDerivedConstructor = isDerivedConstructor;
+ return c;
+}
+
+Heap::FunctionObject *FunctionObject::createMemberFunction(ExecutionContext *scope, Function *function)
+{
+ return scope->engine()->memoryManager->allocate<MemberFunction>(scope, function);
+}
+
+Heap::FunctionObject *FunctionObject::createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
+{
+ Scope scope(engine);
+ ScopedString name(scope, nameOrSymbol);
+ if (!name)
+ name = engine->newString(QChar::fromLatin1('[') + nameOrSymbol->toQString().midRef(1) + QChar::fromLatin1(']'));
+
+ ScopedFunctionObject function(scope, engine->memoryManager->allocate<FunctionObject>(engine->rootContext(), name, code));
+ function->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(argumentCount));
+ return function->d();
}
bool FunctionObject::isBinding() const
@@ -201,10 +236,8 @@ void Heap::FunctionCtor::init(QV4::ExecutionContext *scope)
}
// 15.3.2
-ReturnedValue FunctionCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+QQmlRefPointer<CompiledData::CompilationUnit> FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t)
{
- Scope scope(f->engine());
-
QString arguments;
QString body;
if (argc > 0) {
@@ -215,42 +248,58 @@ ReturnedValue FunctionCtor::callAsConstructor(const FunctionObject *f, const Val
}
body = argv[argc - 1].toQString();
}
- if (scope.engine->hasException)
- return Encode::undefined();
+ if (engine->hasException)
+ return nullptr;
- QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1Char('}');
+ QString function = (t == Type_Function ? QLatin1String("function anonymous(") : QLatin1String("function* anonymous(")) + arguments + QLatin1String("\n){") + body + QLatin1String("\n}");
- QQmlJS::Engine ee, *engine = &ee;
- QQmlJS::Lexer lexer(engine);
+ QQmlJS::Engine ee;
+ QQmlJS::Lexer lexer(&ee);
lexer.setCode(function, 1, false);
- QQmlJS::Parser parser(engine);
+ QQmlJS::Parser parser(&ee);
const bool parsed = parser.parseExpression();
- if (!parsed)
- return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
+ if (!parsed) {
+ engine->throwSyntaxError(QLatin1String("Parse error"));
+ return nullptr;
+ }
QQmlJS::AST::FunctionExpression *fe = QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression *>(parser.rootNode());
- if (!fe)
- return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
+ if (!fe) {
+ engine->throwSyntaxError(QLatin1String("Parse error"));
+ return nullptr;
+ }
- Compiler::Module module(scope.engine->debugger() != nullptr);
+ Compiler::Module module(engine->debugger() != nullptr);
Compiler::JSUnitGenerator jsGenerator(&module);
- RuntimeCodegen cg(scope.engine, &jsGenerator, false);
+ RuntimeCodegen cg(engine, &jsGenerator, false);
cg.generateFromFunctionExpression(QString(), function, fe, &module);
- QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = cg.generateCompilationUnit();
- Function *vmf = compilationUnit->linkToEngine(scope.engine);
+ if (engine->hasException)
+ return nullptr;
- ExecutionContext *global = scope.engine->rootContext();
+ return cg.generateCompilationUnit();
+}
+
+ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+{
+ ExecutionEngine *engine = f->engine();
+
+ QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Function);
+ if (engine->hasException)
+ return Encode::undefined();
+
+ Function *vmf = compilationUnit->linkToEngine(engine);
+ ExecutionContext *global = engine->scriptContext();
return Encode(FunctionObject::createScriptFunction(global, vmf));
}
// 15.3.1: This is equivalent to new Function(...)
-ReturnedValue FunctionCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue FunctionCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
- return callAsConstructor(f, argv, argc);
+ return virtualCallAsConstructor(f, argv, argc, f);
}
DEFINE_OBJECT_VTABLE(FunctionPrototype);
@@ -268,13 +317,14 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ defineReadonlyConfigurableProperty(engine->id_name(), *engine->id_empty());
defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
defineDefaultProperty(QStringLiteral("call"), method_call, 1);
defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
-
+ defineDefaultProperty(engine->symbol_hasInstance(), method_hasInstance, 1, Attr_ReadOnly);
}
ReturnedValue FunctionPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -284,7 +334,19 @@ ReturnedValue FunctionPrototype::method_toString(const FunctionObject *b, const
if (!fun)
return v4->throwTypeError();
- return Encode(v4->newString(QStringLiteral("function() { [code] }")));
+ const Scope scope(fun->engine());
+ const ScopedString scopedFunctionName(scope, fun->name());
+ const QString functionName(scopedFunctionName ? scopedFunctionName->toQString() : QString());
+ QString functionAsString = QStringLiteral("function");
+
+ // If fun->name() is empty, then there is no function name
+ // to append because the function is anonymous.
+ if (!functionName.isEmpty())
+ functionAsString.append(QLatin1Char(' ') + functionName);
+
+ functionAsString.append(QStringLiteral("() { [code] }"));
+
+ return Encode(v4->newString(functionAsString));
}
ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
@@ -304,7 +366,7 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons
uint len = arr->getLength();
Scope scope(v4);
- Value *arguments = v4->jsAlloca(len);
+ Value *arguments = scope.alloc(len);
if (len) {
if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>();
@@ -323,7 +385,7 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons
arguments[i] = Primitive::undefinedValue();
} else {
for (quint32 i = 0; i < len; ++i)
- arguments[i] = arr->getIndexed(i);
+ arguments[i] = arr->get(i);
}
}
@@ -383,18 +445,50 @@ ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Valu
return bound->asReturnedValue();
}
+ReturnedValue FunctionPrototype::method_hasInstance(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ if (!argc)
+ return false;
+ const Object *o = thisObject->as<Object>();
+ if (!o)
+ return f->engine()->throwTypeError();
+
+ return Object::virtualInstanceOf(o, argv[0]);
+}
+
DEFINE_OBJECT_VTABLE(ScriptFunction);
-ReturnedValue ScriptFunction::callAsConstructor(const FunctionObject *fo, const Value *argv, int argc)
+ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *v4 = fo->engine();
const ScriptFunction *f = static_cast<const ScriptFunction *>(fo);
+ Q_ASSERT(newTarget->isFunctionObject());
+ const FunctionObject *nt = static_cast<const FunctionObject *>(newTarget);
Scope scope(v4);
- InternalClass *ic = f->classForConstructor();
+ Scoped<InternalClass> ic(scope);
+ if (nt->d() == f->d()) {
+ ic = f->classForConstructor();
+ } else {
+ const Object *o = nt->d()->protoProperty();
+ ic = scope.engine->internalClasses(EngineBase::Class_Object);
+ if (o)
+ ic = ic->changePrototype(o->d());
+ }
ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic));
- ReturnedValue result = Moth::VME::exec(fo, thisObject, argv, argc);
+ CppStackFrame frame;
+ frame.init(v4, f->function(), argv, argc);
+ frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
+ thisObject,
+ newTarget ? *newTarget : Primitive::undefinedValue());
+
+ frame.push();
+ v4->jsStackTop += frame.requiredJSStackFrameSize();
+
+ ReturnedValue result = Moth::VME::exec(&frame, v4);
+
+ frame.pop();
if (Q_UNLIKELY(v4->hasException))
return Encode::undefined();
@@ -403,9 +497,23 @@ ReturnedValue ScriptFunction::callAsConstructor(const FunctionObject *fo, const
return result;
}
-ReturnedValue ScriptFunction::call(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue ScriptFunction::virtualCall(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
{
- return Moth::VME::exec(fo, thisObject, argv, argc);
+ ExecutionEngine *engine = fo->engine();
+ CppStackFrame frame;
+ frame.init(engine, fo->function(), argv, argc);
+ frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(),
+ thisObject ? *thisObject : Primitive::undefinedValue(),
+ Primitive::undefinedValue());
+
+ frame.push();
+ engine->jsStackTop += frame.requiredJSStackFrameSize();
+
+ ReturnedValue result = Moth::VME::exec(&frame, engine);
+
+ frame.pop();
+
+ return result;
}
void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function)
@@ -415,38 +523,123 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function
setFunction(function);
Q_ASSERT(function);
- Q_ASSERT(function->code);
Scope s(scope);
ScopedFunctionObject f(s, this);
ScopedString name(s, function->name());
- f->init(name, true);
- Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
- setProperty(s.engine, Index_Length, Primitive::fromInt32(f->formalParameterCount()));
-
- if (function->isStrict()) {
- ScopedProperty pd(s);
- pd->value = s.engine->thrower();
- pd->set = s.engine->thrower();
- f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- }
+ if (name)
+ f->setName(name);
+ f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor);
+
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()->propertyKey()) == Index_Length);
+ setProperty(s.engine, Index_Length, Primitive::fromInt32(int(function->compiledFunction->length)));
}
-InternalClass *ScriptFunction::classForConstructor() const
+Heap::InternalClass *ScriptFunction::classForConstructor() const
{
const Object *o = d()->protoProperty();
- InternalClass *ic = d()->cachedClassForConstructor;
- if (ic && ic->prototype == o->d())
- return ic;
+ if (d()->cachedClassForConstructor && d()->cachedClassForConstructor->prototype == o->d())
+ return d()->cachedClassForConstructor;
- ic = engine()->internalClasses[EngineBase::Class_Object];
+ Scope scope(engine());
+ Scoped<InternalClass> ic(scope, engine()->internalClasses(EngineBase::Class_Object));
if (o)
ic = ic->changePrototype(o->d());
- d()->cachedClassForConstructor = ic;
+ d()->cachedClassForConstructor.set(scope.engine, ic->d());
+
+ return ic->d();
+}
+
+DEFINE_OBJECT_VTABLE(ConstructorFunction);
+
+ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
+{
+ const ConstructorFunction *c = static_cast<const ConstructorFunction *>(f);
+ if (!c->d()->isDerivedConstructor)
+ return ScriptFunction::virtualCallAsConstructor(f, argv, argc, newTarget);
+
+ ExecutionEngine *v4 = f->engine();
+
+ CppStackFrame frame;
+ frame.init(v4, f->function(), argv, argc);
+ frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
+ Primitive::undefinedValue(),
+ newTarget ? *newTarget : Primitive::undefinedValue());
+
+ frame.push();
+ v4->jsStackTop += frame.requiredJSStackFrameSize();
+
+ ReturnedValue result = Moth::VME::exec(&frame, v4);
+
+ frame.pop();
+
+ if (Q_UNLIKELY(v4->hasException))
+ return Encode::undefined();
+ else if (Value::fromReturnedValue(result).isObject())
+ return result;
+ else if (!Value::fromReturnedValue(result).isUndefined())
+ return v4->throwTypeError();
+ return frame.jsFrame->thisObject.asReturnedValue();
+}
+
+ReturnedValue ConstructorFunction::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
+{
+ return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|"));
+}
- return ic;
+DEFINE_OBJECT_VTABLE(MemberFunction);
+
+ReturnedValue MemberFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
+{
+ return f->engine()->throwTypeError(QStringLiteral("Function is not a constructor."));
+}
+
+DEFINE_OBJECT_VTABLE(DefaultClassConstructorFunction);
+
+ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
+{
+ const DefaultClassConstructorFunction *c = static_cast<const DefaultClassConstructorFunction *>(f);
+ ExecutionEngine *v4 = f->engine();
+
+ Scope scope(v4);
+
+ if (!c->d()->isDerivedConstructor) {
+ ScopedObject proto(scope, static_cast<const Object *>(newTarget) ->get(scope.engine->id_prototype()));
+ ScopedObject c(scope, scope.engine->newObject());
+ c->setPrototypeUnchecked(proto);
+ return c->asReturnedValue();
+ }
+
+ ScopedFunctionObject super(scope, f->getPrototypeOf());
+ Q_ASSERT(super->isFunctionObject());
+
+ CppStackFrame frame;
+ frame.init(v4, nullptr, argv, argc);
+ frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
+ Primitive::undefinedValue(),
+ newTarget ? *newTarget : Primitive::undefinedValue(), argc, argc);
+
+ frame.push();
+ v4->jsStackTop += frame.requiredJSStackFrameSize(argc);
+
+ // Do a super call
+ ReturnedValue result = super->callAsConstructor(argv, argc, newTarget);
+
+ frame.pop();
+
+ if (Q_UNLIKELY(v4->hasException))
+ return Encode::undefined();
+ else if (Value::fromReturnedValue(result).isObject())
+ return result;
+ else if (!Value::fromReturnedValue(result).isUndefined())
+ return v4->throwTypeError();
+ return frame.jsFrame->thisObject.asReturnedValue();
+}
+
+ReturnedValue DefaultClassConstructorFunction::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
+{
+ return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|"));
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
@@ -479,7 +672,7 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject
f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
-ReturnedValue BoundFunction::call(const FunctionObject *fo, const Value *, const Value *argv, int argc)
+ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc)
{
const BoundFunction *f = static_cast<const BoundFunction *>(fo);
Scope scope(f->engine());
@@ -500,7 +693,7 @@ ReturnedValue BoundFunction::call(const FunctionObject *fo, const Value *, const
return target->call(jsCallData);
}
-ReturnedValue BoundFunction::callAsConstructor(const FunctionObject *fo, const Value *argv, int argc)
+ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *)
{
const BoundFunction *f = static_cast<const BoundFunction *>(fo);
Scope scope(f->engine());
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 32e71a175b..1acb1df0b4 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -64,17 +64,14 @@ namespace QV4 {
struct IndexedBuiltinFunction;
struct JSCallData;
-typedef ReturnedValue (*jsCallFunction)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
-typedef ReturnedValue (*jsConstructFunction)(const FunctionObject *, const Value *argv, int argc);
-
namespace Heap {
#define FunctionObjectMembers(class, Member) \
Member(class, Pointer, ExecutionContext *, scope) \
Member(class, NoMark, Function *, function) \
- Member(class, NoMark, jsCallFunction, jsCall) \
- Member(class, NoMark, jsConstructFunction, jsConstruct)
+ Member(class, NoMark, VTable::Call, jsCall) \
+ Member(class, NoMark, VTable::CallAsConstructor, jsConstruct)
DECLARE_HEAP_OBJECT(FunctionObject, Object) {
DECLARE_MARKOBJECTS(FunctionObject);
@@ -111,14 +108,30 @@ struct IndexedBuiltinFunction : FunctionObject {
uint index;
};
-struct ScriptFunction : FunctionObject {
+#define ScriptFunctionMembers(class, Member) \
+ Member(class, Pointer, InternalClass *, cachedClassForConstructor)
+
+DECLARE_HEAP_OBJECT(ScriptFunction, FunctionObject) {
+ DECLARE_MARKOBJECTS(ScriptFunction)
enum {
Index_Name = FunctionObject::Index_Prototype + 1,
Index_Length
};
void init(QV4::ExecutionContext *scope, Function *function);
+};
- QV4::InternalClass *cachedClassForConstructor;
+struct ConstructorFunction : ScriptFunction
+{
+ bool isDerivedConstructor;
+};
+
+struct MemberFunction : ScriptFunction
+{
+};
+
+struct DefaultClassConstructorFunction : FunctionObject
+{
+ bool isDerivedConstructor;
};
#define BoundFunctionMembers(class, Member) \
@@ -152,25 +165,26 @@ struct Q_QML_EXPORT FunctionObject: Object {
unsigned int formalParameterCount() const { return d()->formalParameterCount(); }
unsigned int varCount() const { return d()->varCount(); }
- void init(String *name, bool createProto);
+ void setName(String *name) {
+ defineReadonlyConfigurableProperty(engine()->id_name(), *name);
+ }
+ void createDefaultPrototypeProperty(uint protoSlot, uint protoConstructorSlot);
inline ReturnedValue callAsConstructor(const JSCallData &data) const;
- ReturnedValue callAsConstructor(const Value *argv, int argc) const {
- return d()->jsConstruct(this, argv, argc);
+ ReturnedValue callAsConstructor(const Value *argv, int argc, const Value *newTarget = nullptr) const {
+ return d()->jsConstruct(this, argv, argc, newTarget ? newTarget : this);
}
inline ReturnedValue call(const JSCallData &data) const;
ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const {
return d()->jsCall(this, thisObject, argv, argc);
}
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function);
- static Heap::FunctionObject *createBuiltinFunction(ExecutionContext *scope, String *name,
- ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc))
- {
- return scope->engine()->memoryManager->allocObject<FunctionObject>(scope, name, code);
- }
+ static Heap::FunctionObject *createConstructorFunction(ExecutionContext *scope, Function *function, bool isDerivedConstructor);
+ static Heap::FunctionObject *createMemberFunction(ExecutionContext *scope, Function *function);
+ static Heap::FunctionObject *createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount);
bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
bool isBinding() const;
@@ -181,7 +195,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
template<>
inline const FunctionObject *Value::as() const {
- return isManaged() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : nullptr;
+ return isManaged() && m()->internalClass->vtable->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : nullptr;
}
@@ -189,8 +203,14 @@ struct FunctionCtor: FunctionObject
{
V4_OBJECT2(FunctionCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+protected:
+ enum Type {
+ Type_Function,
+ Type_Generator
+ };
+ static QQmlRefPointer<CompiledData::CompilationUnit> parse(ExecutionEngine *engine, const Value *argv, int argc, Type t = Type_Function);
};
struct FunctionPrototype: FunctionObject
@@ -203,6 +223,7 @@ struct FunctionPrototype: FunctionObject
static ReturnedValue method_apply(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_bind(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
struct IndexedBuiltinFunction : FunctionObject
@@ -224,27 +245,46 @@ struct ScriptFunction : FunctionObject {
V4_INTERNALCLASS(ScriptFunction)
enum { NInlineProperties = 3 };
- static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+
+ Heap::InternalClass *classForConstructor() const;
+};
+
+struct ConstructorFunction : ScriptFunction {
+ V4_OBJECT2(ConstructorFunction, ScriptFunction)
+ V4_INTERNALCLASS(ConstructorFunction)
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
- InternalClass *classForConstructor() const;
+struct MemberFunction : ScriptFunction {
+ V4_OBJECT2(MemberFunction, ScriptFunction)
+ V4_INTERNALCLASS(MemberFunction)
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
};
+struct DefaultClassConstructorFunction : FunctionObject {
+ V4_OBJECT2(DefaultClassConstructorFunction, FunctionObject)
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
struct BoundFunction: FunctionObject {
V4_OBJECT2(BoundFunction, FunctionObject)
static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs)
{
- return scope->engine()->memoryManager->allocObject<BoundFunction>(scope, target, boundThis, boundArgs);
+ return scope->engine()->memoryManager->allocate<BoundFunction>(scope, target, boundThis, boundArgs);
}
Heap::FunctionObject *target() const { return d()->target; }
Value boundThis() const { return d()->boundThis; }
Heap::MemberData *boundArgs() const { return d()->boundArgs; }
- static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
}
diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp
new file mode 100644
index 0000000000..8c3cd8b863
--- /dev/null
+++ b/src/qml/jsruntime/qv4generatorobject.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qv4generatorobject_p.h>
+#include <qv4symbol_p.h>
+#include <qv4iterator_p.h>
+#include <qv4jscall_p.h>
+#include <qv4vme_moth_p.h>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(GeneratorFunctionCtor);
+DEFINE_OBJECT_VTABLE(GeneratorFunction);
+DEFINE_OBJECT_VTABLE(GeneratorObject);
+
+void Heap::GeneratorFunctionCtor::init(QV4::ExecutionContext *scope)
+{
+ Heap::FunctionObject::init(scope, QStringLiteral("GeneratorFunction"));
+}
+
+ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+{
+ ExecutionEngine *engine = f->engine();
+
+ QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Generator);
+ if (engine->hasException)
+ return Encode::undefined();
+
+ Function *vmf = compilationUnit->linkToEngine(engine);
+ ExecutionContext *global = engine->scriptContext();
+ return Encode(GeneratorFunction::create(global, vmf));
+}
+
+// 15.3.1: This is equivalent to new Function(...)
+ReturnedValue GeneratorFunctionCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ return virtualCallAsConstructor(f, argv, argc, f);
+}
+
+Heap::FunctionObject *GeneratorFunction::create(ExecutionContext *context, Function *function)
+{
+ Scope scope(context);
+ Scoped<GeneratorFunction> g(scope, context->engine()->memoryManager->allocate<GeneratorFunction>(context, function));
+ ScopedObject proto(scope, scope.engine->newObject());
+ proto->setPrototypeOf(scope.engine->generatorPrototype());
+ g->defineDefaultProperty(scope.engine->id_prototype(), proto, Attr_NotConfigurable|Attr_NotEnumerable);
+ g->setPrototypeOf(ScopedObject(scope, scope.engine->generatorFunctionCtor()->get(scope.engine->id_prototype())));
+ return g->d();
+}
+
+ReturnedValue GeneratorFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
+{
+ return f->engine()->throwTypeError();
+}
+
+ReturnedValue GeneratorFunction::virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ const GeneratorFunction *gf = static_cast<const GeneratorFunction *>(f);
+ Function *function = gf->function();
+ ExecutionEngine *engine = gf->engine();
+
+ // We need to set up a separate stack for the generator, as it's being re-entered
+ uint stackSize = argc // space for the original arguments
+ + CppStackFrame::requiredJSStackFrameSize(function); // space for the JS stack frame
+
+ size_t requiredMemory = sizeof(GeneratorObject::Data) - sizeof(Value) + sizeof(Value) * stackSize;
+
+ Scope scope(gf);
+ Scoped<GeneratorObject> g(scope, scope.engine->memoryManager->allocManaged<GeneratorObject>(requiredMemory, scope.engine->classes[EngineBase::Class_GeneratorObject]));
+ g->setPrototypeOf(ScopedObject(scope, gf->get(scope.engine->id_prototype())));
+
+ Heap::GeneratorObject *gp = g->d();
+ gp->stack.size = stackSize;
+ gp->stack.alloc = stackSize;
+
+ // copy original arguments
+ memcpy(gp->stack.values, argv, argc*sizeof(Value));
+ gp->cppFrame.init(engine, function, gp->stack.values, argc);
+ gp->cppFrame.setupJSFrame(&gp->stack.values[argc], *gf, gf->scope(),
+ thisObject ? *thisObject : Primitive::undefinedValue(),
+ Primitive::undefinedValue());
+
+ gp->cppFrame.push();
+
+ Moth::VME::interpret(&gp->cppFrame, engine, function->codeData);
+ gp->state = GeneratorState::SuspendedStart;
+
+ gp->cppFrame.pop();
+ return g->asReturnedValue();
+}
+
+
+void Heap::GeneratorPrototype::init()
+{
+ Heap::FunctionObject::init();
+}
+
+
+void GeneratorPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Scope scope(engine);
+ ScopedValue v(scope);
+
+ ScopedObject ctorProto(scope, engine->newObject(engine->newInternalClass(Object::staticVTable(), engine->functionPrototype())));
+
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), ctorProto);
+
+ ctorProto->defineDefaultProperty(QStringLiteral("constructor"), (v = ctor), Attr_ReadOnly_ButConfigurable);
+ ctorProto->defineDefaultProperty(engine->symbol_toStringTag(), (v = engine->newIdentifier(QStringLiteral("GeneratorFunction"))), Attr_ReadOnly_ButConfigurable);
+ ctorProto->defineDefaultProperty(engine->id_prototype(), (v = this), Attr_ReadOnly_ButConfigurable);
+
+ setPrototypeOf(engine->iteratorPrototype());
+ defineDefaultProperty(QStringLiteral("constructor"), ctorProto, Attr_ReadOnly_ButConfigurable);
+ defineDefaultProperty(QStringLiteral("next"), method_next, 1);
+ defineDefaultProperty(QStringLiteral("return"), method_return, 1);
+ defineDefaultProperty(QStringLiteral("throw"), method_throw, 1);
+ defineDefaultProperty(engine->symbol_toStringTag(), (v = engine->newString(QStringLiteral("Generator"))), Attr_ReadOnly_ButConfigurable);
+}
+
+ReturnedValue GeneratorPrototype::method_next(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *engine = f->engine();
+ const GeneratorObject *g = thisObject->as<GeneratorObject>();
+ if (!g || g->d()->state == GeneratorState::Executing)
+ return engine->throwTypeError();
+ Heap::GeneratorObject *gp = g->d();
+
+ if (gp->state == GeneratorState::Completed)
+ return IteratorPrototype::createIterResultObject(engine, Primitive::undefinedValue(), true);
+
+ return g->resume(engine, argc ? argv[0] : Primitive::undefinedValue());
+}
+
+ReturnedValue GeneratorPrototype::method_return(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *engine = f->engine();
+ const GeneratorObject *g = thisObject->as<GeneratorObject>();
+ if (!g || g->d()->state == GeneratorState::Executing)
+ return engine->throwTypeError();
+
+ Heap::GeneratorObject *gp = g->d();
+
+ if (gp->state == GeneratorState::SuspendedStart)
+ gp->state = GeneratorState::Completed;
+
+ if (gp->state == GeneratorState::Completed)
+ return IteratorPrototype::createIterResultObject(engine, argc ? argv[0] : Primitive::undefinedValue(), true);
+
+ // the bytecode interpreter interprets an exception with empty value as
+ // a yield called with return()
+ engine->throwError(Primitive::emptyValue());
+
+ return g->resume(engine, argc ? argv[0]: Primitive::undefinedValue());
+}
+
+ReturnedValue GeneratorPrototype::method_throw(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *engine = f->engine();
+ const GeneratorObject *g = thisObject->as<GeneratorObject>();
+ if (!g || g->d()->state == GeneratorState::Executing)
+ return engine->throwTypeError();
+
+ Heap::GeneratorObject *gp = g->d();
+
+ engine->throwError(argc ? argv[0]: Primitive::undefinedValue());
+
+ if (gp->state == GeneratorState::SuspendedStart || gp->state == GeneratorState::Completed) {
+ gp->state = GeneratorState::Completed;
+ return Encode::undefined();
+ }
+
+ return g->resume(engine, Primitive::undefinedValue());
+}
+
+ReturnedValue GeneratorObject::resume(ExecutionEngine *engine, const Value &arg) const
+{
+ Heap::GeneratorObject *gp = d();
+ gp->state = GeneratorState::Executing;
+ gp->cppFrame.parent = engine->currentStackFrame;
+ engine->currentStackFrame = &gp->cppFrame;
+
+ Q_ASSERT(gp->cppFrame.yield != nullptr);
+ const char *code = gp->cppFrame.yield;
+ gp->cppFrame.yield = nullptr;
+ gp->cppFrame.jsFrame->accumulator = arg;
+
+ Scope scope(engine);
+ ScopedValue result(scope, Moth::VME::interpret(&gp->cppFrame, engine, code));
+
+ engine->currentStackFrame = gp->cppFrame.parent;
+
+ bool done = (gp->cppFrame.yield == nullptr);
+ gp->state = done ? GeneratorState::Completed : GeneratorState::SuspendedYield;
+ if (engine->hasException)
+ return Encode::undefined();
+ return IteratorPrototype::createIterResultObject(engine, result, done);
+}
+
+DEFINE_OBJECT_VTABLE(MemberGeneratorFunction);
+
+Heap::FunctionObject *MemberGeneratorFunction::create(ExecutionContext *context, Function *function)
+{
+ Scope scope(context);
+ Scoped<GeneratorFunction> g(scope, context->engine()->memoryManager->allocate<MemberGeneratorFunction>(context, function));
+ ScopedObject proto(scope, scope.engine->newObject());
+ proto->setPrototypeOf(scope.engine->generatorPrototype());
+ g->defineDefaultProperty(scope.engine->id_prototype(), proto, Attr_NotConfigurable|Attr_NotEnumerable);
+ g->setPrototypeOf(ScopedObject(scope, scope.engine->generatorFunctionCtor()->get(scope.engine->id_prototype())));
+ return g->d();
+}
+
+ReturnedValue MemberGeneratorFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
+{
+ return f->engine()->throwTypeError(QStringLiteral("Function is not a constructor."));
+}
diff --git a/src/qml/jsruntime/qv4generatorobject_p.h b/src/qml/jsruntime/qv4generatorobject_p.h
new file mode 100644
index 0000000000..a97050473c
--- /dev/null
+++ b/src/qml/jsruntime/qv4generatorobject_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4GENERATOROBJECT_P_H
+#define QV4GENERATOROBJECT_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 "qv4functionobject_p.h"
+#include "qv4stackframe_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+enum class GeneratorState {
+ Undefined,
+ SuspendedStart,
+ SuspendedYield,
+ Executing,
+ Completed
+};
+
+namespace Heap {
+
+struct GeneratorFunctionCtor : FunctionObject {
+ void init(QV4::ExecutionContext *scope);
+};
+
+struct GeneratorFunction : ScriptFunction {
+};
+
+struct MemberGeneratorFunction : ScriptFunction {
+};
+
+struct GeneratorPrototype : FunctionObject {
+ void init();
+};
+
+#define GeneratorObjectMembers(class, Member) \
+ Member(class, Pointer, ExecutionContext *, context) \
+ Member(class, Pointer, GeneratorFunction *, function) \
+ Member(class, NoMark, GeneratorState, state) \
+ Member(class, NoMark, CppStackFrame, cppFrame) \
+ Member(class, ValueArray, ValueArray, stack)
+
+DECLARE_HEAP_OBJECT(GeneratorObject, Object) {
+ DECLARE_MARKOBJECTS(GeneratorObject);
+};
+
+}
+
+struct GeneratorFunctionCtor : FunctionCtor
+{
+ V4_OBJECT2(GeneratorFunctionCtor, FunctionCtor)
+
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct GeneratorFunction : ScriptFunction
+{
+ V4_OBJECT2(GeneratorFunction, ScriptFunction)
+ V4_INTERNALCLASS(GeneratorFunction)
+
+ static Heap::FunctionObject *create(ExecutionContext *scope, Function *function);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct MemberGeneratorFunction : GeneratorFunction
+{
+ V4_OBJECT2(MemberGeneratorFunction, GeneratorFunction)
+ V4_INTERNALCLASS(MemberGeneratorFunction)
+
+ static Heap::FunctionObject *create(ExecutionContext *scope, Function *function);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+};
+
+struct GeneratorPrototype : Object
+{
+ void init(ExecutionEngine *engine, Object *ctor);
+
+ static ReturnedValue method_next(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_return(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_throw(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+
+struct GeneratorObject : Object {
+ V4_OBJECT2(GeneratorObject, Object)
+ Q_MANAGED_TYPE(GeneratorObject)
+ V4_INTERNALCLASS(GeneratorObject)
+ V4_PROTOTYPE(generatorPrototype)
+
+ ReturnedValue resume(ExecutionEngine *engine, const Value &arg) const;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4GENERATORFUNCTION_P_H
+
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 1fa4bae049..e3b3423a9d 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -153,6 +153,11 @@ namespace Compiler {
struct Module;
struct Context;
struct JSUnitGenerator;
+ class Codegen;
+}
+
+namespace Moth {
+ class BytecodeGenerator;
}
namespace Heap {
@@ -160,13 +165,17 @@ namespace Heap {
struct MemberData;
struct ArrayData;
+ struct StringOrSymbol;
struct String;
+ struct Symbol;
struct Object;
struct ObjectPrototype;
struct ExecutionContext;
struct CallContext;
+ struct QmlContext;
struct ScriptFunction;
+ struct InternalClass;
struct BooleanObject;
struct NumberObject;
@@ -188,14 +197,19 @@ namespace Heap {
template <typename T, size_t> struct Pointer;
}
+struct CppStackFrame;
class MemoryManager;
class ExecutableAllocator;
+struct PropertyKey;
+struct StringOrSymbol;
struct String;
+struct Symbol;
struct Object;
struct ObjectPrototype;
struct ObjectIterator;
struct ExecutionContext;
struct CallContext;
+struct QmlContext;
struct ScriptFunction;
struct InternalClass;
struct Property;
@@ -236,6 +250,7 @@ struct Scope;
struct ScopedValue;
template<typename T> struct Scoped;
typedef Scoped<String> ScopedString;
+typedef Scoped<StringOrSymbol> ScopedStringOrSymbol;
typedef Scoped<Object> ScopedObject;
typedef Scoped<ArrayObject> ScopedArrayObject;
typedef Scoped<FunctionObject> ScopedFunctionObject;
@@ -244,6 +259,7 @@ typedef Scoped<ExecutionContext> ScopedContext;
struct PersistentValueStorage;
class PersistentValue;
class WeakValue;
+struct MarkStack;
struct IdentifierTable;
class RegExpCache;
@@ -357,6 +373,12 @@ struct Q_QML_EXPORT StackFrame {
};
typedef QVector<StackFrame> StackTrace;
+enum class ObjectLiteralArgument {
+ Value,
+ Getter,
+ Setter
+};
+
}
Q_DECLARE_TYPEINFO(QV4::PropertyAttributes, Q_PRIMITIVE_TYPE);
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index f419ab53fe..43895011f3 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -335,7 +335,7 @@ void Heap::EvalFunction::init(QV4::ExecutionContext *scope)
Scope s(scope);
Heap::FunctionObject::init(scope, s.engine->id_eval());
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
+ f->defineReadonlyConfigurableProperty(s.engine->id_length(), Primitive::fromInt32(1));
}
ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc, bool directCall) const
@@ -351,7 +351,7 @@ ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc,
if (!directCall) {
// the context for eval should be the global scope
- ctx = v4->rootContext();
+ ctx = v4->scriptContext();
}
String *scode = argv[0].stringValue();
@@ -361,7 +361,7 @@ ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc,
const QString code = scode->toQString();
bool inheritContext = !isStrict;
- Script script(ctx, QV4::Compiler::EvalCode, code, QStringLiteral("eval code"));
+ Script script(ctx, QV4::Compiler::ContextType::Eval, code, QStringLiteral("eval code"));
script.strictMode = (directCall && isStrict);
script.inheritContext = inheritContext;
script.parse();
@@ -384,7 +384,7 @@ ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc,
}
-ReturnedValue EvalFunction::call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue EvalFunction::virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
{
// indirect call
return static_cast<const EvalFunction *>(f)->evalCall(thisObject, argv, argc, false);
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index fd1820c23c..021b445955 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -71,7 +71,7 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
ReturnedValue evalCall(const Value *thisObject, const Value *argv, int argc, bool directCall) const;
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct GlobalFunctions
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index c122bcb51a..5db5bd46ec 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qv4identifier_p.h"
#include "qv4identifiertable_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -54,14 +55,16 @@ static inline int primeForNumBits(int numBits)
}
-IdentifierHashData::IdentifierHashData(int numBits)
+IdentifierHashData::IdentifierHashData(IdentifierTable *table, int numBits)
: size(0)
, numBits(numBits)
+ , identifierTable(table)
{
refCount.store(1);
alloc = primeForNumBits(numBits);
entries = (IdentifierHashEntry *)malloc(alloc*sizeof(IdentifierHashEntry));
memset(entries, 0, alloc*sizeof(IdentifierHashEntry));
+ identifierTable->addIdentifierHash(this);
}
IdentifierHashData::IdentifierHashData(IdentifierHashData *other)
@@ -73,12 +76,18 @@ IdentifierHashData::IdentifierHashData(IdentifierHashData *other)
alloc = other->alloc;
entries = (IdentifierHashEntry *)malloc(alloc*sizeof(IdentifierHashEntry));
memcpy(entries, other->entries, alloc*sizeof(IdentifierHashEntry));
+ identifierTable->addIdentifierHash(this);
+}
+
+IdentifierHashData::~IdentifierHashData() {
+ free(entries);
+ if (identifierTable)
+ identifierTable->removeIdentifierHash(this);
}
IdentifierHash::IdentifierHash(ExecutionEngine *engine)
{
- d = new IdentifierHashData(3);
- d->identifierTable = engine->identifierTable;
+ d = new IdentifierHashData(engine->identifierTable, 3);
}
void IdentifierHash::detach()
@@ -92,8 +101,10 @@ void IdentifierHash::detach()
}
-IdentifierHashEntry *IdentifierHash::addEntry(const Identifier *identifier)
+IdentifierHashEntry *IdentifierHash::addEntry(PropertyKey identifier)
{
+ Q_ASSERT(identifier.isStringOrSymbol());
+
// fill up to max 50%
bool grow = (d->alloc <= d->size*2);
@@ -104,10 +115,10 @@ IdentifierHashEntry *IdentifierHash::addEntry(const Identifier *identifier)
memset(newEntries, 0, newAlloc*sizeof(IdentifierHashEntry));
for (int i = 0; i < d->alloc; ++i) {
const IdentifierHashEntry &e = d->entries[i];
- if (!e.identifier)
+ if (!e.identifier.isValid())
continue;
- uint idx = e.identifier->hashValue % newAlloc;
- while (newEntries[idx].identifier) {
+ uint idx = e.identifier.id() % newAlloc;
+ while (newEntries[idx].identifier.isValid()) {
++idx;
idx %= newAlloc;
}
@@ -118,8 +129,8 @@ IdentifierHashEntry *IdentifierHash::addEntry(const Identifier *identifier)
d->alloc = newAlloc;
}
- uint idx = identifier->hashValue % d->alloc;
- while (d->entries[idx].identifier) {
+ uint idx = identifier.id() % d->alloc;
+ while (d->entries[idx].identifier.isValid()) {
Q_ASSERT(d->entries[idx].identifier != identifier);
++idx;
idx %= d->alloc;
@@ -129,15 +140,15 @@ IdentifierHashEntry *IdentifierHash::addEntry(const Identifier *identifier)
return d->entries + idx;
}
-const IdentifierHashEntry *IdentifierHash::lookup(const Identifier *identifier) const
+const IdentifierHashEntry *IdentifierHash::lookup(PropertyKey identifier) const
{
- if (!d)
+ if (!d || !identifier.isStringOrSymbol())
return nullptr;
Q_ASSERT(d->entries);
- uint idx = identifier->hashValue % d->alloc;
+ uint idx = identifier.id() % d->alloc;
while (1) {
- if (!d->entries[idx].identifier)
+ if (!d->entries[idx].identifier.isValid())
return nullptr;
if (d->entries[idx].identifier == identifier)
return d->entries + idx;
@@ -150,39 +161,54 @@ const IdentifierHashEntry *IdentifierHash::lookup(const QString &str) const
{
if (!d)
return nullptr;
- Q_ASSERT(d->entries);
- uint hash = String::createHashValue(str.constData(), str.length(), nullptr);
- uint idx = hash % d->alloc;
- while (1) {
- if (!d->entries[idx].identifier)
- return nullptr;
- if (d->entries[idx].identifier->string == str)
- return d->entries + idx;
- ++idx;
- idx %= d->alloc;
- }
+ PropertyKey id = d->identifierTable->asPropertyKey(str);
+ return lookup(id);
}
const IdentifierHashEntry *IdentifierHash::lookup(String *str) const
{
if (!d)
return nullptr;
- if (str->d()->identifier)
- return lookup(str->d()->identifier);
+ PropertyKey id = d->identifierTable->asPropertyKey(str);
+ if (id.isValid())
+ return lookup(id);
return lookup(str->toQString());
}
-const Identifier *IdentifierHash::toIdentifier(const QString &str) const
+const PropertyKey IdentifierHash::toIdentifier(const QString &str) const
{
Q_ASSERT(d);
- return d->identifierTable->identifier(str);
+ return d->identifierTable->asPropertyKey(str);
}
-const Identifier *IdentifierHash::toIdentifier(Heap::String *str) const
+const PropertyKey IdentifierHash::toIdentifier(Heap::String *str) const
{
Q_ASSERT(d);
- return d->identifierTable->identifier(str);
+ return d->identifierTable->asPropertyKey(str);
+}
+
+QString QV4::IdentifierHash::findId(int value) const
+{
+ IdentifierHashEntry *e = d->entries;
+ IdentifierHashEntry *end = e + d->alloc;
+ while (e < end) {
+ if (e->identifier.isValid() && e->value == value)
+ return e->identifier.toQString();
+ ++e;
+ }
+ return QString();
+}
+
+void IdentifierHashData::markObjects(MarkStack *markStack) const
+{
+ IdentifierHashEntry *e = entries;
+ IdentifierHashEntry *end = e + alloc;
+ while (e < end) {
+ if (Heap::Base *o = e->identifier.asStringOrSymbol())
+ o->mark(markStack);
+ ++e;
+ }
}
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index 82346d5f68..32de8b7c8d 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -51,38 +51,24 @@
//
#include <qstring.h>
+#include <private/qv4global_p.h>
+#include <private/qv4propertykey_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-namespace Heap {
- struct String;
-}
-
-struct String;
-struct IdentifierTable;
-struct ExecutionEngine;
-
-struct Identifier
-{
- QString string;
- uint hashValue;
-};
-
-
struct IdentifierHashEntry {
- const Identifier *identifier;
+ PropertyKey identifier;
int value;
};
struct IdentifierHashData
{
- IdentifierHashData(int numBits);
+ IdentifierHashData(IdentifierTable *table, int numBits);
explicit IdentifierHashData(IdentifierHashData *other);
- ~IdentifierHashData() {
- free(entries);
- }
+ ~IdentifierHashData();
+ void markObjects(MarkStack *markStack) const;
QBasicAtomicInt refCount;
int alloc;
@@ -117,12 +103,12 @@ struct IdentifierHash
QString findId(int value) const;
protected:
- IdentifierHashEntry *addEntry(const Identifier *i);
- const IdentifierHashEntry *lookup(const Identifier *identifier) const;
+ IdentifierHashEntry *addEntry(PropertyKey i);
+ const IdentifierHashEntry *lookup(PropertyKey identifier) const;
const IdentifierHashEntry *lookup(const QString &str) const;
const IdentifierHashEntry *lookup(String *str) const;
- const Identifier *toIdentifier(const QString &str) const;
- const Identifier *toIdentifier(Heap::String *str) const;
+ const PropertyKey toIdentifier(const QString &str) const;
+ const PropertyKey toIdentifier(Heap::String *str) const;
};
@@ -180,20 +166,6 @@ inline int IdentifierHash::value(String *str) const
return e ? e->value : -1;
}
-
-inline
-QString IdentifierHash::findId(int value) const
-{
- IdentifierHashEntry *e = d->entries;
- IdentifierHashEntry *end = e + d->alloc;
- while (e < end) {
- if (e->identifier && e->value == value)
- return e->identifier->string;
- ++e;
- }
- return QString();
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index b77f9478d3..0412695404 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
#include "qv4identifiertable_p.h"
+#include "qv4symbol_p.h"
QT_BEGIN_NAMESPACE
@@ -53,44 +54,44 @@ static inline int primeForNumBits(int numBits)
}
-IdentifierTable::IdentifierTable(ExecutionEngine *engine)
+IdentifierTable::IdentifierTable(ExecutionEngine *engine, int numBits)
: engine(engine)
, size(0)
- , numBits(8)
+ , numBits(numBits)
{
alloc = primeForNumBits(numBits);
- entries = (Heap::String **)malloc(alloc*sizeof(Heap::String *));
- memset(entries, 0, alloc*sizeof(Heap::String *));
+ entriesByHash = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::StringOrSymbol *));
+ entriesById = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::StringOrSymbol *));
+ memset(entriesByHash, 0, alloc*sizeof(Heap::String *));
+ memset(entriesById, 0, alloc*sizeof(Heap::String *));
}
IdentifierTable::~IdentifierTable()
{
- for (int i = 0; i < alloc; ++i)
- if (entries[i])
- delete entries[i]->identifier;
- free(entries);
+ free(entriesByHash);
+ free(entriesById);
+ for (auto &h : idHashes)
+ h->identifierTable = nullptr;
}
-void IdentifierTable::addEntry(Heap::String *str)
+void IdentifierTable::addEntry(Heap::StringOrSymbol *str)
{
uint hash = str->hashValue();
if (str->subtype == Heap::String::StringType_ArrayIndex)
return;
- str->identifier = new Identifier;
- str->identifier->string = str->toQString();
- str->identifier->hashValue = hash;
+ str->identifier = PropertyKey::fromStringOrSymbol(str);
bool grow = (alloc <= size*2);
if (grow) {
++numBits;
int newAlloc = primeForNumBits(numBits);
- Heap::String **newEntries = (Heap::String **)malloc(newAlloc*sizeof(Heap::String *));
- memset(newEntries, 0, newAlloc*sizeof(Heap::String *));
+ Heap::StringOrSymbol **newEntries = (Heap::StringOrSymbol **)malloc(newAlloc*sizeof(Heap::String *));
+ memset(newEntries, 0, newAlloc*sizeof(Heap::StringOrSymbol *));
for (int i = 0; i < alloc; ++i) {
- Heap::String *e = entries[i];
+ Heap::StringOrSymbol *e = entriesByHash[i];
if (!e)
continue;
uint idx = e->stringHash % newAlloc;
@@ -100,17 +101,42 @@ void IdentifierTable::addEntry(Heap::String *str)
}
newEntries[idx] = e;
}
- free(entries);
- entries = newEntries;
+ free(entriesByHash);
+ entriesByHash = newEntries;
+
+ newEntries = (Heap::StringOrSymbol **)malloc(newAlloc*sizeof(Heap::String *));
+ memset(newEntries, 0, newAlloc*sizeof(Heap::StringOrSymbol *));
+ for (int i = 0; i < alloc; ++i) {
+ Heap::StringOrSymbol *e = entriesById[i];
+ if (!e)
+ continue;
+ uint idx = e->identifier.id() % newAlloc;
+ while (newEntries[idx]) {
+ ++idx;
+ idx %= newAlloc;
+ }
+ newEntries[idx] = e;
+ }
+ free(entriesById);
+ entriesById = newEntries;
+
alloc = newAlloc;
}
uint idx = hash % alloc;
- while (entries[idx]) {
+ while (entriesByHash[idx]) {
+ ++idx;
+ idx %= alloc;
+ }
+ entriesByHash[idx] = str;
+
+ idx = str->identifier.id() % alloc;
+ while (entriesById[idx]) {
++idx;
idx %= alloc;
}
- entries[idx] = str;
+ entriesById[idx] = str;
+
++size;
}
@@ -120,10 +146,16 @@ Heap::String *IdentifierTable::insertString(const QString &s)
{
uint subtype;
uint hash = String::createHashValue(s.constData(), s.length(), &subtype);
+ if (subtype == Heap::String::StringType_ArrayIndex) {
+ Heap::String *str = engine->newString(s);
+ str->stringHash = hash;
+ str->subtype = subtype;
+ return str;
+ }
uint idx = hash % alloc;
- while (Heap::String *e = entries[idx]) {
+ while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
if (e->stringHash == hash && e->toQString() == s)
- return e;
+ return static_cast<Heap::String *>(e);
++idx;
idx %= alloc;
}
@@ -135,18 +167,42 @@ Heap::String *IdentifierTable::insertString(const QString &s)
return str;
}
+Heap::Symbol *IdentifierTable::insertSymbol(const QString &s)
+{
+ Q_ASSERT(s.at(0) == QLatin1Char('@'));
+
+ uint subtype;
+ uint hash = String::createHashValue(s.constData(), s.length(), &subtype);
+ uint idx = hash % alloc;
+ while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
+ if (e->stringHash == hash && e->toQString() == s)
+ return static_cast<Heap::Symbol *>(e);
+ ++idx;
+ idx %= alloc;
+ }
+
+ Heap::Symbol *str = Symbol::create(engine, s);
+ str->stringHash = hash;
+ str->subtype = subtype;
+ addEntry(str);
+ return str;
-Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
+}
+
+
+PropertyKey IdentifierTable::asPropertyKeyImpl(const Heap::String *str)
{
- if (str->identifier)
+ if (str->identifier.isValid())
return str->identifier;
uint hash = str->hashValue();
- if (str->subtype == Heap::String::StringType_ArrayIndex)
- return nullptr;
+ if (str->subtype == Heap::String::StringType_ArrayIndex) {
+ str->identifier = PropertyKey::fromArrayIndex(hash);
+ return str->identifier;
+ }
uint idx = hash % alloc;
- while (Heap::String *e = entries[idx]) {
- if (e->stringHash == hash && e->isEqualTo(str)) {
+ while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
+ if (e->stringHash == hash && e->toQString() == str->toQString()) {
str->identifier = e->identifier;
return e->identifier;
}
@@ -158,37 +214,117 @@ Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
return str->identifier;
}
-Heap::String *IdentifierTable::stringFromIdentifier(Identifier *i)
+Heap::StringOrSymbol *IdentifierTable::resolveId(PropertyKey i) const
{
- if (!i)
+ uint arrayIdx = i.asArrayIndex();
+ if (arrayIdx < UINT_MAX)
+ return engine->newString(QString::number(arrayIdx));
+ if (!i.isValid())
return nullptr;
- uint idx = i->hashValue % alloc;
+ uint idx = i.id() % alloc;
while (1) {
- Heap::String *e = entries[idx];
- Q_ASSERT(e);
- if (e->identifier == i)
+ Heap::StringOrSymbol *e = entriesById[idx];
+ if (!e || e->identifier == i)
return e;
++idx;
idx %= alloc;
}
}
-Identifier *IdentifierTable::identifier(const QString &s)
+Heap::String *IdentifierTable::stringForId(PropertyKey i) const
+{
+ Heap::StringOrSymbol *s = resolveId(i);
+ Q_ASSERT(s && s->internalClass->vtable->isString);
+ return static_cast<Heap::String *>(s);
+}
+
+Heap::Symbol *IdentifierTable::symbolForId(PropertyKey i) const
+{
+ Heap::StringOrSymbol *s = resolveId(i);
+ Q_ASSERT(!s || !s->internalClass->vtable->isString);
+ return static_cast<Heap::Symbol *>(s);
+}
+
+void IdentifierTable::markObjects(MarkStack *markStack)
+{
+ for (const auto &h : idHashes)
+ h->markObjects(markStack);
+}
+
+template <typename Key>
+int sweepTable(Heap::StringOrSymbol **table, int alloc, std::function<Key(Heap::StringOrSymbol *)> f) {
+ int freed = 0;
+ uint lastKey = 0;
+
+ int lastEntry = -1;
+ int start = 0;
+ // start at an empty entry so we compress properly
+ for (; start < alloc; ++start) {
+ if (!table[start])
+ break;
+ }
+
+ for (int i = 0; i < alloc; ++i) {
+ int idx = (i + start) % alloc;
+ Heap::StringOrSymbol *entry = table[idx];
+ if (!entry) {
+ lastEntry = -1;
+ continue;
+ }
+ if (entry->isMarked()) {
+ if (lastEntry >= 0 && lastKey == (f(entry) % alloc)) {
+ Q_ASSERT(table[lastEntry] == nullptr);
+ table[lastEntry] = entry;
+ table[idx] = nullptr;
+
+ // find next free slot just like in addEntry()
+ do {
+ lastEntry = (lastEntry + 1) % alloc;
+ } while (table[lastEntry] != nullptr);
+ }
+ continue;
+ }
+ if (lastEntry == -1) {
+ lastEntry = idx;
+ lastKey = f(entry) % alloc;
+ }
+ table[idx] = nullptr;
+ ++freed;
+ }
+ for (int i = 0; i < alloc; ++i) {
+ Heap::StringOrSymbol *entry = table[i];
+ if (!entry)
+ continue;
+ Q_ASSERT(entry->isMarked());
+ }
+ return freed;
+}
+
+void IdentifierTable::sweep()
+{
+ int f = sweepTable<uint>(entriesByHash, alloc, [](Heap::StringOrSymbol *entry) {return entry->hashValue(); });
+ int freed = sweepTable<quint64>(entriesById, alloc, [](Heap::StringOrSymbol *entry) {return entry->identifier.id(); });
+ Q_UNUSED(f);
+ Q_ASSERT(f == freed);
+ size -= freed;
+}
+
+PropertyKey IdentifierTable::asPropertyKey(const QString &s)
{
return insertString(s)->identifier;
}
-Identifier *IdentifierTable::identifier(const char *s, int len)
+PropertyKey IdentifierTable::asPropertyKey(const char *s, int len)
{
uint subtype;
uint hash = String::createHashValue(s, len, &subtype);
if (hash == UINT_MAX)
- return identifier(QString::fromUtf8(s, len));
+ return asPropertyKey(QString::fromUtf8(s, len));
QLatin1String latin(s, len);
uint idx = hash % alloc;
- while (Heap::String *e = entries[idx]) {
+ while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
if (e->stringHash == hash && e->toQString() == latin)
return e->identifier;
++idx;
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index b0b08f1e54..3674ece84f 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -53,55 +53,61 @@
#include "qv4identifier_p.h"
#include "qv4string_p.h"
#include "qv4engine_p.h"
+#include <qset.h>
#include <limits.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct IdentifierTable
+struct Q_QML_PRIVATE_EXPORT IdentifierTable
{
ExecutionEngine *engine;
int alloc;
int size;
int numBits;
- Heap::String **entries;
+ Heap::StringOrSymbol **entriesByHash;
+ Heap::StringOrSymbol **entriesById;
- void addEntry(Heap::String *str);
+ QSet<IdentifierHashData *> idHashes;
+
+ void addEntry(Heap::StringOrSymbol *str);
public:
- IdentifierTable(ExecutionEngine *engine);
+ IdentifierTable(ExecutionEngine *engine, int numBits = 8);
~IdentifierTable();
Heap::String *insertString(const QString &s);
+ Heap::Symbol *insertSymbol(const QString &s);
- Identifier *identifier(const Heap::String *str) {
- if (str->identifier)
+ PropertyKey asPropertyKey(const Heap::String *str) {
+ if (str->identifier.isValid())
return str->identifier;
- return identifierImpl(str);
+ return asPropertyKeyImpl(str);
}
- Identifier *identifier(const QV4::String *str) {
- return identifier(str->d());
+ PropertyKey asPropertyKey(const QV4::String *str) {
+ return asPropertyKey(str->d());
}
- Identifier *identifier(const QString &s);
- Identifier *identifier(const char *s, int len);
+ PropertyKey asPropertyKey(const QString &s);
+ PropertyKey asPropertyKey(const char *s, int len);
+
+ PropertyKey asPropertyKeyImpl(const Heap::String *str);
- Identifier *identifierImpl(const Heap::String *str);
+ Heap::StringOrSymbol *resolveId(PropertyKey i) const;
+ Heap::String *stringForId(PropertyKey i) const;
+ Heap::Symbol *symbolForId(PropertyKey i) const;
- Heap::String *stringFromIdentifier(Identifier *i);
+ void markObjects(MarkStack *markStack);
+ void sweep();
- void mark(MarkStack *markStack) {
- for (int i = 0; i < alloc; ++i) {
- Heap::String *entry = entries[i];
- if (!entry || entry->isMarked())
- continue;
- entry->setMarkBit();
- Q_ASSERT(entry->vtable()->markObjects);
- entry->vtable()->markObjects(entry, markStack);
- }
+ void addIdentifierHash(IdentifierHashData *h) {
+ idHashes.insert(h);
+ }
+ void removeIdentifierHash(IdentifierHashData *h) {
+ idHashes.remove(h);
}
};
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index 3bfcf358bf..c890dc0550 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -47,7 +47,7 @@
QT_BEGIN_NAMESPACE
-using namespace QV4;
+namespace QV4 {
static const uchar prime_deltas[] = {
0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
@@ -74,27 +74,11 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
// fill up to max 50%
bool grow = (d->alloc <= d->size*2);
- if (classSize < d->size || grow) {
- PropertyHashData *dd = new PropertyHashData(grow ? d->numBits + 1 : d->numBits);
- for (int i = 0; i < d->alloc; ++i) {
- const Entry &e = d->entries[i];
- if (!e.identifier || e.index >= static_cast<unsigned>(classSize))
- continue;
- uint idx = e.identifier->hashValue % dd->alloc;
- while (dd->entries[idx].identifier) {
- ++idx;
- idx %= dd->alloc;
- }
- dd->entries[idx] = e;
- }
- dd->size = classSize;
- Q_ASSERT(d->refCount > 1);
- --d->refCount;
- d = dd;
- }
+ if (classSize < d->size || grow)
+ detach(grow, classSize);
- uint idx = entry.identifier->hashValue % d->alloc;
- while (d->entries[idx].identifier) {
+ uint idx = entry.identifier.id() % d->alloc;
+ while (d->entries[idx].identifier.isValid()) {
++idx;
idx %= d->alloc;
}
@@ -102,38 +86,125 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
++d->size;
}
+int PropertyHash::removeIdentifier(PropertyKey identifier, int classSize)
+{
+ int val = -1;
+ PropertyHashData *dd = new PropertyHashData(d->numBits);
+ for (int i = 0; i < d->alloc; ++i) {
+ const Entry &e = d->entries[i];
+ if (!e.identifier.isValid() || e.index >= static_cast<unsigned>(classSize))
+ continue;
+ if (e.identifier == identifier) {
+ val = e.index;
+ continue;
+ }
+ uint idx = e.identifier.id() % dd->alloc;
+ while (dd->entries[idx].identifier.isValid()) {
+ ++idx;
+ idx %= dd->alloc;
+ }
+ dd->entries[idx] = e;
+ }
+ dd->size = classSize;
+ if (!--d->refCount)
+ delete d;
+ d = dd;
+
+ Q_ASSERT(val != -1);
+ return val;
+}
+
+void PropertyHash::detach(bool grow, int classSize)
+{
+ if (d->refCount == 1 && !grow)
+ return;
-InternalClass::InternalClass(ExecutionEngine *engine)
- : engine(engine)
- , vtable(nullptr)
- , prototype(nullptr)
- , m_sealed(nullptr)
- , m_frozen(nullptr)
- , size(0)
- , extensible(true)
+ PropertyHashData *dd = new PropertyHashData(grow ? d->numBits + 1 : d->numBits);
+ for (int i = 0; i < d->alloc; ++i) {
+ const Entry &e = d->entries[i];
+ if (!e.identifier.isValid() || e.index >= static_cast<unsigned>(classSize))
+ continue;
+ uint idx = e.identifier.id() % dd->alloc;
+ while (dd->entries[idx].identifier.isValid()) {
+ ++idx;
+ idx %= dd->alloc;
+ }
+ dd->entries[idx] = e;
+ }
+ dd->size = classSize;
+ if (!--d->refCount)
+ delete d;
+ d = dd;
+}
+
+namespace Heap {
+
+void InternalClass::init(ExecutionEngine *engine)
{
- id = engine->newInternalClassId();
+ Base::init();
+ new (&propertyTable) PropertyHash();
+ new (&nameMap) SharedInternalClassData<PropertyKey>();
+ new (&propertyData) SharedInternalClassData<PropertyAttributes>();
+ new (&transitions) std::vector<Transition>();
+
+ this->engine = engine;
+ vtable = QV4::InternalClass::staticVTable();
+// prototype = nullptr;
+// parent = nullptr;
+// size = 0;
+ extensible = true;
+ isFrozen = false;
+ isSealed = false;
+ isUsedAsProto = false;
+ protoId = engine->newProtoId();
+
+ // Also internal classes need an internal class pointer. Simply make it point to itself
+ internalClass.set(engine, this);
}
-InternalClass::InternalClass(const QV4::InternalClass &other)
- : QQmlJS::Managed()
- , engine(other.engine)
- , vtable(other.vtable)
- , prototype(other.prototype)
- , propertyTable(other.propertyTable)
- , nameMap(other.nameMap)
- , propertyData(other.propertyData)
- , m_sealed(nullptr)
- , m_frozen(nullptr)
- , size(other.size)
- , extensible(other.extensible)
- , isUsedAsProto(other.isUsedAsProto)
+void InternalClass::init(Heap::InternalClass *other)
+{
+ Base::init();
+ Q_ASSERT(!other->isFrozen);
+ new (&propertyTable) PropertyHash(other->propertyTable);
+ new (&nameMap) SharedInternalClassData<PropertyKey>(other->nameMap);
+ new (&propertyData) SharedInternalClassData<PropertyAttributes>(other->propertyData);
+ new (&transitions) std::vector<Transition>();
+
+ engine = other->engine;
+ vtable = other->vtable;
+ prototype = other->prototype;
+ parent = other;
+ size = other->size;
+ extensible = other->extensible;
+ isSealed = other->isSealed;
+ isFrozen = other->isFrozen;
+ isUsedAsProto = other->isUsedAsProto;
+ protoId = engine->newProtoId();
+
+ internalClass.set(engine, other->internalClass);
+}
+
+void InternalClass::destroy()
{
- id = engine->newInternalClassId();
+#ifndef QT_NO_DEBUG
+ for (const auto &t : transitions) {
+ Q_ASSERT(!t.lookup || !t.lookup->isMarked());
+ }
+#endif
+ if (parent && parent->engine && parent->isMarked())
+ parent->removeChildEntry(this);
+
+ propertyTable.~PropertyHash();
+ nameMap.~SharedInternalClassData<PropertyKey>();
+ propertyData.~SharedInternalClassData<PropertyAttributes>();
+ transitions.~vector<Transition>();
+ engine = nullptr;
+ Base::destroy();
}
-static void insertHoleIntoPropertyData(Object *object, int idx)
+static void insertHoleIntoPropertyData(QV4::Object *object, int idx)
{
Heap::Object *o = object->d();
ExecutionEngine *v4 = o->internalClass->engine;
@@ -142,7 +213,7 @@ static void insertHoleIntoPropertyData(Object *object, int idx)
o->setProperty(v4, i, *o->propertyData(i - 1));
}
-static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
+static void removeFromPropertyData(QV4::Object *object, int idx, bool accessor = false)
{
Heap::Object *o = object->d();
ExecutionEngine *v4 = o->internalClass->engine;
@@ -154,20 +225,23 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals
o->setProperty(v4, size + 1, Primitive::undefinedValue());
}
-void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
+void InternalClass::changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index)
{
+ Q_ASSERT(id.isStringOrSymbol());
uint idx;
- InternalClass *oldClass = object->internalClass();
- InternalClass *newClass = oldClass->changeMember(string->identifier(), data, &idx);
+ Heap::InternalClass *oldClass = object->internalClass();
+ Heap::InternalClass *newClass = oldClass->changeMember(id, data, &idx);
if (index)
*index = idx;
+ uint oldSize = oldClass->size;
object->setInternalClass(newClass);
- if (newClass->size > oldClass->size) {
- Q_ASSERT(newClass->size == oldClass->size + 1);
+ // don't use oldClass anymore, it could be GC'ed
+ if (newClass->size > oldSize) {
+ Q_ASSERT(newClass->size == oldSize + 1);
insertHoleIntoPropertyData(object, idx);
- } else if (newClass->size < oldClass->size) {
- Q_ASSERT(newClass->size == oldClass->size - 1);
+ } else if (newClass->size < oldSize) {
+ Q_ASSERT(newClass->size == oldSize - 1);
removeFromPropertyData(object, idx + 1);
}
}
@@ -183,7 +257,16 @@ InternalClassTransition &InternalClass::lookupOrInsertTransition(const InternalC
}
}
-InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttributes data, uint *index)
+static void addDummyEntry(InternalClass *newClass, PropertyHash::Entry e)
+{
+ // add a dummy entry, since we need two entries for accessors
+ newClass->propertyTable.addEntry(e, newClass->size);
+ newClass->nameMap.add(newClass->size, PropertyKey::invalid());
+ newClass->propertyData.add(newClass->size, PropertyAttributes());
+ ++newClass->size;
+}
+
+Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, PropertyAttributes data, uint *index)
{
data.resolve();
uint idx = find(identifier);
@@ -193,7 +276,7 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri
*index = idx;
if (data == propertyData.at(idx))
- return this;
+ return static_cast<Heap::InternalClass *>(this);
Transition temp = { { identifier }, nullptr, (int)data.flags() };
Transition &t = lookupOrInsertTransition(temp);
@@ -201,14 +284,34 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri
return t.lookup;
// create a new class and add it to the tree
- InternalClass *newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
- newClass = newClass->changePrototype(prototype);
- for (uint i = 0; i < size; ++i) {
- if (i == idx) {
- newClass = newClass->addMember(nameMap.at(i), data);
- } else if (!propertyData.at(i).isEmpty()) {
- newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
+ Heap::InternalClass *newClass = engine->newClass(this);
+ if (data.isAccessor() != propertyData.at(idx).isAccessor()) {
+ // this changes the layout of the class, so we need to rebuild the data
+ newClass->propertyTable = PropertyHash();
+ newClass->nameMap = SharedInternalClassData<PropertyKey>();
+ newClass->propertyData = SharedInternalClassData<PropertyAttributes>();
+ newClass->size = 0;
+ for (uint i = 0; i < size; ++i) {
+ PropertyKey identifier = nameMap.at(i);
+ PropertyHash::Entry e = { identifier, newClass->size };
+ if (i && !identifier.isValid())
+ e.identifier = nameMap.at(i - 1);
+ newClass->propertyTable.addEntry(e, newClass->size);
+ newClass->nameMap.add(newClass->size, identifier);
+ if (i == idx) {
+ newClass->propertyData.add(newClass->size, data);
+ ++newClass->size;
+ if (data.isAccessor())
+ addDummyEntry(newClass, e);
+ else
+ ++i;
+ } else {
+ newClass->propertyData.add(newClass->size, propertyData.at(i));
+ ++newClass->size;
+ }
}
+ } else {
+ newClass->propertyData.set(idx, data);
}
t.lookup = newClass;
@@ -216,14 +319,16 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri
return newClass;
}
-InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
+Heap::InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
{
+ Scope scope(engine);
+ ScopedValue protectThis(scope, this);
if (proto)
proto->setUsedAsProto();
Q_ASSERT(prototype != proto);
Q_ASSERT(!proto || proto->internalClass->isUsedAsProto);
- Transition temp = { { nullptr }, nullptr, Transition::PrototypeChange };
+ Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::PrototypeChange };
temp.prototype = proto;
Transition &t = lookupOrInsertTransition(temp);
@@ -231,29 +336,19 @@ InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
return t.lookup;
// create a new class and add it to the tree
- InternalClass *newClass;
- if (!size && !prototype) {
- newClass = engine->newClass(*this);
- newClass->prototype = proto;
- } else {
- newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
- newClass = newClass->changePrototype(proto);
- for (uint i = 0; i < size; ++i) {
- if (!propertyData.at(i).isEmpty())
- newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
- }
- }
+ Heap::InternalClass *newClass = engine->newClass(this);
+ newClass->prototype = proto;
t.lookup = newClass;
return newClass;
}
-InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
+Heap::InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
{
Q_ASSERT(vtable != vt);
- Transition temp = { { nullptr }, nullptr, Transition::VTableChange };
+ Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::VTableChange };
temp.vtable = vt;
Transition &t = lookupOrInsertTransition(temp);
@@ -261,18 +356,8 @@ InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
return t.lookup;
// create a new class and add it to the tree
- InternalClass *newClass;
- if (this == engine->internalClasses[EngineBase::Class_Empty]) {
- newClass = engine->newClass(*this);
- newClass->vtable = vt;
- } else {
- newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vt);
- newClass = newClass->changePrototype(prototype);
- for (uint i = 0; i < size; ++i) {
- if (!propertyData.at(i).isEmpty())
- newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
- }
- }
+ Heap::InternalClass *newClass = engine->newClass(this);
+ newClass->vtable = vt;
t.lookup = newClass;
Q_ASSERT(t.lookup);
@@ -280,17 +365,17 @@ InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
return newClass;
}
-InternalClass *InternalClass::nonExtensible()
+Heap::InternalClass *InternalClass::nonExtensible()
{
if (!extensible)
return this;
- Transition temp = { { nullptr }, nullptr, Transition::NotExtensible};
+ Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::NotExtensible};
Transition &t = lookupOrInsertTransition(temp);
if (t.lookup)
return t.lookup;
- InternalClass *newClass = engine->newClass(*this);
+ Heap::InternalClass *newClass = engine->newClass(this);
newClass->extensible = false;
t.lookup = newClass;
@@ -298,31 +383,26 @@ InternalClass *InternalClass::nonExtensible()
return newClass;
}
-void InternalClass::addMember(Object *object, String *string, PropertyAttributes data, uint *index)
+void InternalClass::addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index)
{
+ Q_ASSERT(id.isStringOrSymbol());
data.resolve();
- object->internalClass()->engine->identifierTable->identifier(string);
- if (object->internalClass()->propertyTable.lookup(string->d()->identifier) < object->internalClass()->size) {
- changeMember(object, string, data, index);
+ if (object->internalClass()->propertyTable.lookup(id) < object->internalClass()->size) {
+ changeMember(object, id, data, index);
return;
}
uint idx;
- InternalClass *newClass = object->internalClass()->addMemberImpl(string->identifier(), data, &idx);
+ Heap::InternalClass *newClass = object->internalClass()->addMemberImpl(id, data, &idx);
if (index)
*index = idx;
object->setInternalClass(newClass);
}
-InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index)
-{
- engine->identifierTable->identifier(string);
- return addMember(string->identifier(), data, index);
-}
-
-InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttributes data, uint *index)
+Heap::InternalClass *InternalClass::addMember(PropertyKey identifier, PropertyAttributes data, uint *index)
{
+ Q_ASSERT(identifier.isStringOrSymbol());
data.resolve();
if (propertyTable.lookup(identifier) < size)
@@ -331,7 +411,7 @@ InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttribut
return addMemberImpl(identifier, data, index);
}
-InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index)
+Heap::InternalClass *InternalClass::addMemberImpl(PropertyKey identifier, PropertyAttributes data, uint *index)
{
Transition temp = { { identifier }, nullptr, (int)data.flags() };
Transition &t = lookupOrInsertTransition(temp);
@@ -343,109 +423,156 @@ InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttr
return t.lookup;
// create a new class and add it to the tree
- InternalClass *newClass = engine->newClass(*this);
+ Heap::InternalClass *newClass = engine->newClass(this);
PropertyHash::Entry e = { identifier, newClass->size };
newClass->propertyTable.addEntry(e, newClass->size);
newClass->nameMap.add(newClass->size, identifier);
newClass->propertyData.add(newClass->size, data);
++newClass->size;
- if (data.isAccessor()) {
- // add a dummy entry, since we need two entries for accessors
- newClass->propertyTable.addEntry(e, newClass->size);
- newClass->nameMap.add(newClass->size, 0);
- newClass->propertyData.add(newClass->size, PropertyAttributes());
- ++newClass->size;
- }
+ if (data.isAccessor())
+ addDummyEntry(newClass, e);
t.lookup = newClass;
Q_ASSERT(t.lookup);
return newClass;
}
-void InternalClass::removeMember(Object *object, Identifier *id)
+void InternalClass::removeChildEntry(InternalClass *child)
{
- InternalClass *oldClass = object->internalClass();
- uint propIdx = oldClass->propertyTable.lookup(id);
- Q_ASSERT(propIdx < oldClass->size);
+ Q_ASSERT(engine);
+ for (auto &t : transitions) {
+ if (t.lookup == child) {
+ t.lookup = nullptr;
+ return;
+ }
+ }
+ Q_UNREACHABLE();
- Transition temp = { { id }, nullptr, -1 };
- Transition &t = object->internalClass()->lookupOrInsertTransition(temp);
+}
- bool accessor = oldClass->propertyData.at(propIdx).isAccessor();
+void InternalClass::removeMember(QV4::Object *object, PropertyKey identifier)
+{
+ Heap::InternalClass *oldClass = object->internalClass();
+ Q_ASSERT(oldClass->propertyTable.lookup(identifier) < oldClass->size);
- if (t.lookup) {
- object->setInternalClass(t.lookup);
- } else {
+ Transition temp = { { identifier }, nullptr, Transition::RemoveMember };
+ Transition &t = object->internalClass()->lookupOrInsertTransition(temp);
+
+ if (!t.lookup) {
// create a new class and add it to the tree
- InternalClass *newClass = oldClass->engine->internalClasses[EngineBase::Class_Empty]->changeVTable(oldClass->vtable);
- newClass = newClass->changePrototype(oldClass->prototype);
- for (uint i = 0; i < oldClass->size; ++i) {
- if (i == propIdx)
- continue;
- if (!oldClass->propertyData.at(i).isEmpty())
- newClass = newClass->addMember(oldClass->nameMap.at(i), oldClass->propertyData.at(i));
- }
- object->setInternalClass(newClass);
+ Heap::InternalClass *newClass = oldClass->engine->newClass(oldClass);
+ // simply make the entry inaccessible
+ int idx = newClass->propertyTable.removeIdentifier(identifier, oldClass->size);
+ newClass->nameMap.set(idx, PropertyKey::invalid());
+ newClass->propertyData.set(idx, PropertyAttributes());
+ t.lookup = newClass;
+ Q_ASSERT(t.lookup);
}
+ object->setInternalClass(t.lookup);
- Q_ASSERT(object->internalClass()->size == oldClass->size - (accessor ? 2 : 1));
-
- // remove the entry in the property data
- removeFromPropertyData(object, propIdx, accessor);
-
- t.lookup = object->internalClass();
- Q_ASSERT(t.lookup);
+ // we didn't remove the data slot, just made it inaccessible
+ Q_ASSERT(object->internalClass()->size == oldClass->size);
}
-uint InternalClass::find(const String *string)
+Heap::InternalClass *InternalClass::sealed()
{
- engine->identifierTable->identifier(string);
- const Identifier *id = string->d()->identifier;
+ if (isSealed)
+ return this;
- uint index = propertyTable.lookup(id);
- if (index < size)
- return index;
+ bool alreadySealed = !extensible;
+ for (uint i = 0; i < size; ++i) {
+ PropertyAttributes attrs = propertyData.at(i);
+ if (attrs.isEmpty())
+ continue;
+ if (attrs.isConfigurable()) {
+ alreadySealed = false;
+ break;
+ }
+ }
- return UINT_MAX;
-}
+ if (alreadySealed) {
+ isSealed = true;
+ return this;
+ }
-InternalClass *InternalClass::sealed()
-{
- if (m_sealed)
- return m_sealed;
+ Transition temp = { { PropertyKey::invalid() }, nullptr, InternalClassTransition::Sealed };
+ Transition &t = lookupOrInsertTransition(temp);
+
+ if (t.lookup) {
+ Q_ASSERT(t.lookup && t.lookup->isSealed);
+ return t.lookup;
+ }
+
+ Heap::InternalClass *s = engine->newClass(this);
- m_sealed = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
- m_sealed = m_sealed->changePrototype(prototype);
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
continue;
attrs.setConfigurable(false);
- m_sealed = m_sealed->addMember(nameMap.at(i), attrs);
+ s->propertyData.set(i, attrs);
}
- m_sealed = m_sealed->nonExtensible();
+ s->extensible = false;
+ s->isSealed = true;
- m_sealed->m_sealed = m_sealed;
- return m_sealed;
+ t.lookup = s;
+ return s;
}
-InternalClass *InternalClass::frozen()
+Heap::InternalClass *InternalClass::frozen()
{
- if (m_frozen)
- return m_frozen;
+ if (isFrozen)
+ return this;
+
+ bool alreadyFrozen = !extensible;
+ for (uint i = 0; i < size; ++i) {
+ PropertyAttributes attrs = propertyData.at(i);
+ if (attrs.isEmpty())
+ continue;
+ if ((attrs.isData() && attrs.isWritable()) || attrs.isConfigurable()) {
+ alreadyFrozen = false;
+ break;
+ }
+ }
+
+ if (alreadyFrozen) {
+ isSealed = true;
+ isFrozen = true;
+ return this;
+ }
+
+ Transition temp = { { PropertyKey::invalid() }, nullptr, InternalClassTransition::Frozen };
+ Transition &t = lookupOrInsertTransition(temp);
+
+ if (t.lookup) {
+ Q_ASSERT(t.lookup && t.lookup->isSealed && t.lookup->isFrozen);
+ return t.lookup;
+ }
+
+ Heap::InternalClass *f = engine->newClass(this);
- m_frozen = propertiesFrozen();
- m_frozen = m_frozen->nonExtensible();
+ for (uint i = 0; i < size; ++i) {
+ PropertyAttributes attrs = propertyData.at(i);
+ if (attrs.isEmpty())
+ continue;
+ if (attrs.isData())
+ attrs.setWritable(false);
+ attrs.setConfigurable(false);
+ f->propertyData.set(i, attrs);
+ }
+ f->extensible = false;
+ f->isSealed = true;
+ f->isFrozen = true;
- m_frozen->m_frozen = m_frozen;
- m_frozen->m_sealed = m_frozen;
- return m_frozen;
+ t.lookup = f;
+ return f;
}
-InternalClass *InternalClass::propertiesFrozen() const
+Heap::InternalClass *InternalClass::propertiesFrozen() const
{
- InternalClass *frozen = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
+ Scope scope(engine);
+ Scoped<QV4::InternalClass> frozen(scope, engine->internalClasses(EngineBase::Class_Empty)->changeVTable(vtable));
frozen = frozen->changePrototype(prototype);
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
@@ -455,20 +582,20 @@ InternalClass *InternalClass::propertiesFrozen() const
attrs.setConfigurable(false);
frozen = frozen->addMember(nameMap.at(i), attrs);
}
- return frozen;
+ return frozen->d();
}
-InternalClass *InternalClass::asProtoClass()
+Heap::InternalClass *InternalClass::asProtoClass()
{
if (isUsedAsProto)
return this;
- Transition temp = { { nullptr }, nullptr, Transition::ProtoClass };
+ Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::ProtoClass };
Transition &t = lookupOrInsertTransition(temp);
if (t.lookup)
return t.lookup;
- InternalClass *newClass = engine->newClass(*this);
+ Heap::InternalClass *newClass = engine->newClass(this);
newClass->isUsedAsProto = true;
t.lookup = newClass;
@@ -476,90 +603,43 @@ InternalClass *InternalClass::asProtoClass()
return newClass;
}
-void InternalClass::destroy()
+static void updateProtoUsage(Heap::Object *o, Heap::InternalClass *ic)
{
- std::vector<InternalClass *> destroyStack;
- destroyStack.reserve(64);
- destroyStack.push_back(this);
-
- while (!destroyStack.empty()) {
- InternalClass *next = destroyStack.back();
- destroyStack.pop_back();
- if (!next->engine)
- continue;
- next->engine = nullptr;
- next->propertyTable.~PropertyHash();
- next->nameMap.~SharedInternalClassData<Identifier *>();
- next->propertyData.~SharedInternalClassData<PropertyAttributes>();
- if (next->m_sealed)
- destroyStack.push_back(next->m_sealed);
- if (next->m_frozen)
- destroyStack.push_back(next->m_frozen);
-
- for (size_t i = 0; i < next->transitions.size(); ++i) {
- Q_ASSERT(next->transitions.at(i).lookup);
- destroyStack.push_back(next->transitions.at(i).lookup);
- }
-
- next->transitions.~vector<Transition>();
+ if (ic->prototype == o)
+ ic->protoId = ic->engine->newProtoId();
+ for (auto &t : ic->transitions) {
+ if (t.lookup)
+ updateProtoUsage(o, t.lookup);
}
}
+
void InternalClass::updateProtoUsage(Heap::Object *o)
{
Q_ASSERT(isUsedAsProto);
- InternalClass *ic = engine->internalClasses[EngineBase::Class_Empty];
+ Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_Empty);
Q_ASSERT(!ic->prototype);
- // only need to go two levels into the IC hierarchy, as prototype changes
- // can only happen there
- for (auto &t : ic->transitions) {
- Q_ASSERT(t.lookup);
- if (t.flags == InternalClassTransition::VTableChange) {
- InternalClass *ic2 = t.lookup;
- for (auto &t2 : ic2->transitions) {
- if (t2.flags == InternalClassTransition::PrototypeChange &&
- t2.lookup->prototype == o)
- ic2->updateInternalClassIdRecursive();
- }
- } else if (t.flags == InternalClassTransition::PrototypeChange && t.lookup->prototype == o) {
- ic->updateInternalClassIdRecursive();
- }
- }
+ Heap::updateProtoUsage(o, ic);
}
-void InternalClass::updateInternalClassIdRecursive()
+void InternalClass::markObjects(Heap::Base *b, MarkStack *stack)
{
- id = engine->newInternalClassId();
- for (auto &t : transitions) {
- Q_ASSERT(t.lookup);
- if (t.flags == InternalClassTransition::VTableChange || t.flags == InternalClassTransition::PrototypeChange)
- continue;
- t.lookup->updateInternalClassIdRecursive();
+ Heap::InternalClass *ic = static_cast<Heap::InternalClass *>(b);
+ if (ic->prototype)
+ ic->prototype->mark(stack);
+ if (ic->parent)
+ ic->parent->mark(stack);
+
+ for (uint i = 0; i < ic->size; ++i) {
+ PropertyKey id = ic->nameMap.at(i);
+ if (Heap::Base *b = id.asStringOrSymbol())
+ b->mark(stack);
}
}
+}
-
-void InternalClassPool::markObjects(MarkStack *markStack)
-{
- InternalClass *ic = markStack->engine->internalClasses[EngineBase::Class_Empty];
- Q_ASSERT(!ic->prototype);
-
- // only need to go two levels into the IC hierarchy, as prototype changes
- // can only happen there
- for (auto &t : ic->transitions) {
- Q_ASSERT(t.lookup);
- if (t.flags == InternalClassTransition::VTableChange) {
- InternalClass *ic2 = t.lookup;
- for (auto &t2 : ic2->transitions) {
- if (t2.flags == InternalClassTransition::PrototypeChange)
- t2.lookup->prototype->mark(markStack);
- }
- } else if (t.flags == InternalClassTransition::PrototypeChange) {
- t.lookup->prototype->mark(markStack);
- }
- }
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index b689272006..888eedcaba 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -53,16 +53,13 @@
#include "qv4global_p.h"
#include <QHash>
-#include <private/qqmljsmemorypool_p.h>
-#include <private/qv4identifier_p.h>
+#include <private/qv4propertykey_p.h>
+#include <private/qv4heap_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct String;
-struct Object;
-struct Identifier;
struct VTable;
struct MarkStack;
@@ -70,7 +67,7 @@ struct PropertyHashData;
struct PropertyHash
{
struct Entry {
- const Identifier *identifier;
+ PropertyKey identifier;
uint index;
};
@@ -79,12 +76,12 @@ struct PropertyHash
inline PropertyHash();
inline PropertyHash(const PropertyHash &other);
inline ~PropertyHash();
+ PropertyHash &operator=(const PropertyHash &other);
void addEntry(const Entry &entry, int classSize);
- uint lookup(const Identifier *identifier) const;
-
-private:
- PropertyHash &operator=(const PropertyHash &other);
+ uint lookup(PropertyKey identifier) const;
+ int removeIdentifier(PropertyKey identifier, int classSize);
+ void detach(bool grow, int classSize);
};
struct PropertyHashData
@@ -118,15 +115,26 @@ inline PropertyHash::~PropertyHash()
delete d;
}
-inline uint PropertyHash::lookup(const Identifier *identifier) const
+inline PropertyHash &PropertyHash::operator=(const PropertyHash &other)
+{
+ ++other.d->refCount;
+ if (!--d->refCount)
+ delete d;
+ d = other.d;
+ return *this;
+}
+
+
+
+inline uint PropertyHash::lookup(PropertyKey identifier) const
{
Q_ASSERT(d->entries);
- uint idx = identifier->hashValue % d->alloc;
+ uint idx = identifier.id() % d->alloc;
while (1) {
if (d->entries[idx].identifier == identifier)
return d->entries[idx].index;
- if (!d->entries[idx].identifier)
+ if (!d->entries[idx].identifier.isValid())
return UINT_MAX;
++idx;
idx %= d->alloc;
@@ -163,6 +171,13 @@ struct SharedInternalClassData {
if (!--d->refcount)
delete d;
}
+ SharedInternalClassData &operator=(const SharedInternalClassData &other) {
+ ++other.d->refcount;
+ if (!--d->refcount)
+ delete d;
+ d = other.d;
+ return *this;
+ }
void add(uint pos, T value) {
if (pos < d->size) {
@@ -214,26 +229,26 @@ struct SharedInternalClassData {
Q_ASSERT(i < d->size);
return d->data[i];
}
-
-private:
- SharedInternalClassData &operator=(const SharedInternalClassData &other);
};
struct InternalClassTransition
{
union {
- Identifier *id;
+ PropertyKey id;
const VTable *vtable;
Heap::Object *prototype;
};
- InternalClass *lookup;
+ Heap::InternalClass *lookup;
int flags;
enum {
// range 0-0xff is reserved for attribute changes
NotExtensible = 0x100,
VTableChange = 0x200,
PrototypeChange = 0x201,
- ProtoClass = 0x202
+ ProtoClass = 0x202,
+ Sealed = 0x203,
+ Frozen = 0x204,
+ RemoveMember = -1
};
bool operator==(const InternalClassTransition &other) const
@@ -243,48 +258,44 @@ struct InternalClassTransition
{ return id < other.id || (id == other.id && flags < other.flags); }
};
-struct InternalClass : public QQmlJS::Managed {
- int id = 0; // unique across the engine, gets changed also when proto chain changes
+namespace Heap {
+
+struct InternalClass : Base {
ExecutionEngine *engine;
const VTable *vtable;
+ quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes
Heap::Object *prototype;
+ InternalClass *parent;
PropertyHash propertyTable; // id to valueIndex
- SharedInternalClassData<Identifier *> nameMap;
+ SharedInternalClassData<PropertyKey> nameMap;
SharedInternalClassData<PropertyAttributes> propertyData;
typedef InternalClassTransition Transition;
std::vector<Transition> transitions;
InternalClassTransition &lookupOrInsertTransition(const InternalClassTransition &t);
- InternalClass *m_sealed;
- InternalClass *m_frozen;
-
uint size;
bool extensible;
- bool isUsedAsProto = false;
+ bool isSealed;
+ bool isFrozen;
+ bool isUsedAsProto;
+
+ void init(ExecutionEngine *engine);
+ void init(InternalClass *other);
+ void destroy();
Q_REQUIRED_RESULT InternalClass *nonExtensible();
- Q_REQUIRED_RESULT InternalClass *changeVTable(const VTable *vt) {
- if (vtable == vt)
- return this;
- return changeVTableImpl(vt);
- }
- Q_REQUIRED_RESULT InternalClass *changePrototype(Heap::Object *proto) {
- if (prototype == proto)
- return this;
- return changePrototypeImpl(proto);
- }
- static void addMember(Object *object, String *string, PropertyAttributes data, uint *index);
- Q_REQUIRED_RESULT InternalClass *addMember(String *string, PropertyAttributes data, uint *index = nullptr);
- Q_REQUIRED_RESULT InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = nullptr);
- Q_REQUIRED_RESULT InternalClass *changeMember(Identifier *identifier, PropertyAttributes data, uint *index = nullptr);
- static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = nullptr);
- static void removeMember(Object *object, Identifier *id);
- uint find(const String *string);
- uint find(const Identifier *id)
+ static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index);
+ Q_REQUIRED_RESULT InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, uint *index = nullptr);
+ Q_REQUIRED_RESULT InternalClass *changeMember(PropertyKey identifier, PropertyAttributes data, uint *index = nullptr);
+ static void changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index = nullptr);
+ static void removeMember(QV4::Object *object, PropertyKey identifier);
+ uint find(const PropertyKey id)
{
+ Q_ASSERT(id.isStringOrSymbol());
+
uint index = propertyTable.lookup(id);
if (index < size)
return index;
@@ -298,24 +309,37 @@ struct InternalClass : public QQmlJS::Managed {
Q_REQUIRED_RESULT InternalClass *asProtoClass();
- void destroy();
+ Q_REQUIRED_RESULT InternalClass *changeVTable(const VTable *vt) {
+ if (vtable == vt)
+ return this;
+ return changeVTableImpl(vt);
+ }
+ Q_REQUIRED_RESULT InternalClass *changePrototype(Heap::Object *proto) {
+ if (prototype == proto)
+ return this;
+ return changePrototypeImpl(proto);
+ }
void updateProtoUsage(Heap::Object *o);
+ static void markObjects(Heap::Base *ic, MarkStack *stack);
+
private:
Q_QML_EXPORT InternalClass *changeVTableImpl(const VTable *vt);
Q_QML_EXPORT InternalClass *changePrototypeImpl(Heap::Object *proto);
- InternalClass *addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index);
- void updateInternalClassIdRecursive();
+ InternalClass *addMemberImpl(PropertyKey identifier, PropertyAttributes data, uint *index);
+
+ void removeChildEntry(InternalClass *child);
friend struct ExecutionEngine;
- InternalClass(ExecutionEngine *engine);
- InternalClass(const InternalClass &other);
};
-struct InternalClassPool : public QQmlJS::MemoryPool
+inline
+void Base::markObjects(Base *b, MarkStack *stack)
{
- void markObjects(MarkStack *markStack);
-};
+ b->internalClass->mark(stack);
+}
+
+}
}
diff --git a/src/qml/jsruntime/qv4iterator.cpp b/src/qml/jsruntime/qv4iterator.cpp
new file mode 100644
index 0000000000..df8000a8f7
--- /dev/null
+++ b/src/qml/jsruntime/qv4iterator.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qv4iterator_p.h>
+#include <qv4symbol_p.h>
+#include <qv4engine_p.h>
+
+using namespace QV4;
+
+void IteratorPrototype::init(ExecutionEngine *engine)
+{
+ defineDefaultProperty(engine->symbol_iterator(), method_iterator, 0);
+}
+
+ReturnedValue IteratorPrototype::method_iterator(const FunctionObject *, const Value *thisObject, const Value *, int)
+{
+ return thisObject->asReturnedValue();
+}
+
+
+ReturnedValue IteratorPrototype::createIterResultObject(ExecutionEngine *engine, const Value &value, bool done)
+{
+ Scope scope(engine);
+ ScopedObject obj(scope, engine->newObject());
+ obj->set(ScopedString(scope, engine->newString(QStringLiteral("value"))), value, Object::DoNotThrow);
+ obj->set(ScopedString(scope, engine->newString(QStringLiteral("done"))), Primitive::fromBoolean(done), Object::DoNotThrow);
+ return obj->asReturnedValue();
+}
+
diff --git a/src/qml/jsruntime/qv4iterator_p.h b/src/qml/jsruntime/qv4iterator_p.h
new file mode 100644
index 0000000000..28e337d21b
--- /dev/null
+++ b/src/qml/jsruntime/qv4iterator_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4ITERATOR_P_H
+#define QV4ITERATOR_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 "qv4object_p.h"
+#include "qv4arraydata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+namespace QV4 {
+
+enum IteratorKind {
+ KeyIteratorKind,
+ ValueIteratorKind,
+ KeyValueIteratorKind
+};
+
+struct IteratorPrototype : Object
+{
+ void init(ExecutionEngine *engine);
+
+ static ReturnedValue method_iterator(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue createIterResultObject(ExecutionEngine *engine, const Value &value, bool done);
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4ARRAYITERATOR_P_H
+
diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h
index c676b57c51..307eec9111 100644
--- a/src/qml/jsruntime/qv4jscall_p.h
+++ b/src/qml/jsruntime/qv4jscall_p.h
@@ -55,6 +55,7 @@
#include "qv4functionobject_p.h"
#include "qv4context_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4stackframe_p.h"
QT_BEGIN_NAMESPACE
@@ -67,7 +68,7 @@ struct JSCallData {
if (thisObject)
this->thisObject = const_cast<Value *>(thisObject);
else
- this->thisObject = scope.alloc(1);
+ this->thisObject = scope.alloc();
if (argv)
this->args = const_cast<Value *>(argv);
else
@@ -80,8 +81,7 @@ struct JSCallData {
CallData *callData(const FunctionObject *f = nullptr) const {
int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
- CallData *ptr = reinterpret_cast<CallData *>(scope.engine->jsStackTop);
- scope.engine->jsStackTop += size;
+ CallData *ptr = reinterpret_cast<CallData *>(scope.alloc<Scope::Uninitialized>(size));
ptr->function = Encode::undefined();
ptr->context = Encode::undefined();
ptr->accumulator = Encode::undefined();
@@ -102,7 +102,9 @@ struct JSCallData {
inline
ReturnedValue FunctionObject::callAsConstructor(const JSCallData &data) const
{
- return d()->jsConstruct(this, data.args, data.argc);
+ if (!d()->jsConstruct)
+ return engine()->throwTypeError(QStringLiteral("Object is not a constructor."));
+ return d()->jsConstruct(this, data.args, data.argc, this);
}
inline
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index c3569c29d2..2e2314cafe 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -47,6 +47,7 @@
#include <qv4variantobject_p.h>
#include "qv4string_p.h"
#include "qv4jscall_p.h"
+#include <qv4symbol_p.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -260,11 +261,12 @@ bool JsonParser::parseMember(Object *o)
if (!parseValue(val))
return false;
- ScopedString s(scope, engine->newIdentifier(key));
- uint idx = s->asArrayIndex();
- if (idx < UINT_MAX) {
- o->putIndexed(idx, val);
+ ScopedString s(scope, engine->newString(key));
+ PropertyKey skey = s->toPropertyKey();
+ if (skey.isArrayIndex()) {
+ o->put(skey.asArrayIndex(), val);
} else {
+ // avoid trouble with properties named __proto__
o->insertMember(s, val);
}
@@ -743,7 +745,7 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
if (!o->as<FunctionObject>()) {
- if (o->as<ArrayObject>() || o->isListType()) {
+ if (o->isArrayLike()) {
return JA(o.getPointer());
} else {
return JO(o);
@@ -846,7 +848,7 @@ QString Stringify::JA(Object *a)
ScopedValue v(scope);
for (uint i = 0; i < len; ++i) {
bool exists;
- v = a->getIndexed(i, &exists);
+ v = a->get(i, &exists);
if (!exists) {
partial += QStringLiteral("null");
continue;
@@ -881,6 +883,8 @@ void Heap::JsonObject::init()
o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2);
o->defineDefaultProperty(QStringLiteral("stringify"), QV4::JsonObject::method_stringify, 3);
+ ScopedString json(scope, scope.engine->newString(QStringLiteral("JSON")));
+ o->defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), json);
}
@@ -916,7 +920,7 @@ ReturnedValue JsonObject::method_stringify(const FunctionObject *b, const Value
stringify.propertyList = static_cast<QV4::String *>(scope.alloc(arrayLen));
for (uint i = 0; i < arrayLen; ++i) {
Value *v = stringify.propertyList + i;
- *v = o->getIndexed(i);
+ *v = o->get(i);
if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
*v = v->toString(scope.engine);
if (!v->isString()) {
@@ -1078,7 +1082,7 @@ QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObj
ScopedValue v(scope);
quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
- v = a->getIndexed(i);
+ v = a->get(i);
if (v->as<FunctionObject>())
v = Encode::null();
result.append(toJsonValue(v, visitedObjects));
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 52ab03cd94..daa5b2dfbd 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-void Lookup::resolveProtoGetter(Identifier *name, const Heap::Object *proto)
+void Lookup::resolveProtoGetter(PropertyKey name, const Heap::Object *proto)
{
while (proto) {
uint index = proto->internalClass->find(name);
@@ -70,7 +70,12 @@ void Lookup::resolveProtoGetter(Identifier *name, const Heap::Object *proto)
ReturnedValue Lookup::resolveGetter(ExecutionEngine *engine, const Object *object)
{
Heap::Object *obj = object->d();
- Identifier *name = engine->identifierTable->identifier(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ if (name.isArrayIndex()) {
+ indexedLookup.index = name.asArrayIndex();
+ getter = getterIndexed;
+ return getter(this, engine, *object);
+ }
uint index = obj->internalClass->find(name);
if (index != UINT_MAX) {
@@ -92,7 +97,7 @@ ReturnedValue Lookup::resolveGetter(ExecutionEngine *engine, const Object *objec
return getter(this, engine, *object);
}
- protoLookup.icIdentifier = obj->internalClass->id;
+ protoLookup.protoId = obj->internalClass->protoId;
resolveProtoGetter(name, obj->prototype());
return getter(this, engine, *object);
}
@@ -109,11 +114,12 @@ ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Valu
break;
case Value::Managed_Type: {
// ### Should move this over to the Object path, as strings also have an internalClass
- Q_ASSERT(object.isString());
- primitiveLookup.proto = engine->stringPrototype()->d();
+ Q_ASSERT(object.isStringOrSymbol());
+ primitiveLookup.proto = static_cast<const Managed &>(object).internalClass()->prototype;
+ Q_ASSERT(primitiveLookup.proto);
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- if (name->equals(engine->id_length())) {
+ if (object.isString() && name->equals(engine->id_length())) {
// special case, as the property is on the object itself
getter = stringLengthGetter;
return stringLengthGetter(this, engine, object);
@@ -125,8 +131,8 @@ ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Valu
primitiveLookup.proto = engine->numberPrototype()->d();
}
- Identifier *name = engine->identifierTable->identifier(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- protoLookup.icIdentifier = primitiveLookup.proto->internalClass->id;
+ PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ protoLookup.protoId = primitiveLookup.proto->internalClass->protoId;
resolveProtoGetter(name, primitiveLookup.proto);
if (getter == getterProto)
@@ -139,8 +145,8 @@ ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Valu
ReturnedValue Lookup::resolveGlobalGetter(ExecutionEngine *engine)
{
Object *o = engine->globalObject;
- Identifier *name = engine->identifierTable->identifier(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- protoLookup.icIdentifier = o->internalClass()->id;
+ PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ protoLookup.protoId = o->internalClass()->protoId;
resolveProtoGetter(name, o->d());
if (getter == getterProto)
@@ -188,16 +194,16 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const
return result;
}
if (first.getter == getterProto && second.getter == getterProto) {
- l->protoLookupTwoClasses.icIdentifier = first.protoLookup.icIdentifier;
- l->protoLookupTwoClasses.icIdentifier2 = second.protoLookup.icIdentifier;
+ l->protoLookupTwoClasses.protoId = first.protoLookup.protoId;
+ l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId;
l->protoLookupTwoClasses.data = first.protoLookup.data;
l->protoLookupTwoClasses.data2 = second.protoLookup.data;
l->getter = getterProtoTwoClasses;
return result;
}
if (first.getter == getterProtoAccessor && second.getter == getterProtoAccessor) {
- l->protoLookupTwoClasses.icIdentifier = first.protoLookup.icIdentifier;
- l->protoLookupTwoClasses.icIdentifier2 = second.protoLookup.icIdentifier;
+ l->protoLookupTwoClasses.protoId = first.protoLookup.protoId;
+ l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId;
l->protoLookupTwoClasses.data = first.protoLookup.data;
l->protoLookupTwoClasses.data2 = second.protoLookup.data;
l->getter = getterProtoAccessorTwoClasses;
@@ -250,7 +256,7 @@ ReturnedValue Lookup::getterProto(Lookup *l, ExecutionEngine *engine, const Valu
// the internal class won't match
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o) {
- if (l->protoLookup.icIdentifier == o->internalClass->id)
+ if (l->protoLookup.protoId == o->internalClass->protoId)
return l->protoLookup.data->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
@@ -307,9 +313,9 @@ ReturnedValue Lookup::getterProtoTwoClasses(Lookup *l, ExecutionEngine *engine,
// the internal class won't match
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o) {
- if (l->protoLookupTwoClasses.icIdentifier == o->internalClass->id)
+ if (l->protoLookupTwoClasses.protoId == o->internalClass->protoId)
return l->protoLookupTwoClasses.data->asReturnedValue();
- if (l->protoLookupTwoClasses.icIdentifier2 == o->internalClass->id)
+ if (l->protoLookupTwoClasses.protoId2 == o->internalClass->protoId)
return l->protoLookupTwoClasses.data2->asReturnedValue();
return getterFallback(l, engine, object);
}
@@ -340,14 +346,13 @@ ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, co
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
- if (o && l->protoLookup.icIdentifier == o->internalClass->id) {
+ if (o && l->protoLookup.protoId == o->internalClass->protoId) {
const Value *getter = l->protoLookup.data;
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0);
}
- l->getter = getterTwoClasses;
return getterTwoClasses(l, engine, object);
}
@@ -358,9 +363,9 @@ ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o) {
const Value *getter = nullptr;
- if (l->protoLookupTwoClasses.icIdentifier == o->internalClass->id)
+ if (l->protoLookupTwoClasses.protoId == o->internalClass->protoId)
getter = l->protoLookupTwoClasses.data;
- else if (l->protoLookupTwoClasses.icIdentifier2 == o->internalClass->id)
+ else if (l->protoLookupTwoClasses.protoId2 == o->internalClass->protoId)
getter = l->protoLookupTwoClasses.data2;
if (getter) {
if (!getter->isFunctionObject()) // ### catch at resolve time
@@ -373,11 +378,29 @@ ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *
return getterFallback(l, engine, object);
}
+ReturnedValue Lookup::getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object)
+{
+ Object *o = object.objectValue();
+ if (o) {
+ Heap::Object *ho = o->d();
+ if (ho->arrayData && ho->arrayData->type == Heap::ArrayData::Simple) {
+ Heap::SimpleArrayData *s = ho->arrayData.cast<Heap::SimpleArrayData>();
+ if (l->indexedLookup.index < s->values.size)
+ if (!s->data(l->indexedLookup.index).isEmpty())
+ return s->data(l->indexedLookup.index).asReturnedValue();
+ }
+ return o->get(l->indexedLookup.index);
+ }
+ l->getter = getterFallback;
+ return getterFallback(l, engine, object);
+
+}
+
ReturnedValue Lookup::primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object)
{
if (object.type() == l->primitiveLookup.type) {
Heap::Object *o = l->primitiveLookup.proto;
- if (l->primitiveLookup.icIdentifier == o->internalClass->id)
+ if (l->primitiveLookup.protoId == o->internalClass->protoId)
return l->primitiveLookup.data->asReturnedValue();
}
l->getter = getterGeneric;
@@ -388,7 +411,7 @@ ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine
{
if (object.type() == l->primitiveLookup.type) {
Heap::Object *o = l->primitiveLookup.proto;
- if (l->primitiveLookup.icIdentifier == o->internalClass->id) {
+ if (l->primitiveLookup.protoId == o->internalClass->protoId) {
const Value *getter = l->primitiveLookup.data;
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
@@ -417,7 +440,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine)
{
Heap::Object *o = engine->globalObject->d();
- if (l->protoLookup.icIdentifier == o->internalClass->id)
+ if (l->protoLookup.protoId == o->internalClass->protoId)
return l->protoLookup.data->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -426,7 +449,7 @@ ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine)
{
Heap::Object *o = engine->globalObject->d();
- if (l->protoLookup.icIdentifier == o->internalClass->id) {
+ if (l->protoLookup.protoId == o->internalClass->protoId) {
const Value *getter = l->protoLookup.data;
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
@@ -442,8 +465,9 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value
Scope scope(engine);
ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- InternalClass *c = object->internalClass();
- uint idx = c->find(name);
+ Heap::InternalClass *c = object->internalClass();
+ PropertyKey key = name->toPropertyKey();
+ uint idx = c->find(key);
if (idx != UINT_MAX) {
if (object->isArrayObject() && idx == Heap::ArrayObject::LengthPropertyIndex) {
setter = arrayLengthSetter;
@@ -460,8 +484,8 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value
return setter(this, engine, *object, value);
}
- insertionLookup.icIdentifier = c->id;
- if (!object->put(name, value)) {
+ insertionLookup.protoId = c->protoId;
+ if (!object->put(key, value)) {
setter = Lookup::setterFallback;
return false;
}
@@ -471,7 +495,7 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value
setter = setterFallback;
return true;
}
- idx = object->internalClass()->find(name);
+ idx = object->internalClass()->find(key);
if (idx == UINT_MAX) { // ### can this even happen?
setter = setterFallback;
return false;
@@ -574,7 +598,7 @@ bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c
bool Lookup::setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
- if (o && o->internalClass()->id == l->insertionLookup.icIdentifier) {
+ if (o && o->internalClass()->protoId == l->insertionLookup.protoId) {
o->setInternalClass(l->insertionLookup.newClass);
o->d()->setProperty(engine, l->insertionLookup.offset, value);
return true;
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 5f507733fd..c7555539b4 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct Lookup {
- enum { Size = 4 };
union {
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
@@ -73,44 +72,57 @@ struct Lookup {
};
union {
struct {
- InternalClass *ic;
+ Heap::Base *h1;
+ Heap::Base *h2;
+ quintptr unused;
+ quintptr unused2;
+ } markDef;
+ struct {
+ Heap::InternalClass *ic;
+ quintptr _unused;
int offset;
} objectLookup;
struct {
+ quintptr protoId;
+ quintptr _unused;
const Value *data;
- int icIdentifier;
} protoLookup;
struct {
- InternalClass *ic;
- InternalClass *ic2;
+ Heap::InternalClass *ic;
+ Heap::InternalClass *ic2;
int offset;
int offset2;
} objectLookupTwoClasses;
struct {
+ quintptr protoId;
+ quintptr protoId2;
const Value *data;
const Value *data2;
- int icIdentifier;
- int icIdentifier2;
} protoLookupTwoClasses;
struct {
// Make sure the next two values are in sync with protoLookup
- const Value *data;
- int icIdentifier;
- unsigned type;
+ quintptr protoId;
Heap::Object *proto;
+ const Value *data;
+ quintptr type;
} primitiveLookup;
struct {
- InternalClass *newClass;
- int icIdentifier;
+ Heap::InternalClass *newClass;
+ quintptr protoId;
int offset;
} insertionLookup;
+ struct {
+ quintptr _unused;
+ quintptr _unused2;
+ uint index;
+ } indexedLookup;
};
uint nameIndex;
ReturnedValue resolveGetter(ExecutionEngine *engine, const Object *object);
ReturnedValue resolvePrimitiveGetter(ExecutionEngine *engine, const Value &object);
ReturnedValue resolveGlobalGetter(ExecutionEngine *engine);
- void resolveProtoGetter(Identifier *name, const Heap::Object *proto);
+ void resolveProtoGetter(PropertyKey name, const Heap::Object *proto);
static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
@@ -126,6 +138,7 @@ struct Lookup {
static ReturnedValue getterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue getterProtoAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
+ static ReturnedValue getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
@@ -144,6 +157,17 @@ struct Lookup {
static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+
+ void markObjects(MarkStack *stack) {
+ if (markDef.h1 && !(reinterpret_cast<quintptr>(markDef.h1) & 1))
+ markDef.h1->mark(stack);
+ if (markDef.h2 && !(reinterpret_cast<quintptr>(markDef.h2) & 1))
+ markDef.h2->mark(stack);
+ }
+
+ void clear() {
+ memset(&markDef, 0, sizeof(markDef));
+ }
};
Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index b50e5f0355..bb7b8086e4 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -43,34 +43,23 @@
using namespace QV4;
+DEFINE_MANAGED_VTABLE(Managed);
-const VTable Managed::static_vtbl =
-{
- nullptr,
- 0,
- 0,
- Managed::IsExecutionContext,
- Managed::IsString,
- Managed::IsObject,
- Managed::IsFunctionObject,
- Managed::IsErrorObject,
- Managed::IsArrayData,
- 0,
- Managed::MyType,
- "Managed",
- nullptr,
- nullptr /*markObjects*/,
- isEqualTo
-};
+DEFINE_MANAGED_VTABLE(InternalClass);
QString Managed::className() const
{
const char *s = nullptr;
- switch (Type(d()->vtable()->type)) {
+ switch (Type(vtable()->type)) {
case Type_Invalid:
- case Type_String:
return QString();
+ case Type_String:
+ s = "String";
+ break;
+ case Type_Symbol:
+ s = "Symbol";
+ break;
case Type_Object:
s = "Object";
break;
@@ -80,6 +69,9 @@ QString Managed::className() const
case Type_FunctionObject:
s = "Function";
break;
+ case Type_GeneratorObject:
+ s = "Generator";
+ break;
case Type_BooleanObject:
s = "Boolean";
break;
@@ -89,6 +81,9 @@ QString Managed::className() const
case Type_StringObject:
s = "String";
break;
+ case Type_SymbolObject:
+ s = "Symbol";
+ break;
case Type_DateObject:
s = "Date";
break;
@@ -96,7 +91,7 @@ QString Managed::className() const
s = "RegExp";
break;
case Type_ErrorObject:
- s = ErrorObject::className(static_cast<Heap::ErrorObject *>(d())->errorType);
+ s = "Error";
break;
case Type_ArgumentsObject:
s = "Arguments";
@@ -104,6 +99,9 @@ QString Managed::className() const
case Type_JsonObject:
s = "JSON";
break;
+ case Type_ProxyObject:
+ s = "ProxyObject";
+ break;
case Type_MathObject:
s = "Math";
break;
@@ -111,8 +109,23 @@ QString Managed::className() const
case Type_ExecutionContext:
s = "__ExecutionContext";
break;
- case Type_ForeachIteratorObject:
- s = "__ForeachIterator";
+ case Type_MapIteratorObject:
+ s = "Map Iterator";
+ break;
+ case Type_SetIteratorObject:
+ s = "Set Iterator";
+ break;
+ case Type_ArrayIteratorObject:
+ s = "Array Iterator";
+ break;
+ case Type_StringIteratorObject:
+ s = "String Iterator";
+ break;
+ case Type_ForInIterator:
+ s = "__ForIn Iterator";
+ break;
+ case Type_InternalClass:
+ s = "__InternalClass";
break;
case Type_RegExp:
s = "__RegExp";
@@ -125,7 +138,7 @@ QString Managed::className() const
return QString::fromLatin1(s);
}
-bool Managed::isEqualTo(Managed *, Managed *)
+bool Managed::virtualIsEqualTo(Managed *, Managed *)
{
return false;
}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 092c61b81c..cacb262ba7 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -55,6 +55,7 @@
#include "qv4enginebase_p.h"
#include <private/qv4heap_p.h>
#include <private/qv4writebarrier_p.h>
+#include <private/qv4vtable_p.h>
QT_BEGIN_NAMESPACE
@@ -70,13 +71,9 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
template <typename T1, typename T2>
inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
-#ifdef Q_COMPILER_STATIC_ASSERT
-#define V4_MANAGED_SIZE_TEST void __dataTest() { Q_STATIC_ASSERT(sizeof(*this) == sizeof(Managed)); }
-#else
-#define V4_MANAGED_SIZE_TEST
-#endif
+#define V4_MANAGED_SIZE_TEST void __dataTest() { static_assert (sizeof(*this) == sizeof(Managed), "Classes derived from Managed can't have own data members."); }
-#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->destroy(); }
+#define V4_NEEDS_DESTROY static void virtualDestroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->destroy(); }
#define V4_MANAGED_ITSELF(DataClass, superClass) \
@@ -92,77 +89,30 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
QV4::Heap::DataClass *dptr = d_unchecked(); \
dptr->_checkIsInitialized(); \
return dptr; \
- } \
- Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
+ }
#define V4_MANAGED(DataClass, superClass) \
private: \
DataClass() Q_DECL_EQ_DELETE; \
Q_DISABLE_COPY(DataClass) \
- V4_MANAGED_ITSELF(DataClass, superClass)
+ V4_MANAGED_ITSELF(DataClass, superClass) \
+ Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
#define Q_MANAGED_TYPE(type) \
public: \
enum { MyType = Type_##type };
-#define Q_VTABLE_FUNCTION(classname, func) \
- (classname::func == QV4::Managed::func ? 0 : classname::func)
-
-// Q_VTABLE_FUNCTION triggers a bogus tautological-compare warning in GCC6+
-#if (defined(Q_CC_GNU) && Q_CC_GNU >= 600)
-#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
- QT_WARNING_PUSH; \
- QT_WARNING_DISABLE_GCC("-Wtautological-compare")
-
-#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \
- ;QT_WARNING_POP
-#elif defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
-#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
- QT_WARNING_PUSH; \
- QT_WARNING_DISABLE_CLANG("-Wtautological-compare")
-
-#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \
- ;QT_WARNING_POP
-#else
-#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON
-#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
-#endif
-
-#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
-{ \
- parentVTable, \
- (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
- (sizeof(classname::Data) + (classname::NInlineProperties*sizeof(QV4::Value)) + QV4::Chunk::SlotSize - 1)/QV4::Chunk::SlotSize*QV4::Chunk::SlotSize/sizeof(QV4::Value) \
- - (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
- classname::IsExecutionContext, \
- classname::IsString, \
- classname::IsObject, \
- classname::IsFunctionObject, \
- classname::IsErrorObject, \
- classname::IsArrayData, \
- 0, \
- classname::MyType, \
- #classname, \
- Q_VTABLE_FUNCTION(classname, destroy), \
- classname::Data::markObjects, \
- isEqualTo \
-} \
-
-#define DEFINE_MANAGED_VTABLE(classname) \
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
-const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) \
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
-
#define V4_INTERNALCLASS(c) \
- static QV4::InternalClass *defaultInternalClass(QV4::EngineBase *e) \
- { return e->internalClasses[QV4::EngineBase::Class_##c]; }
+ static Heap::InternalClass *defaultInternalClass(QV4::EngineBase *e) \
+ { return e->internalClasses(QV4::EngineBase::Class_##c); }
-struct Q_QML_PRIVATE_EXPORT Managed : Value
+struct Q_QML_PRIVATE_EXPORT Managed : Value, VTableBase
{
V4_MANAGED_ITSELF(Base, Managed)
enum {
IsExecutionContext = false,
IsString = false,
+ IsStringOrSymbol = false,
IsObject = false,
IsFunctionObject = false,
IsErrorObject = false,
@@ -180,47 +130,55 @@ public:
Type_Invalid,
Type_String,
Type_Object,
+ Type_Symbol,
Type_ArrayObject,
Type_FunctionObject,
+ Type_GeneratorObject,
Type_BooleanObject,
Type_NumberObject,
Type_StringObject,
+ Type_SymbolObject,
Type_DateObject,
Type_RegExpObject,
Type_ErrorObject,
Type_ArgumentsObject,
Type_JsonObject,
Type_MathObject,
+ Type_ProxyObject,
Type_ExecutionContext,
- Type_ForeachIteratorObject,
+ Type_InternalClass,
+ Type_SetIteratorObject,
+ Type_MapIteratorObject,
+ Type_ArrayIteratorObject,
+ Type_StringIteratorObject,
+ Type_ForInIterator,
Type_RegExp,
Type_QmlSequence
};
Q_MANAGED_TYPE(Invalid)
- InternalClass *internalClass() const { return d()->internalClass; }
+ Heap::InternalClass *internalClass() const { return d()->internalClass; }
+ const VTable *vtable() const { return d()->internalClass->vtable; }
inline ExecutionEngine *engine() const { return internalClass()->engine; }
- bool isListType() const { return d()->vtable()->type == Type_QmlSequence; }
+ bool isListType() const { return d()->internalClass->vtable->type == Type_QmlSequence; }
+ bool isArrayLike() const { return isArrayObject() || isListType(); }
- bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; }
- bool isStringObject() const { return d()->vtable()->type == Type_StringObject; }
+ bool isArrayObject() const { return d()->internalClass->vtable->type == Type_ArrayObject; }
+ bool isStringObject() const { return d()->internalClass->vtable->type == Type_StringObject; }
+ bool isSymbolObject() const { return d()->internalClass->vtable->type == Type_SymbolObject; }
QString className() const;
bool isEqualTo(const Managed *other) const
- { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
-
- static bool isEqualTo(Managed *m, Managed *other);
+ { return d()->internalClass->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
bool inUse() const { return d()->inUse(); }
bool markBit() const { return d()->isMarked(); }
inline void mark(MarkStack *markStack);
- static void destroy(Heap::Base *) {}
-
Q_ALWAYS_INLINE Heap::Base *heapObject() const {
return m();
}
@@ -232,6 +190,9 @@ public:
return static_cast<const T *>(this);
}
+protected:
+ static bool virtualIsEqualTo(Managed *m, Managed *other);
+
private:
friend class MemoryManager;
friend struct Identifiers;
@@ -254,6 +215,29 @@ inline const Object *Value::as() const {
return objectValue();
}
+
+struct InternalClass : Managed
+{
+ V4_MANAGED_ITSELF(InternalClass, Managed)
+ Q_MANAGED_TYPE(InternalClass)
+ V4_INTERNALCLASS(Empty)
+ V4_NEEDS_DESTROY
+
+ Q_REQUIRED_RESULT Heap::InternalClass *changeVTable(const VTable *vt) {
+ return d()->changeVTable(vt);
+ }
+ Q_REQUIRED_RESULT Heap::InternalClass *changePrototype(Heap::Object *proto) {
+ return d()->changePrototype(proto);
+ }
+ Q_REQUIRED_RESULT Heap::InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, uint *index = 0) {
+ return d()->addMember(identifier, data, index);
+ }
+
+ void operator =(Heap::InternalClass *ic) {
+ Value::operator=(ic);
+ }
+};
+
}
diff --git a/src/qml/jsruntime/qv4mapiterator.cpp b/src/qml/jsruntime/qv4mapiterator.cpp
new file mode 100644
index 0000000000..7be7416e4a
--- /dev/null
+++ b/src/qml/jsruntime/qv4mapiterator.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qv4iterator_p.h>
+#include <private/qv4estable_p.h>
+#include <private/qv4mapiterator_p.h>
+#include <private/qv4mapobject_p.h>
+#include <private/qv4symbol_p.h>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(MapIteratorObject);
+
+void MapIteratorPrototype::init(ExecutionEngine *e)
+{
+ defineDefaultProperty(QStringLiteral("next"), method_next, 0);
+
+ Scope scope(e);
+ ScopedString val(scope, e->newString(QLatin1String("Map Iterator")));
+ defineReadonlyConfigurableProperty(e->symbol_toStringTag(), val);
+}
+
+ReturnedValue MapIteratorPrototype::method_next(const FunctionObject *b, const Value *that, const Value *, int)
+{
+ Scope scope(b);
+ const MapIteratorObject *thisObject = that->as<MapIteratorObject>();
+ if (!thisObject)
+ return scope.engine->throwTypeError(QLatin1String("Not a Map Iterator instance"));
+
+ Scoped<MapObject> s(scope, thisObject->d()->iteratedMap);
+ uint index = thisObject->d()->mapNextIndex;
+ IteratorKind itemKind = thisObject->d()->iterationKind;
+
+ if (!s) {
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+ }
+
+ Value *arguments = scope.alloc(2);
+
+ while (index < s->d()->esTable->size()) {
+ s->d()->esTable->iterate(index, &arguments[0], &arguments[1]);
+ thisObject->d()->mapNextIndex = index + 1;
+
+ ScopedValue result(scope);
+
+ if (itemKind == KeyIteratorKind) {
+ result = arguments[0];
+ } else if (itemKind == ValueIteratorKind) {
+ result = arguments[1];
+ } else {
+ Q_ASSERT(itemKind == KeyValueIteratorKind);
+
+ result = scope.engine->newArrayObject();
+
+ Scoped<ArrayObject> resultArray(scope, result);
+ resultArray->arrayReserve(2);
+ resultArray->arrayPut(0, arguments[0]);
+ resultArray->arrayPut(1, arguments[1]);
+ resultArray->setArrayLengthUnchecked(2);
+ }
+
+ return IteratorPrototype::createIterResultObject(scope.engine, result, false);
+ }
+
+ thisObject->d()->iteratedMap.set(scope.engine, nullptr);
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+}
+
+
diff --git a/src/qml/jsruntime/qv4mapiterator_p.h b/src/qml/jsruntime/qv4mapiterator_p.h
new file mode 100644
index 0000000000..836ba14663
--- /dev/null
+++ b/src/qml/jsruntime/qv4mapiterator_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4MAPITERATOR_P_H
+#define QV4MAPITERATOR_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 "qv4object_p.h"
+#include "qv4iterator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Heap {
+
+#define MapIteratorObjectMembers(class, Member) \
+ Member(class, Pointer, Object *, iteratedMap) \
+ Member(class, NoMark, IteratorKind, iterationKind) \
+ Member(class, NoMark, quint32, mapNextIndex)
+
+DECLARE_HEAP_OBJECT(MapIteratorObject, Object) {
+ DECLARE_MARKOBJECTS(MapIteratorObject);
+ void init(Object *obj, QV4::ExecutionEngine *engine)
+ {
+ Object::init();
+ this->iteratedMap.set(engine, obj);
+ this->mapNextIndex = 0;
+ }
+};
+
+}
+
+struct MapIteratorPrototype : Object
+{
+ V4_PROTOTYPE(iteratorPrototype)
+ void init(ExecutionEngine *engine);
+
+ static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct MapIteratorObject : Object
+{
+ V4_OBJECT2(MapIteratorObject, Object)
+ Q_MANAGED_TYPE(MapIteratorObject)
+ V4_PROTOTYPE(mapIteratorPrototype)
+
+ void init(ExecutionEngine *engine);
+};
+
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4MAPITERATOR_P_H
+
+
diff --git a/src/qml/jsruntime/qv4mapobject.cpp b/src/qml/jsruntime/qv4mapobject.cpp
new file mode 100644
index 0000000000..ca9e1723f9
--- /dev/null
+++ b/src/qml/jsruntime/qv4mapobject.cpp
@@ -0,0 +1,279 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4setobject_p.h" // ### temporary
+#include "qv4mapobject_p.h"
+#include "qv4mapiterator_p.h"
+#include "qv4estable_p.h"
+#include "qv4symbol_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(MapCtor);
+DEFINE_OBJECT_VTABLE(MapObject);
+
+void Heap::MapCtor::init(QV4::ExecutionContext *scope)
+{
+ Heap::FunctionObject::init(scope, QStringLiteral("Map"));
+}
+
+ReturnedValue MapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+{
+ Scope scope(f);
+ Scoped<MapObject> a(scope, scope.engine->memoryManager->allocate<MapObject>());
+
+ if (argc > 0) {
+ ScopedValue iterable(scope, argv[0]);
+
+ // ### beware, hack alert!
+ // Object iteration seems broken right now. if we allow any object to
+ // iterate, it endlessly loops in the Map/prototype tests in test262...
+ // disable these for now until Object iteration is fixed, just so we can
+ // test this.
+ Scoped<MapObject> mapObjectCheck(scope, argv[0]);
+ Scoped<SetObject> setObjectCheck(scope, argv[0]);
+
+ if (!iterable->isUndefined() && !iterable->isNull() && (mapObjectCheck || setObjectCheck)) {
+ ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("set")))));
+ if (!adder)
+ return scope.engine->throwTypeError();
+ ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true));
+
+ CHECK_EXCEPTION();
+ if (!iter)
+ return a.asReturnedValue();
+
+ Value *nextValue = scope.alloc(1);
+ ScopedValue done(scope);
+ forever {
+ done = Runtime::method_iteratorNext(scope.engine, iter, nextValue);
+ CHECK_EXCEPTION();
+ if (done->toBoolean())
+ return a.asReturnedValue();
+
+ adder->call(a, nextValue, 1);
+ if (scope.engine->hasException) {
+ ScopedValue falsey(scope, Encode(false));
+ return Runtime::method_iteratorClose(scope.engine, iter, falsey);
+ }
+ }
+ }
+ }
+ return a.asReturnedValue();
+}
+
+ReturnedValue MapCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
+{
+ Scope scope(f);
+ return scope.engine->throwTypeError(QString::fromLatin1("Map requires new"));
+}
+
+void MapPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Scope scope(engine);
+ ScopedObject o(scope);
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->addSymbolSpecies();
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
+
+ defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
+ defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
+ defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
+ defineDefaultProperty(QStringLiteral("get"), method_get, 1);
+ defineDefaultProperty(QStringLiteral("has"), method_has, 1);
+ defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
+ defineDefaultProperty(QStringLiteral("set"), method_set, 0);
+ defineAccessorProperty(QStringLiteral("size"), method_get_size, nullptr);
+ defineDefaultProperty(QStringLiteral("values"), method_values, 0);
+
+ // Per the spec, the value for entries/@@iterator is the same
+ ScopedString valString(scope, scope.engine->newIdentifier(QStringLiteral("entries")));
+ ScopedFunctionObject entriesFn(scope, FunctionObject::createBuiltinFunction(engine, valString, MapPrototype::method_entries, 0));
+ defineDefaultProperty(QStringLiteral("entries"), entriesFn);
+ defineDefaultProperty(engine->symbol_iterator(), entriesFn);
+
+ ScopedString val(scope, engine->newString(QLatin1String("Map")));
+ defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
+}
+
+void Heap::MapObject::init()
+{
+ Object::init();
+ esTable = new ESTable();
+}
+
+void Heap::MapObject::destroy()
+{
+ delete esTable;
+ esTable = 0;
+}
+
+void Heap::MapObject::markObjects(Heap::Base *that, MarkStack *markStack)
+{
+ MapObject *m = static_cast<MapObject *>(that);
+ m->esTable->markObjects(markStack);
+ Object::markObjects(that, markStack);
+}
+
+ReturnedValue MapPrototype::method_clear(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ that->d()->esTable->clear();
+ return Encode::undefined();
+}
+
+ReturnedValue MapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return Encode(that->d()->esTable->remove(argv[0]));
+}
+
+ReturnedValue MapPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
+ ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue MapPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ ScopedFunctionObject callbackfn(scope, argv[0]);
+ if (!callbackfn)
+ return scope.engine->throwTypeError();
+
+ ScopedValue thisArg(scope, Primitive::undefinedValue());
+ if (argc > 1)
+ thisArg = ScopedValue(scope, argv[1]);
+
+ Value *arguments = scope.alloc(3);
+ for (uint i = 0; i < that->d()->esTable->size(); ++i) {
+ that->d()->esTable->iterate(i, &arguments[0], &arguments[1]); // fill in key (0), value (1)
+
+ arguments[2] = that;
+ callbackfn->call(thisArg, arguments, 3);
+ CHECK_EXCEPTION();
+ }
+ return Encode::undefined();
+}
+
+ReturnedValue MapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return that->d()->esTable->get(argv[0]);
+}
+
+ReturnedValue MapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return Encode(that->d()->esTable->has(argv[0]));
+}
+
+ReturnedValue MapPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
+ ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue MapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ that->d()->esTable->set(argv[0], argv[1]);
+ return that.asReturnedValue();
+}
+
+ReturnedValue MapPrototype::method_get_size(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return Encode(that->d()->esTable->size());
+}
+
+ReturnedValue MapPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<MapObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
+ ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
+
diff --git a/src/qml/jsruntime/qv4mapobject_p.h b/src/qml/jsruntime/qv4mapobject_p.h
new file mode 100644
index 0000000000..6793612bcb
--- /dev/null
+++ b/src/qml/jsruntime/qv4mapobject_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4MAPOBJECT_P_H
+#define QV4MAPOBJECT_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 "qv4object_p.h"
+#include "qv4objectproto_p.h"
+#include "qv4functionobject_p.h"
+#include "qv4string_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+class ESTable;
+
+namespace Heap {
+
+struct MapCtor : FunctionObject {
+ void init(QV4::ExecutionContext *scope);
+};
+
+struct MapObject : Object {
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
+ void init();
+ void destroy();
+ ESTable *esTable;
+};
+
+}
+
+struct MapCtor: FunctionObject
+{
+ V4_OBJECT2(MapCtor, FunctionObject)
+
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct MapObject : Object
+{
+ V4_OBJECT2(MapObject, Object)
+ V4_PROTOTYPE(mapPrototype)
+ V4_NEEDS_DESTROY
+};
+
+struct MapPrototype : Object
+{
+ void init(ExecutionEngine *engine, Object *ctor);
+
+ static ReturnedValue method_clear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_delete(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_forEach(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_get(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_has(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_set(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_get_size(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+
+} // namespace QV4
+
+
+QT_END_NAMESPACE
+
+#endif // QV4MAPOBJECT_P_H
+
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 0c18d908de..e176235786 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -39,6 +39,7 @@
#include "qv4mathobject_p.h"
#include "qv4objectproto_p.h"
+#include "qv4symbol_p.h"
#include <QtCore/qdatetime.h>
#include <QtCore/qmath.h>
@@ -70,14 +71,27 @@ void Heap::MathObject::init()
m->defineDefaultProperty(QStringLiteral("abs"), QV4::MathObject::method_abs, 1);
m->defineDefaultProperty(QStringLiteral("acos"), QV4::MathObject::method_acos, 1);
- m->defineDefaultProperty(QStringLiteral("asin"), QV4::MathObject::method_asin, 0);
+ m->defineDefaultProperty(QStringLiteral("acosh"), QV4::MathObject::method_acosh, 1);
+ m->defineDefaultProperty(QStringLiteral("asin"), QV4::MathObject::method_asin, 1);
+ m->defineDefaultProperty(QStringLiteral("asinh"), QV4::MathObject::method_asinh, 1);
m->defineDefaultProperty(QStringLiteral("atan"), QV4::MathObject::method_atan, 1);
+ m->defineDefaultProperty(QStringLiteral("atanh"), QV4::MathObject::method_atanh, 1);
m->defineDefaultProperty(QStringLiteral("atan2"), QV4::MathObject::method_atan2, 2);
+ m->defineDefaultProperty(QStringLiteral("cbrt"), QV4::MathObject::method_cbrt, 1);
m->defineDefaultProperty(QStringLiteral("ceil"), QV4::MathObject::method_ceil, 1);
+ m->defineDefaultProperty(QStringLiteral("clz32"), QV4::MathObject::method_clz32, 1);
m->defineDefaultProperty(QStringLiteral("cos"), QV4::MathObject::method_cos, 1);
+ m->defineDefaultProperty(QStringLiteral("cosh"), QV4::MathObject::method_cosh, 1);
m->defineDefaultProperty(QStringLiteral("exp"), QV4::MathObject::method_exp, 1);
+ m->defineDefaultProperty(QStringLiteral("expm1"), QV4::MathObject::method_expm1, 1);
m->defineDefaultProperty(QStringLiteral("floor"), QV4::MathObject::method_floor, 1);
+ m->defineDefaultProperty(QStringLiteral("fround"), QV4::MathObject::method_fround, 1);
+ m->defineDefaultProperty(QStringLiteral("hypot"), QV4::MathObject::method_hypot, 2);
+ m->defineDefaultProperty(QStringLiteral("imul"), QV4::MathObject::method_imul, 2);
m->defineDefaultProperty(QStringLiteral("log"), QV4::MathObject::method_log, 1);
+ m->defineDefaultProperty(QStringLiteral("log10"), QV4::MathObject::method_log10, 1);
+ m->defineDefaultProperty(QStringLiteral("log1p"), QV4::MathObject::method_log1p, 1);
+ m->defineDefaultProperty(QStringLiteral("log2"), QV4::MathObject::method_log2, 1);
m->defineDefaultProperty(QStringLiteral("max"), QV4::MathObject::method_max, 2);
m->defineDefaultProperty(QStringLiteral("min"), QV4::MathObject::method_min, 2);
m->defineDefaultProperty(QStringLiteral("pow"), QV4::MathObject::method_pow, 2);
@@ -85,8 +99,14 @@ void Heap::MathObject::init()
m->defineDefaultProperty(QStringLiteral("round"), QV4::MathObject::method_round, 1);
m->defineDefaultProperty(QStringLiteral("sign"), QV4::MathObject::method_sign, 1);
m->defineDefaultProperty(QStringLiteral("sin"), QV4::MathObject::method_sin, 1);
+ m->defineDefaultProperty(QStringLiteral("sinh"), QV4::MathObject::method_sinh, 1);
m->defineDefaultProperty(QStringLiteral("sqrt"), QV4::MathObject::method_sqrt, 1);
m->defineDefaultProperty(QStringLiteral("tan"), QV4::MathObject::method_tan, 1);
+ m->defineDefaultProperty(QStringLiteral("tanh"), QV4::MathObject::method_tanh, 1);
+ m->defineDefaultProperty(QStringLiteral("trunc"), QV4::MathObject::method_trunc, 1);
+
+ ScopedString name(scope, scope.engine->newString(QStringLiteral("Math")));
+ m->defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name);
}
static Q_ALWAYS_INLINE double copySign(double x, double y)
@@ -120,6 +140,19 @@ ReturnedValue MathObject::method_acos(const FunctionObject *, const Value *, con
RETURN_RESULT(Encode(std::acos(v)));
}
+ReturnedValue MathObject::method_acosh(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : 2;
+ if (v < 1)
+ RETURN_RESULT(Encode(qt_qnan()));
+
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ RETURN_RESULT(Encode(std::log(v +std::sqrt(v + 1) * std::sqrt(v - 1))));
+#else
+ RETURN_RESULT(Encode(std::acosh(v)));
+#endif
+}
+
ReturnedValue MathObject::method_asin(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : 2;
@@ -129,6 +162,19 @@ ReturnedValue MathObject::method_asin(const FunctionObject *, const Value *, con
RETURN_RESULT(Encode(std::asin(v)));
}
+ReturnedValue MathObject::method_asinh(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : 2;
+ if (v == 0.0)
+ RETURN_RESULT(Encode(v));
+
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ RETURN_RESULT(Encode(std::log(v +std::sqrt(1 + v * v))));
+#else
+ RETURN_RESULT(Encode(std::asinh(v)));
+#endif
+}
+
ReturnedValue MathObject::method_atan(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
@@ -138,6 +184,25 @@ ReturnedValue MathObject::method_atan(const FunctionObject *, const Value *, con
RETURN_RESULT(Encode(std::atan(v)));
}
+ReturnedValue MathObject::method_atanh(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (v == 0.0)
+ RETURN_RESULT(Encode(v));
+
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ if (-1 < v && v < 1)
+ RETURN_RESULT(Encode(0.5 * (std::log(v + 1) - std::log(v - 1))));
+
+ if (v > 1 || v < -1)
+ RETURN_RESULT(Encode(qt_qnan()));
+
+ RETURN_RESULT(Encode(copySign(qt_inf(), v)));
+#else
+ RETURN_RESULT(Encode(std::atanh(v)));
+#endif
+}
+
ReturnedValue MathObject::method_atan2(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v1 = argc ? argv[0].toNumber() : qt_qnan();
@@ -156,6 +221,16 @@ ReturnedValue MathObject::method_atan2(const FunctionObject *, const Value *, co
RETURN_RESULT(Encode(std::atan2(v1, v2)));
}
+ReturnedValue MathObject::method_cbrt(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ RETURN_RESULT(Encode(copySign(std::exp(std::log(std::abs(v)) / 3), v)));
+#else
+ RETURN_RESULT(Encode(std::cbrt(v))); // cube root
+#endif
+}
+
ReturnedValue MathObject::method_ceil(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
@@ -165,12 +240,24 @@ ReturnedValue MathObject::method_ceil(const FunctionObject *, const Value *, con
RETURN_RESULT(Encode(std::ceil(v)));
}
+ReturnedValue MathObject::method_clz32(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ quint32 v = argc ? argv[0].toUInt32() : 0;
+ RETURN_RESULT(Encode(qint32(qCountLeadingZeroBits(v))));
+}
+
ReturnedValue MathObject::method_cos(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
RETURN_RESULT(Encode(std::cos(v)));
}
+ReturnedValue MathObject::method_cosh(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ RETURN_RESULT(Encode(std::cosh(v)));
+}
+
ReturnedValue MathObject::method_exp(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
@@ -184,6 +271,25 @@ ReturnedValue MathObject::method_exp(const FunctionObject *, const Value *, cons
}
}
+ReturnedValue MathObject::method_expm1(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (std::isnan(v) || qIsNull(v)) {
+ RETURN_RESULT(Encode(v));
+ } else if (qt_is_inf(v)) {
+ if (copySign(1.0, v) == -1.0)
+ RETURN_RESULT(Encode(-1.0));
+ else
+ RETURN_RESULT(Encode(qt_inf()));
+ } else {
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ RETURN_RESULT(Encode(std::exp(v) - 1));
+#else
+ RETURN_RESULT(Encode(std::expm1(v)));
+#endif
+ }
+}
+
ReturnedValue MathObject::method_floor(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
@@ -192,6 +298,53 @@ ReturnedValue MathObject::method_floor(const FunctionObject *, const Value *, co
RETURN_RESULT(result);
}
+ReturnedValue MathObject::method_fround(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (std::isnan(v) || qt_is_inf(v) || qIsNull(v))
+ RETURN_RESULT(Encode(v));
+ else // convert to 32-bit float using roundTiesToEven, then convert back to 64-bit double
+ RETURN_RESULT(Encode(double(float(v))));
+}
+
+ReturnedValue MathObject::method_hypot(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ // ES6 Math.hypot(v1, ..., vn) -> sqrt(sum(vi**2)) but "should take care to
+ // avoid the loss of precision from overflows and underflows" (as std::hypot does).
+ double v = argc ? argv[0].toNumber() : 0;
+ // Spec mandates +0 on no args; and says nothing about what to do if toNumber() signals ...
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ bool big = qt_is_inf(v), bad = std::isnan(v);
+ v *= v;
+ for (int i = 1; !big && i < argc; i++) {
+ double u = argv[i].toNumber();
+ if (qt_is_inf(u))
+ big = true;
+ if (std::isnan(u))
+ bad = true;
+ v += u * u;
+ }
+ if (big)
+ RETURN_RESULT(Encode(qt_inf()));
+ if (bad)
+ RETURN_RESULT(Encode(qt_qnan()));
+ // Should actually check for {und,ov}erflow, but too fiddly !
+ RETURN_RESULT(Primitive::fromDouble(sqrt(v)));
+#else
+ for (int i = 1; i < argc; i++)
+ v = std::hypot(v, argv[i].toNumber());
+#endif
+ RETURN_RESULT(Primitive::fromDouble(v));
+}
+
+ReturnedValue MathObject::method_imul(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ quint32 a = argc ? argv[0].toUInt32() : 0;
+ quint32 b = argc > 0 ? argv[1].toUInt32() : 0;
+ qint32 product = a * b;
+ RETURN_RESULT(Encode(product));
+}
+
ReturnedValue MathObject::method_log(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
@@ -201,6 +354,43 @@ ReturnedValue MathObject::method_log(const FunctionObject *, const Value *, cons
RETURN_RESULT(Encode(std::log(v)));
}
+ReturnedValue MathObject::method_log10(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (v < 0)
+ RETURN_RESULT(Encode(qt_qnan()));
+ else
+ RETURN_RESULT(Encode(std::log10(v)));
+}
+
+ReturnedValue MathObject::method_log1p(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+#if !defined(__ANDROID__)
+ using std::log1p;
+#endif
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (v < -1)
+ RETURN_RESULT(Encode(qt_qnan()));
+ else
+ RETURN_RESULT(Encode(log1p(v)));
+}
+
+ReturnedValue MathObject::method_log2(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (v < 0) {
+ RETURN_RESULT(Encode(qt_qnan()));
+ } else {
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ // Android ndk r10e doesn't have std::log2, so fall back.
+ const double ln2 = std::log(2.0);
+ RETURN_RESULT(Encode(std::log(v) / ln2));
+#else
+ RETURN_RESULT(Encode(std::log2(v)));
+#endif
+ }
+}
+
ReturnedValue MathObject::method_max(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double mx = -qt_inf();
@@ -209,7 +399,7 @@ ReturnedValue MathObject::method_max(const FunctionObject *, const Value *, cons
if (x > mx || std::isnan(x))
mx = x;
}
- RETURN_RESULT(Encode(mx));
+ RETURN_RESULT(Encode::smallestNumber(mx));
}
ReturnedValue MathObject::method_min(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -222,7 +412,7 @@ ReturnedValue MathObject::method_min(const FunctionObject *, const Value *, cons
mx = x;
}
}
- RETURN_RESULT(Encode(mx));
+ RETURN_RESULT(Encode::smallestNumber(mx));
}
ReturnedValue MathObject::method_pow(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -283,8 +473,11 @@ ReturnedValue MathObject::method_random(const FunctionObject *, const Value *, c
ReturnedValue MathObject::method_round(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
- v = copySign(std::floor(v + 0.5), v);
- RETURN_RESULT(Encode(v));
+ if (std::isnan(v) || qt_is_inf(v) || qIsNull(v))
+ RETURN_RESULT(Encode(v));
+
+ v = copySign(std::floor(v + 0.5), v);
+ RETURN_RESULT(Encode(v));
}
ReturnedValue MathObject::method_sign(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -303,7 +496,19 @@ ReturnedValue MathObject::method_sign(const FunctionObject *, const Value *, con
ReturnedValue MathObject::method_sin(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double v = argc ? argv[0].toNumber() : qt_qnan();
- RETURN_RESULT(Encode(std::sin(v)));
+ if (v == 0.0)
+ RETURN_RESULT(Encode(v));
+ else
+ RETURN_RESULT(Encode(std::sin(v)));
+}
+
+ReturnedValue MathObject::method_sinh(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (v == 0.0)
+ RETURN_RESULT(Encode(v));
+ else
+ RETURN_RESULT(Encode(std::sinh(v)));
}
ReturnedValue MathObject::method_sqrt(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -321,3 +526,25 @@ ReturnedValue MathObject::method_tan(const FunctionObject *, const Value *, cons
RETURN_RESULT(Encode(std::tan(v)));
}
+ReturnedValue MathObject::method_tanh(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+ if (v == 0.0)
+ RETURN_RESULT(Encode(v));
+ else
+ RETURN_RESULT(Encode(std::tanh(v)));
+}
+
+ReturnedValue MathObject::method_trunc(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ double v = argc ? argv[0].toNumber() : qt_qnan();
+#ifdef Q_OS_ANDROID // incomplete std :-(
+ if (std::isnan(v) || qt_is_inf(v) || qIsNull(v))
+ RETURN_RESULT(Encode(v));
+ // Nearest integer not greater in magnitude:
+ quint64 whole = std::abs(v);
+ RETURN_RESULT(Encode(copySign(whole, v)));
+#else
+ RETURN_RESULT(Encode(std::trunc(v)));
+#endif
+}
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 0bf5da9404..2658e25438 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -71,14 +71,27 @@ struct MathObject: Object
static ReturnedValue method_abs(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_acos(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_acosh(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_asin(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_asinh(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_atan(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_atanh(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_atan2(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_cbrt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_ceil(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_clz32(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_cos(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_cosh(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_exp(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_expm1(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_floor(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_fround(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_hypot(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_imul(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_log(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_log10(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_log1p(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_log2(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_max(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_min(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_pow(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
@@ -86,8 +99,11 @@ struct MathObject: Object
static ReturnedValue method_round(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_sign(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_sin(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_sinh(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_sqrt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_tan(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_tanh(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_trunc(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index ac9671254d..186083b83a 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -74,18 +74,6 @@ struct MemberData : Managed
V4_MANAGED(MemberData, Managed)
V4_INTERNALCLASS(MemberData)
- struct Index {
- Heap::Base *base;
- Value *slot;
-
- void set(EngineBase *e, Value newVal) {
- WriteBarrier::write(e, base, slot->data_ptr(), newVal.asReturnedValue());
- }
- const Value *operator->() const { return slot; }
- const Value &operator*() const { return *slot; }
- bool isNull() const { return !slot; }
- };
-
const Value &operator[] (uint idx) const { return d()->values[idx]; }
const Value *data() const { return d()->values.data(); }
void set(EngineBase *e, uint index, Value v) { d()->values.set(e, index, v); }
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index f58ff45801..d103f65d47 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -78,13 +78,13 @@ void Heap::NumberCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Number"));
}
-ReturnedValue NumberCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue NumberCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
double dbl = argc ? argv[0].toNumber() : 0.;
return Encode(f->engine()->newNumberObject(dbl));
}
-ReturnedValue NumberCtor::call(const FunctionObject *, const Value *, const Value *argv, int argc)
+ReturnedValue NumberCtor::virtualCall(const FunctionObject *, const Value *, const Value *argv, int argc)
{
double dbl = argc ? argv[0].toNumber() : 0.;
return Encode(dbl);
@@ -95,7 +95,7 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qt_qnan()));
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index cfdcf9bc1d..576817cf36 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -79,8 +79,8 @@ struct NumberCtor: FunctionObject
{
V4_OBJECT2(NumberCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
struct NumberPrototype: NumberObject
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 0c6cde84ad..e4d670d4f3 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -50,6 +50,7 @@
#include "qv4string_p.h"
#include "qv4identifiertable_p.h"
#include "qv4jscall_p.h"
+#include "qv4symbol_p.h"
#include <stdint.h>
@@ -57,9 +58,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(Object);
-void Object::setInternalClass(InternalClass *ic)
+void Object::setInternalClass(Heap::InternalClass *ic)
{
- d()->internalClass = ic;
+ d()->internalClass.set(engine(), ic);
if (ic->isUsedAsProto)
ic->updateProtoUsage(d());
Q_ASSERT(ic && ic->vtable);
@@ -89,20 +90,7 @@ void Object::setProperty(uint index, const Property *p)
void Heap::Object::setUsedAsProto()
{
- internalClass = internalClass->asProtoClass();
-}
-
-bool Object::setPrototype(Object *proto)
-{
- Heap::Object *p = proto ? proto->d() : nullptr;
- Heap::Object *pp = p;
- while (pp) {
- if (pp == d())
- return false;
- pp = pp->prototype();
- }
- setInternalClass(internalClass()->changePrototype(p));
- return true;
+ internalClass.set(internalClass->engine, internalClass->asProtoClass());
}
ReturnedValue Object::getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs)
@@ -121,7 +109,7 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property
bool Object::putValue(uint memberIndex, const Value &value)
{
- QV4::InternalClass *ic = internalClass();
+ Heap::InternalClass *ic = internalClass();
if (ic->engine->hasException)
return false;
@@ -148,37 +136,34 @@ bool Object::putValue(uint memberIndex, const Value &value)
return true;
}
-void Object::defineDefaultProperty(const QString &name, const Value &value)
+void Object::defineDefaultProperty(const QString &name, const Value &value, PropertyAttributes attributes)
{
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- defineDefaultProperty(s, value);
+ defineDefaultProperty(s, value, attributes);
}
-void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
+void Object::defineDefaultProperty(const QString &name, VTable::Call code,
+ int argumentCount, PropertyAttributes attributes)
{
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, s, code));
- function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
- defineDefaultProperty(s, function);
+ ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(e, s, code, argumentCount));
+ defineDefaultProperty(s, function, attributes);
}
-void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
+void Object::defineDefaultProperty(StringOrSymbol *nameOrSymbol, VTable::Call code,
+ int argumentCount, PropertyAttributes attributes)
{
ExecutionEngine *e = engine();
Scope scope(e);
- ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, name, code));
- function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
- defineDefaultProperty(name, function);
+ ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(e, nameOrSymbol, code, argumentCount));
+ defineDefaultProperty(nameOrSymbol, function, attributes);
}
-void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
- ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int))
+void Object::defineAccessorProperty(const QString &name, VTable::Call getter, VTable::Call setter)
{
ExecutionEngine *e = engine();
Scope scope(e);
@@ -186,16 +171,27 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)
defineAccessorProperty(s, getter, setter);
}
-void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
- ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int))
+void Object::defineAccessorProperty(StringOrSymbol *name, VTable::Call getter, VTable::Call setter)
{
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
- ExecutionContext *global = v4->rootContext();
- p->setGetter(ScopedFunctionObject(scope, (getter ? FunctionObject::createBuiltinFunction(global, name, getter) : nullptr)));
- p->setSetter(ScopedFunctionObject(scope, (setter ? FunctionObject::createBuiltinFunction(global, name, setter) : nullptr)));
- insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ QString n = name->toQString();
+ if (n.at(0) == QLatin1Char('@'))
+ n = QChar::fromLatin1('[') + n.midRef(1) + QChar::fromLatin1(']');
+ if (getter) {
+ ScopedString getName(scope, v4->newString(QString::fromLatin1("get ") + n));
+ p->setGetter(ScopedFunctionObject(scope, FunctionObject::createBuiltinFunction(v4, getName, getter, 0)));
+ } else {
+ p->setGetter(nullptr);
+ }
+ if (setter) {
+ ScopedString setName(scope, v4->newString(QString::fromLatin1("set ") + n));
+ p->setSetter(ScopedFunctionObject(scope, FunctionObject::createBuiltinFunction(v4, setName, setter, 0)));
+ } else {
+ p->setSetter(nullptr);
+ }
+ insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable);
}
@@ -221,13 +217,23 @@ void Object::defineReadonlyConfigurableProperty(const QString &name, const Value
defineReadonlyConfigurableProperty(s, value);
}
-void Object::defineReadonlyConfigurableProperty(String *name, const Value &value)
+void Object::defineReadonlyConfigurableProperty(StringOrSymbol *name, const Value &value)
{
insertMember(name, value, Attr_ReadOnly_ButConfigurable);
}
+void Object::addSymbolSpecies()
+{
+ Scope scope(engine());
+ ScopedProperty p(scope);
+ p->setGetter(scope.engine->getSymbolSpecies());
+ p->setSetter(nullptr);
+ insertMember(scope.engine->symbol_species(), p, QV4::Attr_Accessor|QV4::Attr_NotWritable|QV4::Attr_NotEnumerable);
+}
+
void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
{
+ Base::markObjects(b, stack);
Object *o = static_cast<Object *>(b);
if (o->memberData)
o->memberData->mark(stack);
@@ -242,10 +248,11 @@ void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
}
}
-void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes)
+void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes)
{
uint idx;
- InternalClass::addMember(this, s, attributes, &idx);
+ PropertyKey key = s->toPropertyKey();
+ Heap::InternalClass::addMember(this, key, attributes, &idx);
if (attributes.isAccessor()) {
setProperty(idx + GetterOffset, p->value);
@@ -255,230 +262,81 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
}
}
-// Section 8.12.1
-void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p)
+void Object::setPrototypeUnchecked(const Object *p)
{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return getOwnProperty(idx, attrs, p);
-
- name->makeIdentifier();
- Identifier *id = name->identifier();
-
- uint member = internalClass()->find(id);
- if (member < UINT_MAX) {
- *attrs = internalClass()->propertyData[member];
- if (p) {
- p->value = *propertyData(member);
- if (attrs->isAccessor())
- p->set = *propertyData(member + SetterOffset);
- }
- return;
- }
-
- if (attrs)
- *attrs = Attr_Invalid;
- return;
-}
-
-void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
-{
- if (arrayData()) {
- if (arrayData()->getProperty(index, p, attrs))
- return;
- }
- if (isStringObject()) {
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- if (p)
- p->value = static_cast<StringObject *>(this)->getIndex(index);
- return;
- }
-
- if (attrs)
- *attrs = Attr_Invalid;
- return;
+ setInternalClass(internalClass()->changePrototype(p ? p->d() : nullptr));
}
// Section 8.12.2
-MemberData::Index Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
-{
- Q_ASSERT(name->asArrayIndex() == UINT_MAX);
-
- name->makeIdentifier();
- Identifier *id = name->identifier();
-
- Heap::Object *o = d();
- while (o) {
- uint idx = o->internalClass->find(id);
- if (idx < UINT_MAX) {
- *attrs = o->internalClass->propertyData[idx];
- return o->writablePropertyData(attrs->isAccessor() ? idx + SetterOffset : idx );
- }
-
- o = o->prototype();
- }
- *attrs = Attr_Invalid;
- return { nullptr, nullptr };
-}
-
-ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
+PropertyIndex Object::getValueOrSetter(PropertyKey id, PropertyAttributes *attrs)
{
- Heap::Object *o = d();
- while (o) {
- if (o->arrayData) {
- uint idx = o->arrayData->mappedIndex(index);
- if (idx != UINT_MAX) {
- *attrs = o->arrayData->attributes(index);
- return { o->arrayData , attrs->isAccessor() ? idx + SetterOffset : idx };
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ Heap::Object *o = d();
+ while (o) {
+ if (o->arrayData) {
+ uint idx = o->arrayData->mappedIndex(index);
+ if (idx != UINT_MAX) {
+ *attrs = o->arrayData->attributes(index);
+ return { o->arrayData , o->arrayData->values.values + (attrs->isAccessor() ? idx + SetterOffset : idx) };
+ }
}
+ if (o->vtable()->type == Type_StringObject) {
+ if (index < static_cast<const Heap::StringObject *>(o)->length()) {
+ // this is an evil hack, but it works, as the method is only ever called from put,
+ // where we don't use the returned pointer there for non writable attributes
+ *attrs = (Attr_NotWritable|Attr_NotConfigurable);
+ return { reinterpret_cast<Heap::ArrayData *>(0x1), nullptr };
+ }
+ }
+ o = o->prototype();
}
- if (o->vtable()->type == Type_StringObject) {
- if (index < static_cast<const Heap::StringObject *>(o)->length()) {
- // this is an evil hack, but it works, as the method is only ever called from putIndexed,
- // where we don't use the returned pointer there for non writable attributes
- *attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return { reinterpret_cast<Heap::ArrayData *>(0x1), 0 };
+ } else {
+ Heap::Object *o = d();
+ while (o) {
+ uint idx = o->internalClass->find(id);
+ if (idx < UINT_MAX) {
+ *attrs = o->internalClass->propertyData[idx];
+ return o->writablePropertyData(attrs->isAccessor() ? idx + SetterOffset : idx );
}
+
+ o = o->prototype();
}
- o = o->prototype();
}
*attrs = Attr_Invalid;
- return { nullptr, 0 };
-}
-
-bool Object::hasProperty(String *name) const
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return hasProperty(idx);
-
- Scope scope(engine());
- ScopedObject o(scope, d());
- while (o) {
- if (o->hasOwnProperty(name))
- return true;
-
- o = o->prototype();
- }
-
- return false;
-}
-
-bool Object::hasProperty(uint index) const
-{
- Scope scope(engine());
- ScopedObject o(scope, d());
- while (o) {
- if (o->hasOwnProperty(index))
- return true;
-
- o = o->prototype();
- }
-
- return false;
-}
-
-bool Object::hasOwnProperty(String *name) const
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return hasOwnProperty(idx);
-
- name->makeIdentifier();
- Identifier *id = name->identifier();
-
- if (internalClass()->find(id) < UINT_MAX)
- return true;
- if (!query(name).isEmpty())
- return true;
- return false;
-}
-
-bool Object::hasOwnProperty(uint index) const
-{
- if (arrayData() && !arrayData()->isEmpty(index))
- return true;
-
- if (isStringObject()) {
- if (index < static_cast<const StringObject *>(this)->length())
- return true;
- }
- if (!queryIndexed(index).isEmpty())
- return true;
- return false;
+ return { nullptr, nullptr };
}
-ReturnedValue Object::callAsConstructor(const FunctionObject *f, const Value *, int)
+ReturnedValue Object::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
{
return f->engine()->throwTypeError();
}
-ReturnedValue Object::call(const FunctionObject *f, const Value *, const Value *, int)
+ReturnedValue Object::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
{
return f->engine()->throwTypeError();
}
-ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue Object::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
- return static_cast<const Object *>(m)->internalGet(name, hasProperty);
+ if (id.isArrayIndex())
+ return static_cast<const Object *>(m)->internalGetIndexed(id.asArrayIndex(), receiver, hasProperty);
+ Scope scope(m);
+ Scoped<StringOrSymbol> name(scope, id.asStringOrSymbol());
+ return static_cast<const Object *>(m)->internalGet(name, receiver, hasProperty);
}
-ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty)
+bool Object::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
+ return static_cast<Object *>(m)->internalPut(id, value, receiver);
}
-bool Object::put(Managed *m, String *name, const Value &value)
+bool Object::virtualDeleteProperty(Managed *m, PropertyKey id)
{
- return static_cast<Object *>(m)->internalPut(name, value);
+ return static_cast<Object *>(m)->internalDeleteProperty(id);
}
-bool Object::putIndexed(Managed *m, uint index, const Value &value)
-{
- return static_cast<Object *>(m)->internalPutIndexed(index, value);
-}
-
-PropertyAttributes Object::query(const Managed *m, String *name)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return queryIndexed(m, idx);
-
- name->makeIdentifier();
- Identifier *id = name->identifier();
-
- const Object *o = static_cast<const Object *>(m);
- idx = o->internalClass()->find(id);
- if (idx < UINT_MAX)
- return o->internalClass()->propertyData[idx];
-
- return Attr_Invalid;
-}
-
-PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
-{
- const Object *o = static_cast<const Object *>(m);
- if (o->arrayData() && !o->arrayData()->isEmpty(index))
- return o->arrayData()->attributes(index);
-
- if (o->isStringObject()) {
- if (index < static_cast<const StringObject *>(o)->length())
- return (Attr_NotWritable|Attr_NotConfigurable);
- }
- return Attr_Invalid;
-}
-
-bool Object::deleteProperty(Managed *m, String *name)
-{
- return static_cast<Object *>(m)->internalDeleteProperty(name);
-}
-
-bool Object::deleteIndexedProperty(Managed *m, uint index)
-{
- return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
-}
-
-void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
name->setM(nullptr);
@@ -525,9 +383,10 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
}
while (it->memberIndex < o->internalClass()->size) {
- Identifier *n = o->internalClass()->nameMap.at(it->memberIndex);
- if (!n) {
+ PropertyKey n = o->internalClass()->nameMap.at(it->memberIndex);
+ if (!n.isStringOrSymbol() || !n.asStringOrSymbol()->internalClass->vtable->isString) {
// accessor properties have a dummy entry with n == 0
+ // symbol entries are supposed to be skipped
++it->memberIndex;
continue;
}
@@ -536,7 +395,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- name->setM(o->engine()->identifierTable->stringFromIdentifier(n));
+ name->setM(n.asStringOrSymbol());
*attrs = a;
pd->value = *o->propertyData(idx);
if (a.isAccessor())
@@ -549,14 +408,11 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
}
// Section 8.12.3
-ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
+ReturnedValue Object::internalGet(StringOrSymbol *name, const Value *receiver, bool *hasProperty) const
{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return getIndexed(idx, hasProperty);
+ PropertyKey id = name->toPropertyKey();
- name->makeIdentifier();
- Identifier *id = name->identifier();
+ Q_ASSERT(!id.isArrayIndex());
Heap::Object *o = d();
while (o) {
@@ -564,7 +420,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
if (idx < UINT_MAX) {
if (hasProperty)
*hasProperty = true;
- return getValue(*o->propertyData(idx), o->internalClass->propertyData.at(idx));
+ return Object::getValue(*receiver, *o->propertyData(idx), o->internalClass->propertyData.at(idx));
}
o = o->prototype();
@@ -575,7 +431,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
return Encode::undefined();
}
-ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
+ReturnedValue Object::internalGetIndexed(uint index, const Value *receiver, bool *hasProperty) const
{
PropertyAttributes attrs;
Scope scope(engine());
@@ -596,13 +452,13 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
return str.asReturnedValue();
}
}
- o = o->prototype();
+ o = o->getPrototypeOf();
}
if (exists) {
if (hasProperty)
*hasProperty = true;
- return getValue(pd->value, attrs);
+ return Object::getValue(*receiver, pd->value, attrs);
}
if (hasProperty)
@@ -612,36 +468,44 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
// Section 8.12.5
-bool Object::internalPut(String *name, const Value &value)
+bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
{
ExecutionEngine *engine = this->engine();
if (engine->hasException)
return false;
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return putIndexed(idx, value);
-
- name->makeIdentifier();
- Identifier *id = name->identifier();
+ uint index = id.asArrayIndex();
+ Scope scope(engine);
- MemberData::Index memberIndex{nullptr, nullptr};
- uint member = internalClass()->find(id);
PropertyAttributes attrs;
- if (member < UINT_MAX) {
- attrs = internalClass()->propertyData[member];
- memberIndex = d()->writablePropertyData(attrs.isAccessor() ? member + SetterOffset : member);
+ PropertyIndex propertyIndex{nullptr, nullptr};
+
+ if (index != UINT_MAX) {
+ if (arrayData())
+ propertyIndex = arrayData()->getValueOrSetter(index, &attrs);
+
+ if (propertyIndex.isNull() && isStringObject()) {
+ if (index < static_cast<StringObject *>(this)->length())
+ // not writable
+ return false;
+ }
+ } else {
+ uint member = internalClass()->find(id);
+ if (member < UINT_MAX) {
+ attrs = internalClass()->propertyData[member];
+ propertyIndex = d()->writablePropertyData(attrs.isAccessor() ? member + SetterOffset : member);
+ }
}
// clause 1
- if (!memberIndex.isNull()) {
+ if (!propertyIndex.isNull()) {
if (attrs.isAccessor()) {
- if (memberIndex->as<FunctionObject>())
+ if (propertyIndex->as<FunctionObject>())
goto cont;
return false;
} else if (!attrs.isWritable())
return false;
- else if (isArrayObject() && name->equals(engine->id_length())) {
+ else if (isArrayObject() && id == engine->id_length()->propertyKey()) {
bool ok;
uint l = value.asArrayLength(&ok);
if (!ok) {
@@ -652,19 +516,18 @@ bool Object::internalPut(String *name, const Value &value)
if (!ok)
return false;
} else {
- memberIndex.set(engine, value);
+ propertyIndex.set(engine, value);
}
return true;
- } else if (!prototype()) {
+ } else if (!getPrototypeOf()) {
if (!isExtensible())
return false;
} else {
// clause 4
- Scope scope(engine);
- memberIndex = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs);
- if (!memberIndex.isNull()) {
+ propertyIndex = ScopedObject(scope, getPrototypeOf())->getValueOrSetter(id, &attrs);
+ if (!propertyIndex.isNull()) {
if (attrs.isAccessor()) {
- if (!memberIndex->as<FunctionObject>())
+ if (!propertyIndex->as<FunctionObject>())
return false;
} else if (!isExtensible() || !attrs.isWritable()) {
return false;
@@ -677,228 +540,59 @@ bool Object::internalPut(String *name, const Value &value)
cont:
// Clause 5
- if (!memberIndex.isNull() && attrs.isAccessor()) {
- Q_ASSERT(memberIndex->as<FunctionObject>());
+ if (!propertyIndex.isNull() && attrs.isAccessor()) {
+ Q_ASSERT(propertyIndex->as<FunctionObject>());
Scope scope(engine);
- ScopedFunctionObject setter(scope, *memberIndex);
+ ScopedFunctionObject setter(scope, *propertyIndex);
JSCallData jsCallData(scope, 1);
jsCallData->args[0] = value;
- *jsCallData->thisObject = this;
+ *jsCallData->thisObject = *receiver;
setter->call(jsCallData);
return !engine->hasException;
}
- insertMember(name, value);
- return true;
-}
-
-bool Object::internalPutIndexed(uint index, const Value &value)
-{
- ExecutionEngine *engine = this->engine();
- if (engine->hasException)
- return false;
-
- PropertyAttributes attrs;
-
- ArrayData::Index arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : ArrayData::Index{ nullptr, 0 };
-
- if (arrayIndex.isNull() && isStringObject()) {
- if (index < static_cast<StringObject *>(this)->length())
- // not writable
- return false;
- }
-
- // clause 1
- if (!arrayIndex.isNull()) {
- if (attrs.isAccessor()) {
- if (arrayIndex->as<FunctionObject>())
- goto cont;
- return false;
- } else if (!attrs.isWritable())
- return false;
-
- arrayIndex.set(engine, value);
- return true;
- } else if (!prototype()) {
- if (!isExtensible())
- return false;
+ if (index != UINT_MAX) {
+ arraySet(index, value);
} else {
- // clause 4
- Scope scope(engine);
- arrayIndex = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs);
- if (!arrayIndex.isNull()) {
- if (attrs.isAccessor()) {
- if (!arrayIndex->as<FunctionObject>())
- return false;
- } else if (!isExtensible() || !attrs.isWritable()) {
- return false;
- }
- } else if (!isExtensible()) {
- return false;
- }
- }
-
- cont:
-
- // Clause 5
- if (!arrayIndex.isNull() && attrs.isAccessor()) {
- Q_ASSERT(arrayIndex->as<FunctionObject>());
-
- Scope scope(engine);
- ScopedFunctionObject setter(scope, *arrayIndex);
- JSCallData jsCallData(scope, 1);
- jsCallData->args[0] = value;
- *jsCallData->thisObject = this;
- setter->call(jsCallData);
- return !engine->hasException;
+ Scoped<StringOrSymbol> name(scope, id.asStringOrSymbol());
+ insertMember(name, value);
}
-
- arraySet(index, value);
return true;
}
// Section 8.12.7
-bool Object::internalDeleteProperty(String *name)
+bool Object::internalDeleteProperty(PropertyKey id)
{
if (internalClass()->engine->hasException)
return false;
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return deleteIndexedProperty(idx);
-
- name->makeIdentifier();
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ Scope scope(engine());
+ if (scope.engine->hasException)
+ return false;
- uint memberIdx = internalClass()->find(name->identifier());
- if (memberIdx != UINT_MAX) {
- if (internalClass()->propertyData[memberIdx].isConfigurable()) {
- InternalClass::removeMember(this, name->identifier());
+ Scoped<ArrayData> ad(scope, arrayData());
+ if (!ad || ad->vtable()->del(this, index))
return true;
- }
- return false;
- }
- return true;
-}
-
-bool Object::internalDeleteIndexedProperty(uint index)
-{
- Scope scope(engine());
- if (scope.engine->hasException)
return false;
+ }
- Scoped<ArrayData> ad(scope, arrayData());
- if (!ad || ad->vtable()->del(this, index))
- return true;
-
- return false;
-}
-
-// Section 8.12.9
-bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return __defineOwnProperty__(engine, idx, p, attrs);
-
- Scope scope(engine);
- name->makeIdentifier();
-
- uint memberIndex;
-
- if (isArrayObject() && name->equals(engine->id_length())) {
- Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()));
- ScopedProperty lp(scope);
- PropertyAttributes cattrs;
- getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs);
- if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
+ uint memberIdx = internalClass()->find(id);
+ if (memberIdx != UINT_MAX) {
+ if (internalClass()->propertyData[memberIdx].isConfigurable()) {
+ Heap::InternalClass::removeMember(this, id);
return true;
- if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
- return false;
- bool succeeded = true;
- if (attrs.type() == PropertyAttributes::Data) {
- bool ok;
- uint l = p->value.asArrayLength(&ok);
- if (!ok) {
- ScopedValue v(scope, p->value);
- engine->throwRangeError(v);
- return false;
- }
- succeeded = setArrayLength(l);
}
- if (attrs.hasWritable() && !attrs.isWritable()) {
- cattrs.setWritable(false);
- InternalClass::changeMember(this, engine->id_length(), cattrs);
- }
- if (!succeeded)
- return false;
- return true;
- }
-
- // Clause 1
- memberIndex = internalClass()->find(name->identifier());
-
- if (memberIndex == UINT_MAX) {
- // clause 3
- if (!isExtensible())
- return false;
- // clause 4
- ScopedProperty pd(scope);
- pd->copy(p, attrs);
- pd->fullyPopulated(&attrs);
- insertMember(name, pd, attrs);
- return true;
- }
-
- return __defineOwnProperty__(engine, memberIndex, name, p, attrs);
-}
-
-bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
-{
- // 15.4.5.1, 4b
- if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable())
return false;
-
- if (ArgumentsObject::isNonStrictArgumentsObject(this))
- return static_cast<ArgumentsObject *>(this)->defineOwnProperty(engine, index, p, attrs);
-
- return defineOwnProperty2(engine, index, p, attrs);
-}
-
-bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
-{
- bool hasProperty = 0;
-
- // Clause 1
- if (arrayData()) {
- hasProperty = arrayData()->mappedIndex(index) != UINT_MAX;
- if (!hasProperty && isStringObject())
- hasProperty = (index < static_cast<StringObject *>(this)->length());
}
- if (!hasProperty) {
- // clause 3
- if (!isExtensible())
- return false;
- // clause 4
- Scope scope(engine);
- ScopedProperty pp(scope);
- pp->copy(p, attrs);
- pp->fullyPopulated(&attrs);
- if (attrs == Attr_Data) {
- ScopedValue v(scope, pp->value);
- arraySet(index, v);
- } else {
- arraySet(index, pp, attrs);
- }
- return true;
- }
-
- return __defineOwnProperty__(engine, index, nullptr, p, attrs);
+ return true;
}
-bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs)
+bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs)
{
// clause 5
if (attrs.isEmpty())
@@ -977,7 +671,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
current->merge(cattrs, p, attrs);
if (member) {
- InternalClass::changeMember(this, member, cattrs);
+ Heap::InternalClass::changeMember(this, member->propertyKey(), cattrs);
setProperty(index, current);
} else {
setArrayAttributes(index, cattrs);
@@ -986,15 +680,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
return true;
}
-
-bool Object::__defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs)
-{
- Scope scope(engine);
- ScopedString s(scope, engine->newString(name));
- return __defineOwnProperty__(engine, s, p, attrs);
-}
-
-
void Object::copyArrayData(Object *other)
{
Q_ASSERT(isArrayObject());
@@ -1007,7 +692,7 @@ void Object::copyArrayData(Object *other)
ScopedValue v(scope);
for (uint i = 0; i < len; ++i) {
- arraySet(i, (v = other->getIndexed(i)));
+ arraySet(i, (v = other->get(i)));
}
} else if (!other->arrayData()) {
;
@@ -1030,15 +715,15 @@ void Object::copyArrayData(Object *other)
setArrayLengthUnchecked(other->getLength());
}
-uint Object::getLength(const Managed *m)
+qint64 Object::virtualGetLength(const Managed *m)
{
Scope scope(static_cast<const Object *>(m)->engine());
ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length()));
- return v->toUInt32();
+ return v->toLength();
}
// 'var' is 'V' in 15.3.5.3.
-ReturnedValue Object::instanceOf(const Object *typeObject, const Value &var)
+ReturnedValue Object::virtualInstanceOf(const Object *typeObject, const Value &var)
{
QV4::ExecutionEngine *engine = typeObject->internalClass()->engine;
@@ -1080,6 +765,141 @@ ReturnedValue Object::instanceOf(const Object *typeObject, const Value &var)
return Encode(false);
}
+bool Object::virtualHasProperty(const Managed *m, PropertyKey id)
+{
+ Scope scope(m->engine());
+ ScopedObject o(scope, m);
+ ScopedProperty p(scope);
+ while (o) {
+ if (o->getOwnProperty(id, p) != Attr_Invalid)
+ return true;
+
+ o = o->getPrototypeOf();
+ }
+
+ return false;
+}
+
+PropertyAttributes Object::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
+{
+ PropertyAttributes attrs;
+ Object *o = static_cast<Object *>(m);
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if (o->arrayData()) {
+ if (o->arrayData()->getProperty(index, p, &attrs))
+ return attrs;
+ }
+ } else {
+ Q_ASSERT(id.asStringOrSymbol());
+
+ uint member = o->internalClass()->find(id);
+ if (member < UINT_MAX) {
+ attrs = o->internalClass()->propertyData[member];
+ if (p) {
+ p->value = *o->propertyData(member);
+ if (attrs.isAccessor())
+ p->set = *o->propertyData(member + SetterOffset);
+ }
+ return attrs;
+ }
+ }
+
+ return Attr_Invalid;
+}
+
+bool Object::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
+{
+ Object *o = static_cast<Object *>(m);
+ Scope scope(o);
+
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+
+ bool hasProperty = false;
+
+ if (o->arrayData()) {
+ hasProperty = o->arrayData()->mappedIndex(index) != UINT_MAX;
+ if (!hasProperty && o->isStringObject())
+ hasProperty = (index < static_cast<StringObject *>(o)->length());
+ }
+
+ if (!hasProperty) {
+ if (!o->isExtensible())
+ return false;
+
+ ScopedProperty pp(scope);
+ pp->copy(p, attrs);
+ pp->fullyPopulated(&attrs);
+ if (attrs == Attr_Data) {
+ ScopedValue v(scope, pp->value);
+ o->arraySet(index, v);
+ } else {
+ o->arraySet(index, pp, attrs);
+ }
+ return true;
+ }
+
+ return o->internalDefineOwnProperty(scope.engine, index, nullptr, p, attrs);
+ }
+
+ uint memberIndex = o->internalClass()->find(id);
+ Scoped<StringOrSymbol> name(scope, id.asStringOrSymbol());
+
+ if (memberIndex == UINT_MAX) {
+ if (!o->isExtensible())
+ return false;
+
+ ScopedProperty pd(scope);
+ pd->copy(p, attrs);
+ pd->fullyPopulated(&attrs);
+ o->insertMember(name, pd, attrs);
+ return true;
+ }
+
+ return o->internalDefineOwnProperty(scope.engine, memberIndex, name, p, attrs);
+}
+
+bool Object::virtualIsExtensible(const Managed *m)
+{
+ return m->d()->internalClass->extensible;
+}
+
+bool Object::virtualPreventExtensions(Managed *m)
+{
+ Q_ASSERT(m->isObject());
+ Object *o = static_cast<Object *>(m);
+ o->setInternalClass(o->internalClass()->nonExtensible());
+ return true;
+}
+
+Heap::Object *Object::virtualGetPrototypeOf(const Managed *m)
+{
+ return m->internalClass()->prototype;
+}
+
+bool Object::virtualSetPrototypeOf(Managed *m, const Object *proto)
+{
+ Q_ASSERT(m->isObject());
+ Object *o = static_cast<Object *>(m);
+ Heap::Object *current = o->internalClass()->prototype;
+ Heap::Object *protod = proto ? proto->d() : nullptr;
+ if (current == protod)
+ return true;
+ if (!o->internalClass()->extensible)
+ return false;
+ Heap::Object *p = protod;
+ while (p) {
+ if (p == o->d())
+ return false;
+ if (p->vtable()->getPrototypeOf != Object::staticVTable()->getPrototypeOf)
+ break;
+ p = p->prototype();
+ }
+ o->setInternalClass(o->internalClass()->changePrototype(protod));
+ return true;
+}
+
bool Object::setArrayLength(uint newLen)
{
Q_ASSERT(isArrayObject());
@@ -1132,12 +952,10 @@ void Heap::ArrayObject::init(const QStringList &list)
a->setArrayLengthUnchecked(len);
}
-uint ArrayObject::getLength(const Managed *m)
+qint64 ArrayObject::virtualGetLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- if (a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->isInteger())
- return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->integerValue();
- return Primitive::toUInt32(a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->doubleValue());
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->toLength();
}
QStringList ArrayObject::toQStringList() const
@@ -1150,8 +968,62 @@ QStringList ArrayObject::toQStringList() const
uint length = getLength();
for (uint i = 0; i < length; ++i) {
- v = const_cast<ArrayObject *>(this)->getIndexed(i);
+ v = const_cast<ArrayObject *>(this)->get(i);
result.append(v->toQStringNoThrow());
}
return result;
}
+
+bool ArrayObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
+{
+ Q_ASSERT(m->isArrayObject());
+ ArrayObject *a = static_cast<ArrayObject *>(m);
+
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ uint len = a->getLength();
+ if (index >= len && !a->internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable())
+ return false;
+
+ bool succeeded = Object::virtualDefineOwnProperty(m, id, p, attrs);
+ if (!succeeded)
+ return false;
+
+ if (index >= len)
+ a->setArrayLengthUnchecked(index + 1);
+
+ return true;
+ }
+
+ ExecutionEngine *engine = m->engine();
+ if (id == engine->id_length()->propertyKey()) {
+ Scope scope(engine);
+ Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == a->internalClass()->find(engine->id_length()->propertyKey()));
+ ScopedProperty lp(scope);
+ PropertyAttributes cattrs;
+ a->getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs);
+ if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
+ return true;
+ if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
+ return false;
+ bool succeeded = true;
+ if (attrs.type() == PropertyAttributes::Data) {
+ bool ok;
+ uint l = p->value.asArrayLength(&ok);
+ if (!ok) {
+ ScopedValue v(scope, p->value);
+ engine->throwRangeError(v);
+ return false;
+ }
+ succeeded = a->setArrayLength(l);
+ }
+ if (attrs.hasWritable() && !attrs.isWritable()) {
+ cattrs.setWritable(false);
+ Heap::InternalClass::changeMember(a, engine->id_length()->propertyKey(), cattrs);
+ }
+ if (!succeeded)
+ return false;
+ return true;
+ }
+ return Object::virtualDefineOwnProperty(m, id, p, attrs);
+}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 1731ae3c76..dea080f98a 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -74,6 +74,10 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
static void markObjects(Heap::Base *base, MarkStack *stack);
void init() { Base::init(); }
+ const VTable *vtable() const {
+ return internalClass->vtable;
+ }
+
const Value *inlinePropertyDataWithOffset(uint indexWithOffset) const {
Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < vtable()->inlinePropertyOffset + vtable()->nInlineProperties);
return reinterpret_cast<const Value *>(this) + indexWithOffset;
@@ -90,15 +94,15 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
void setInlineProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
Q_ASSERT(index < vtable()->nInlineProperties);
Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
- WriteBarrier::write(e, this, prop->data_ptr(), b->asReturnedValue());
+ WriteBarrier::write(e, this, prop->data_ptr(), Value::fromHeapObject(b).asReturnedValue());
}
- QV4::MemberData::Index writablePropertyData(uint index) {
+ PropertyIndex writablePropertyData(uint index) {
uint nInline = vtable()->nInlineProperties;
if (index < nInline)
- return { this, reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index};
+ return PropertyIndex{ this, reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index};
index -= nInline;
- return { memberData, memberData->values.values + index };
+ return PropertyIndex{ memberData, memberData->values.values + index };
}
const Value *propertyData(uint index) const {
@@ -134,76 +138,6 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
}
-#define V4_OBJECT2(DataClass, superClass) \
- private: \
- DataClass() Q_DECL_EQ_DELETE; \
- Q_DISABLE_COPY(DataClass) \
- public: \
- Q_MANAGED_CHECK \
- typedef QV4::Heap::DataClass Data; \
- typedef superClass SuperClass; \
- static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
- V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
- QV4::Heap::DataClass *d() const { \
- QV4::Heap::DataClass *dptr = d_unchecked(); \
- dptr->_checkIsInitialized(); \
- return dptr; \
- } \
- Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
-
-#define V4_PROTOTYPE(p) \
- static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
- { return e->p(); }
-
-struct ObjectVTable
-{
- VTable vTable;
- ReturnedValue (*call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- ReturnedValue (*callAsConstructor)(const FunctionObject *, const Value *argv, int argc);
- ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty);
- ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
- bool (*put)(Managed *, String *name, const Value &value);
- bool (*putIndexed)(Managed *, uint index, const Value &value);
- PropertyAttributes (*query)(const Managed *, String *name);
- PropertyAttributes (*queryIndexed)(const Managed *, uint index);
- bool (*deleteProperty)(Managed *m, String *name);
- bool (*deleteIndexedProperty)(Managed *m, uint index);
- uint (*getLength)(const Managed *m);
- void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- ReturnedValue (*instanceOf)(const Object *typeObject, const Value &var);
-};
-
-#define DEFINE_OBJECT_VTABLE_BASE(classname) \
-const QV4::ObjectVTable classname::static_vtbl = \
-{ \
- DEFINE_MANAGED_VTABLE_INT(classname, (std::is_same<classname::SuperClass, Object>::value) ? nullptr : &classname::SuperClass::static_vtbl.vTable), \
- call, \
- callAsConstructor, \
- get, \
- getIndexed, \
- put, \
- putIndexed, \
- query, \
- queryIndexed, \
- deleteProperty, \
- deleteIndexedProperty, \
- getLength, \
- advanceIterator, \
- instanceOf \
-}
-
-#define DEFINE_OBJECT_VTABLE(classname) \
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
-DEFINE_OBJECT_VTABLE_BASE(classname) \
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
-
-#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
-template<> DEFINE_OBJECT_VTABLE_BASE(classname) \
-QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
-
struct Q_QML_EXPORT Object: Managed {
V4_OBJECT2(Object, Object)
Q_MANAGED_TYPE(Object)
@@ -218,7 +152,7 @@ struct Q_QML_EXPORT Object: Managed {
SetterOffset = 1
};
- void setInternalClass(InternalClass *ic);
+ void setInternalClass(Heap::InternalClass *ic);
const Value *propertyData(uint index) const { return d()->propertyData(index); }
@@ -232,27 +166,21 @@ struct Q_QML_EXPORT Object: Managed {
void setProperty(ExecutionEngine *engine, uint index, Value v) const { d()->setProperty(engine, index, v); }
void setProperty(ExecutionEngine *engine, uint index, Heap::Base *b) const { d()->setProperty(engine, index, b); }
- const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
- Heap::Object *prototype() const { return d()->prototype(); }
- bool setPrototype(Object *proto);
+ const VTable *vtable() const { return d()->vtable(); }
- void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = nullptr);
- void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = nullptr);
-
- MemberData::Index getValueOrSetter(String *name, PropertyAttributes *attrs);
- ArrayData::Index getValueOrSetter(uint index, PropertyAttributes *attrs);
+ PropertyAttributes getOwnProperty(PropertyKey id, Property *p = nullptr) {
+ return vtable()->getOwnProperty(this, id, p);
+ }
- bool hasProperty(String *name) const;
- bool hasProperty(uint index) const;
+ PropertyIndex getValueOrSetter(PropertyKey id, PropertyAttributes *attrs);
- bool hasOwnProperty(String *name) const;
- bool hasOwnProperty(uint index) const;
+ bool hasProperty(PropertyKey id) const {
+ return vtable()->hasProperty(this, id);
+ }
- bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs);
- bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
+ bool defineOwnProperty(PropertyKey id, const Property *p, PropertyAttributes attrs) {
+ return vtable()->defineOwnProperty(this, id, p, attrs);
+ }
//
// helpers
@@ -267,33 +195,39 @@ struct Q_QML_EXPORT Object: Managed {
bool putValue(uint memberIndex, const Value &value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
- void defineDefaultProperty(String *name, const Value &value) {
- insertMember(name, value, Attr_Data|Attr_NotEnumerable);
+ void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable) {
+ insertMember(name, value, attributes);
}
- void defineDefaultProperty(const QString &name, const Value &value);
- void defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount = 0);
- void defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount = 0);
- void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
- ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int));
- void defineAccessorProperty(String *name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
- ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int));
+ void defineDefaultProperty(const QString &name, const Value &value, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable);
+ void defineDefaultProperty(const QString &name, VTable::Call code,
+ int argumentCount = 0, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable);
+ void defineDefaultProperty(StringOrSymbol *name, VTable::Call code,
+ int argumentCount = 0, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable);
+ void defineAccessorProperty(const QString &name, VTable::Call getter, VTable::Call setter);
+ void defineAccessorProperty(StringOrSymbol *name, VTable::Call getter, VTable::Call setter);
/* Fixed: Writable: false, Enumerable: false, Configurable: false */
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
/* Fixed: Writable: false, Enumerable: false, Configurable: true */
void defineReadonlyConfigurableProperty(const QString &name, const Value &value);
- void defineReadonlyConfigurableProperty(String *name, const Value &value);
+ void defineReadonlyConfigurableProperty(StringOrSymbol *name, const Value &value);
+
+ void addSymbolSpecies();
- void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
+ void insertMember(StringOrSymbol *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
ScopedProperty p(scope);
p->value = v;
insertMember(s, p, attributes);
}
- void insertMember(String *s, const Property *p, PropertyAttributes attributes);
+ void insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes);
- bool isExtensible() const { return d()->internalClass->extensible; }
+ bool isExtensible() const { return vtable()->isExtensible(this); }
+ bool preventExtensions() { return vtable()->preventExtensions(this); }
+ Heap::Object *getPrototypeOf() const { return vtable()->getPrototypeOf(this); }
+ bool setPrototypeOf(const Object *p) { return vtable()->setPrototypeOf(this, p); }
+ void setPrototypeUnchecked(const Object *p);
// Array handling
@@ -353,33 +287,58 @@ public:
Scope scope(engine());
ScopedObject p(scope, this);
- while ((p = p->prototype()))
+ while ((p = p->getPrototypeOf()))
if (p->arrayData())
return true;
return false;
}
- inline ReturnedValue get(String *name, bool *hasProperty = nullptr) const
- { return vtable()->get(this, name, hasProperty); }
- inline ReturnedValue getIndexed(uint idx, bool *hasProperty = nullptr) const
- { return vtable()->getIndexed(this, idx, hasProperty); }
+ inline ReturnedValue get(StringOrSymbol *name, bool *hasProperty = nullptr, const Value *receiver = nullptr) const
+ { if (!receiver) receiver = this; return vtable()->get(this, name->toPropertyKey(), receiver, hasProperty); }
+ inline ReturnedValue get(uint idx, bool *hasProperty = nullptr, const Value *receiver = nullptr) const
+ { if (!receiver) receiver = this; return vtable()->get(this, PropertyKey::fromArrayIndex(idx), receiver, hasProperty); }
+ QT_DEPRECATED inline ReturnedValue getIndexed(uint idx, bool *hasProperty = nullptr) const
+ { return get(idx, hasProperty); }
+ inline ReturnedValue get(PropertyKey id, const Value *receiver = nullptr, bool *hasProperty = nullptr) const
+ { if (!receiver) receiver = this; return vtable()->get(this, id, receiver, hasProperty); }
// use the set variants instead, to customize throw behavior
- inline bool put(String *name, const Value &v)
- { return vtable()->put(this, name, v); }
- inline bool putIndexed(uint idx, const Value &v)
- { return vtable()->putIndexed(this, idx, v); }
+ inline bool put(StringOrSymbol *name, const Value &v, Value *receiver = nullptr)
+ { if (!receiver) receiver = this; return vtable()->put(this, name->toPropertyKey(), v, receiver); }
+ inline bool put(uint idx, const Value &v, Value *receiver = nullptr)
+ { if (!receiver) receiver = this; return vtable()->put(this, PropertyKey::fromArrayIndex(idx), v, receiver); }
+ QT_DEPRECATED inline bool putIndexed(uint idx, const Value &v)
+ { return put(idx, v); }
+ inline bool put(PropertyKey id, const Value &v, Value *receiver = nullptr)
+ { if (!receiver) receiver = this; return vtable()->put(this, id, v, receiver); }
enum ThrowOnFailure {
DoThrowOnRejection,
DoNotThrow
};
+ // This is the same as set(), but it doesn't require creating a string key,
+ // which is much more efficient for the array case.
+ inline bool setIndexed(uint idx, const Value &v, ThrowOnFailure shouldThrow)
+ {
+ bool ret = vtable()->put(this, PropertyKey::fromArrayIndex(idx), v, this);
+ // ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception.
+ if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
+ ExecutionEngine *e = engine();
+ if (!e->hasException) { // allow a custom set impl to throw itself
+ QString message = QLatin1String("Cannot assign to read-only property \"") +
+ QString::number(idx) + QLatin1Char('\"');
+ e->throwTypeError(message);
+ }
+ }
+ return ret;
+ }
+
// ES6: 7.3.3 Set (O, P, V, Throw)
- inline bool set(String *name, const Value &v, ThrowOnFailure shouldThrow)
+ inline bool set(StringOrSymbol *name, const Value &v, ThrowOnFailure shouldThrow)
{
- bool ret = vtable()->put(this, name, v);
+ bool ret = vtable()->put(this, name->toPropertyKey(), v, this);
// ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception.
if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
ExecutionEngine *e = engine();
@@ -392,42 +351,37 @@ public:
return ret;
}
- PropertyAttributes query(String *name) const
- { return vtable()->query(this, name); }
- PropertyAttributes queryIndexed(uint index) const
- { return vtable()->queryIndexed(this, index); }
- bool deleteProperty(String *name)
- { return vtable()->deleteProperty(this, name); }
- bool deleteIndexedProperty(uint index)
- { return vtable()->deleteIndexedProperty(this, index); }
+ bool deleteProperty(PropertyKey id)
+ { return vtable()->deleteProperty(this, id); }
void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
- uint getLength() const { return vtable()->getLength(this); }
+ qint64 getLength() const { return vtable()->getLength(this); }
ReturnedValue instanceOf(const Value &var) const
{ return vtable()->instanceOf(this, var); }
protected:
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
- static bool putIndexed(Managed *m, uint index, const Value &value);
- static PropertyAttributes query(const Managed *m, String *name);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static bool deleteProperty(Managed *m, String *name);
- static bool deleteIndexedProperty(Managed *m, uint index);
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- static uint getLength(const Managed *m);
- static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver,bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static bool virtualDeleteProperty(Managed *m, PropertyKey id);
+ static bool virtualHasProperty(const Managed *m, PropertyKey id);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs);
+ static bool virtualIsExtensible(const Managed *m);
+ static bool virtualPreventExtensions(Managed *);
+ static Heap::Object *virtualGetPrototypeOf(const Managed *);
+ static bool virtualSetPrototypeOf(Managed *, const Object *);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static qint64 virtualGetLength(const Managed *m);
+ static ReturnedValue virtualInstanceOf(const Object *typeObject, const Value &var);
private:
- ReturnedValue internalGet(String *name, bool *hasProperty) const;
- ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
- bool internalPut(String *name, const Value &value);
- bool internalPutIndexed(uint index, const Value &value);
- bool internalDeleteProperty(String *name);
- bool internalDeleteIndexedProperty(uint index);
+ bool internalDefineOwnProperty(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs);
+ ReturnedValue internalGet(StringOrSymbol *name, const Value *receiver, bool *hasProperty) const;
+ ReturnedValue internalGetIndexed(uint index, const Value *receiver, bool *hasProperty) const;
+ bool internalPut(PropertyKey id, const Value &value, Value *receiver);
+ bool internalDeleteProperty(PropertyKey id);
friend struct ObjectIterator;
friend struct ObjectPrototype;
@@ -499,10 +453,12 @@ struct ArrayObject: Object {
void init(ExecutionEngine *engine);
- using Object::getLength;
- static uint getLength(const Managed *m);
+ static qint64 virtualGetLength(const Managed *m);
QStringList toQStringList() const;
+protected:
+ static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs);
+
};
inline void Object::setArrayLengthUnchecked(uint l)
@@ -551,7 +507,7 @@ inline void Object::arraySet(uint index, const Value &value)
template<>
inline const ArrayObject *Value::as() const {
- return isManaged() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : nullptr;
+ return isManaged() && m()->internalClass->vtable->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : nullptr;
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 7bf7e1aa04..73c09a864a 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -42,9 +42,29 @@
#include "qv4identifier_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4string_p.h"
+#include "qv4iterator_p.h"
using namespace QV4;
+void ForInIteratorPrototype::init(ExecutionEngine *)
+{
+ defineDefaultProperty(QStringLiteral("next"), method_next, 0);
+}
+
+ReturnedValue ForInIteratorPrototype::method_next(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ const ForInIteratorObject *forIn = thisObject->as<ForInIteratorObject>();
+ Q_ASSERT(forIn);
+ Scope scope(b->engine());
+ ScopedValue n(scope, forIn->nextPropertyName());
+ bool done = false;
+ if (n->asReturnedValue() == Encode::null()) {
+ done = true;
+ n = Primitive::undefinedValue();
+ }
+ return IteratorPrototype::createIterResultObject(scope.engine, n, done);
+}
+
void ObjectIterator::init(const Object *o)
{
object->setM(o ? o->m() : nullptr);
@@ -84,12 +104,12 @@ void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttrib
n = *name;
bool shadowed = false;
while (o->d() != current->heapObject()) {
- if ((!!n && o->hasOwnProperty(n)) ||
- (*index != UINT_MAX && o->hasOwnProperty(*index))) {
+ PropertyKey id = n ? (n->toPropertyKey()) : PropertyKey::fromArrayIndex(*index);
+ if (id.isValid() && o->getOwnProperty(id) != Attr_Invalid) {
shadowed = true;
break;
}
- o = o->prototype();
+ o = o->getPrototypeOf();
}
if (shadowed)
continue;
@@ -98,7 +118,7 @@ void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttrib
}
if (flags & WithProtoChain)
- current->setM(co->prototype());
+ current->setM(co->getPrototypeOf());
else
current->setM(nullptr);
@@ -175,11 +195,11 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
}
-DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
+DEFINE_OBJECT_VTABLE(ForInIteratorObject);
-void Heap::ForEachIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
+void Heap::ForInIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
{
- ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
+ ForInIteratorObject *o = static_cast<ForInIteratorObject *>(that);
o->workArea[0].mark(markStack);
o->workArea[1].mark(markStack);
Object::markObjects(that, markStack);
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 744d16301a..1e7000ad1f 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -92,8 +92,8 @@ struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData
ObjectIterator(Scope &scope, const Object *o, uint flags)
{
engine = scope.engine;
- object = scope.alloc(1);
- current = scope.alloc(1);
+ object = scope.alloc();
+ current = scope.alloc();
arrayNode = nullptr;
arrayIndex = 0;
memberIndex = 0;
@@ -111,7 +111,7 @@ private:
};
namespace Heap {
-struct ForEachIteratorObject : Object {
+struct ForInIteratorObject : Object {
void init(QV4::Object *o);
ObjectIterator &it() { return *reinterpret_cast<ObjectIterator*>(&itData); }
Value workArea[2];
@@ -123,15 +123,24 @@ private:
}
-struct ForEachIteratorObject: Object {
- V4_OBJECT2(ForEachIteratorObject, Object)
- Q_MANAGED_TYPE(ForeachIteratorObject)
+struct ForInIteratorPrototype : Object
+{
+ V4_PROTOTYPE(iteratorPrototype)
+ void init(ExecutionEngine *engine);
+
+ static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct ForInIteratorObject: Object {
+ V4_OBJECT2(ForInIteratorObject, Object)
+ Q_MANAGED_TYPE(ForInIterator)
+ V4_PROTOTYPE(forInIteratorPrototype)
- ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); }
+ ReturnedValue nextPropertyName() const { return d()->it().nextPropertyNameAsString(); }
};
inline
-void Heap::ForEachIteratorObject::init(QV4::Object *o)
+void Heap::ForInIteratorObject::init(QV4::Object *o)
{
Object::init();
it() = ObjectIterator(internalClass->engine, workArea, workArea + 1, o,
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index b998b78520..65e9b836d1 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -47,6 +47,8 @@
#include "qv4objectiterator_p.h"
#include "qv4string_p.h"
#include "qv4jscall_p.h"
+#include "qv4symbol_p.h"
+#include "qv4propertykey_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
@@ -61,23 +63,23 @@ void Heap::ObjectCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Object"));
}
-ReturnedValue ObjectCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue ObjectCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *v4 = f->engine();
- const ObjectCtor *ctor = static_cast<const ObjectCtor *>(f);
+ const ObjectCtor *nt = static_cast<const ObjectCtor *>(newTarget);
if (!argc || argv[0].isUndefined() || argv[0].isNull()) {
Scope scope(v4);
ScopedObject obj(scope, scope.engine->newObject());
- ScopedObject proto(scope, ctor->get(scope.engine->id_prototype()));
+ ScopedObject proto(scope, nt->get(scope.engine->id_prototype()));
if (!!proto)
- obj->setPrototype(proto);
+ obj->setPrototypeOf(proto);
return obj.asReturnedValue();
} else {
return argv[0].toObject(v4)->asReturnedValue();
}
}
-ReturnedValue ObjectCtor::call(const FunctionObject *m, const Value *, const Value *argv, int argc)
+ReturnedValue ObjectCtor::virtualCall(const FunctionObject *m, const Value *, const Value *argv, int argc)
{
ExecutionEngine *v4 = m->engine();
if (!argc || argv[0].isUndefined() || argv[0].isNull()) {
@@ -97,6 +99,7 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
+ ctor->defineDefaultProperty(QStringLiteral("getOwnPropertySymbols"), method_getOwnPropertySymbols, 1);
ctor->defineDefaultProperty(QStringLiteral("assign"), method_assign, 2);
ctor->defineDefaultProperty(QStringLiteral("create"), method_create, 2);
ctor->defineDefaultProperty(QStringLiteral("defineProperty"), method_defineProperty, 3);
@@ -104,10 +107,12 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("seal"), method_seal, 1);
ctor->defineDefaultProperty(QStringLiteral("freeze"), method_freeze, 1);
ctor->defineDefaultProperty(QStringLiteral("preventExtensions"), method_preventExtensions, 1);
+ ctor->defineDefaultProperty(QStringLiteral("is"), method_is, 2);
ctor->defineDefaultProperty(QStringLiteral("isSealed"), method_isSealed, 1);
ctor->defineDefaultProperty(QStringLiteral("isFrozen"), method_isFrozen, 1);
ctor->defineDefaultProperty(QStringLiteral("isExtensible"), method_isExtensible, 1);
ctor->defineDefaultProperty(QStringLiteral("keys"), method_keys, 1);
+ ctor->defineDefaultProperty(QStringLiteral("setPrototypeOf"), method_setPrototypeOf, 2);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(v4->id_toString(), method_toString, 0);
@@ -119,11 +124,7 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
- ExecutionContext *global = v4->rootContext();
- ScopedProperty p(scope);
- p->value = FunctionObject::createBuiltinFunction(global, v4->id___proto__(), method_get_proto);
- p->set = FunctionObject::createBuiltinFunction(global, v4->id___proto__(), method_set_proto);
- insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
+ defineAccessorProperty(v4->id___proto__(), method_get_proto, method_set_proto);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(const FunctionObject *b, const Value *, const Value *argv, int argc)
@@ -136,10 +137,19 @@ ReturnedValue ObjectPrototype::method_getPrototypeOf(const FunctionObject *b, co
if (scope.engine->hasException)
return QV4::Encode::undefined();
- ScopedObject p(scope, o->prototype());
+ ScopedObject p(scope, o->getPrototypeOf());
return (!!p ? p->asReturnedValue() : Encode::null());
}
+ReturnedValue ObjectPrototype::method_is(const FunctionObject *, const Value *, const Value *argv, int argc)
+{
+ if (!argc)
+ return Encode(true);
+ if (argc == 1)
+ return Encode((argv[0].isUndefined() ? true : false));
+ return Encode(argv[0].sameValue(argv[1]));
+}
+
ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
Scope scope(b);
@@ -154,13 +164,12 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObj
static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate();
ScopedValue v(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
- ScopedString name(scope, v->toString(scope.engine));
+ ScopedPropertyKey name(scope, v->toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- PropertyAttributes attrs;
ScopedProperty desc(scope);
- O->getOwnProperty(name, &attrs, desc);
+ PropertyAttributes attrs = O->getOwnProperty(name, desc);
return fromPropertyDescriptor(scope.engine, desc, attrs);
}
@@ -177,6 +186,28 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyNames(const FunctionObject *
return Encode(getOwnPropertyNames(scope.engine, argv[0]));
}
+ReturnedValue ObjectPrototype::method_getOwnPropertySymbols(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (!argc)
+ return scope.engine->throwTypeError();
+
+ ScopedObject O(scope, argv[0].toObject(scope.engine));
+ if (!O)
+ return Encode::undefined();
+ Heap::InternalClass *ic = O->d()->internalClass;
+ ScopedValue n(scope);
+ ScopedArrayObject array(scope, scope.engine->newArrayObject());
+ for (uint i = 0; i < ic->size; ++i) {
+ PropertyKey id = ic->nameMap.at(i);
+ n = id.asStringOrSymbol();
+ if (!n || !n->isSymbol())
+ continue;
+ array->push_back(n);
+ }
+ return array->asReturnedValue();
+}
+
// 19.1.2.1
ReturnedValue ObjectPrototype::method_assign(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
@@ -204,11 +235,10 @@ ReturnedValue ObjectPrototype::method_assign(const FunctionObject *b, const Valu
ScopedString nextKey(scope);
ScopedValue propValue(scope);
for (quint32 i = 0; i < length; ++i) {
- nextKey = Value::fromReturnedValue(keys->getIndexed(i)).toString(scope.engine);
+ nextKey = Value::fromReturnedValue(keys->get(i)).toString(scope.engine);
- PropertyAttributes attrs;
ScopedProperty prop(scope);
- from->getOwnProperty(nextKey, &attrs, prop);
+ PropertyAttributes attrs = from->getOwnProperty(nextKey->toPropertyKey(), prop);
if (attrs == PropertyFlag::Attr_Invalid)
continue;
@@ -235,7 +265,7 @@ ReturnedValue ObjectPrototype::method_create(const FunctionObject *builtin, cons
ScopedObject O(scope, argv[0]);
ScopedObject newObject(scope, scope.engine->newObject());
- newObject->setPrototype(O);
+ newObject->setPrototypeOf(O);
if (argc > 1 && !argv[1].isUndefined()) {
@@ -255,7 +285,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(const FunctionObject *b, co
return scope.engine->throwTypeError();
ScopedObject O(scope, argv[0]);
- ScopedString name(scope, argc > 1 ? argv[1] : Primitive::undefinedValue(), ScopedString::Convert);
+ ScopedPropertyKey name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
@@ -266,7 +296,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(const FunctionObject *b, co
if (scope.engine->hasException)
return QV4::Encode::undefined();
- if (!O->__defineOwnProperty__(scope.engine, name, pd, attrs))
+ if (!O->defineOwnProperty(name, pd, attrs))
THROW_TYPE_ERROR();
return O.asReturnedValue();
@@ -287,7 +317,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(const FunctionObject *b,
ScopedValue val(scope);
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
- ScopedString name(scope);
+ ScopedStringOrSymbol name(scope);
ScopedProperty pd(scope);
ScopedProperty n(scope);
while (1) {
@@ -303,9 +333,9 @@ ReturnedValue ObjectPrototype::method_defineProperties(const FunctionObject *b,
return QV4::Encode::undefined();
bool ok;
if (name)
- ok = O->__defineOwnProperty__(scope.engine, name, n, nattrs);
+ ok = O->defineOwnProperty(name->toPropertyKey(), n, nattrs);
else
- ok = O->__defineOwnProperty__(scope.engine, index, n, nattrs);
+ ok = O->defineOwnProperty(PropertyKey::fromArrayIndex(index), n, nattrs);
if (!ok)
THROW_TYPE_ERROR();
}
@@ -372,7 +402,7 @@ ReturnedValue ObjectPrototype::method_preventExtensions(const FunctionObject *b,
if (!o)
return argv[0].asReturnedValue();
- o->setInternalClass(o->internalClass()->nonExtensible());
+ o->preventExtensions();
return o.asReturnedValue();
}
@@ -477,19 +507,53 @@ ReturnedValue ObjectPrototype::method_keys(const FunctionObject *b, const Value
return a.asReturnedValue();
}
+ReturnedValue ObjectPrototype::method_setPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f->engine());
+ if (argc < 2 || argv[0].isNullOrUndefined() || !(argv[1].isObject() || argv[1].isNull()))
+ return scope.engine->throwTypeError();
+
+ if (!argv[0].isObject())
+ return argv[0].asReturnedValue();
+
+ ScopedObject o(scope, argv[0]);
+ const Object *p = argv[1].isNull() ? nullptr : static_cast<const Object *>(argv + 1);
+ bool ok = o->setPrototypeOf(p);
+ if (!ok)
+ return scope.engine->throwTypeError(QStringLiteral("Could not change prototype."));
+ return o->asReturnedValue();
+}
+
ReturnedValue ObjectPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
+ QString string;
if (thisObject->isUndefined()) {
- return Encode(v4->newString(QStringLiteral("[object Undefined]")));
+ string = QStringLiteral("[object Undefined]");
} else if (thisObject->isNull()) {
- return Encode(v4->newString(QStringLiteral("[object Null]")));
+ string = QStringLiteral("[object Null]");
} else {
+ const Object *o = thisObject->as<Object>();
+ if (!o) {
+ // primitive, get the proper prototype
+ if (thisObject->isBoolean())
+ o = v4->booleanPrototype();
+ else if (thisObject->isNumber())
+ o = v4->numberPrototype();
+ else if (thisObject->isString())
+ o = v4->stringPrototype();
+ else if (thisObject->isSymbol())
+ o = v4->symbolPrototype();
+ Q_ASSERT(o);
+ }
+ QString name = o->className();
Scope scope(v4);
- ScopedObject obj(scope, thisObject->toObject(scope.engine));
- QString className = obj->className();
- return Encode(v4->newString(QStringLiteral("[object %1]").arg(className)));
+ ScopedString toStringTag(scope, o->get(v4->symbol_toStringTag()));
+ if (toStringTag)
+ name = toStringTag->toQString();
+ string = QStringLiteral("[object %1]").arg(name);
}
+ return Encode(v4->newString(string));
}
ReturnedValue ObjectPrototype::method_toLocaleString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
@@ -514,15 +578,13 @@ ReturnedValue ObjectPrototype::method_valueOf(const FunctionObject *b, const Val
ReturnedValue ObjectPrototype::method_hasOwnProperty(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
- ScopedString P(scope, argc ? argv[0] : Primitive::undefinedValue(), ScopedString::Convert);
+ ScopedPropertyKey P(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
ScopedObject O(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- bool r = O->hasOwnProperty(P);
- if (!r)
- r = !O->query(P).isEmpty();
+ bool r = O->getOwnProperty(P) != Attr_Invalid;
return Encode(r);
}
@@ -536,11 +598,11 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(const FunctionObject *b, con
ScopedObject O(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- ScopedObject proto(scope, V->prototype());
+ ScopedObject proto(scope, V->getPrototypeOf());
while (proto) {
if (O->d() == proto->d())
return Encode(true);
- proto = proto->prototype();
+ proto = proto->getPrototypeOf();
}
return Encode(false);
}
@@ -548,15 +610,14 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(const FunctionObject *b, con
ReturnedValue ObjectPrototype::method_propertyIsEnumerable(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
- ScopedString p(scope, argc ? argv[0] : Primitive::undefinedValue(), ScopedString::Convert);
+ ScopedPropertyKey p(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
ScopedObject o(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- PropertyAttributes attrs;
- o->getOwnProperty(p, &attrs);
+ PropertyAttributes attrs = o->getOwnProperty(p);
return Encode(attrs.isEnumerable());
}
@@ -584,7 +645,7 @@ ReturnedValue ObjectPrototype::method_defineGetter(const FunctionObject *b, cons
ScopedProperty pd(scope);
pd->value = f;
pd->set = Primitive::emptyValue();
- bool ok = o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
+ bool ok = o->defineOwnProperty(prop->toPropertyKey(), pd, Attr_Accessor);
if (!ok)
THROW_TYPE_ERROR();
RETURN_UNDEFINED();
@@ -614,7 +675,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(const FunctionObject *b, cons
ScopedProperty pd(scope);
pd->value = Primitive::emptyValue();
pd->set = f;
- bool ok = o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
+ bool ok = o->defineOwnProperty(prop->toPropertyKey(), pd, Attr_Accessor);
if (!ok)
THROW_TYPE_ERROR();
RETURN_UNDEFINED();
@@ -627,32 +688,21 @@ ReturnedValue ObjectPrototype::method_get_proto(const FunctionObject *b, const V
if (!o)
THROW_TYPE_ERROR();
- return Encode(o->prototype());
+ return Encode(o->getPrototypeOf());
}
ReturnedValue ObjectPrototype::method_set_proto(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
ScopedObject o(scope, thisObject);
- if (!o || !argc)
+ if (!o || !argc || (!argv[0].isObject() && !argv[0].isNull()))
THROW_TYPE_ERROR();
- if (argv[0].isNull()) {
- o->setPrototype(nullptr);
- RETURN_UNDEFINED();
- }
-
- ScopedObject p(scope, argv[0]);
- bool ok = false;
- if (!!p) {
- if (o->prototype() == p->d()) {
- ok = true;
- } else if (o->isExtensible()) {
- ok = o->setPrototype(p);
- }
- }
+ const Object *p = argv[0].isNull() ? nullptr : static_cast<const Object *>(argv);
+ bool ok = o->setPrototypeOf(p);
if (!ok)
- return scope.engine->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
+ return scope.engine->throwTypeError(QStringLiteral("Could not change prototype."));
+ return Encode::undefined();
RETURN_UNDEFINED();
}
@@ -670,13 +720,13 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(engine->id_enumerable()))
+ if (o->hasProperty(engine->id_enumerable()->toPropertyKey()))
attrs->setEnumerable((tmp = o->get(engine->id_enumerable()))->toBoolean());
- if (o->hasProperty(engine->id_configurable()))
+ if (o->hasProperty(engine->id_configurable()->toPropertyKey()))
attrs->setConfigurable((tmp = o->get(engine->id_configurable()))->toBoolean());
- if (o->hasProperty(engine->id_get())) {
+ if (o->hasProperty(engine->id_get()->toPropertyKey())) {
ScopedValue get(scope, o->get(engine->id_get()));
FunctionObject *f = get->as<FunctionObject>();
if (f || get->isUndefined()) {
@@ -688,7 +738,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_set())) {
+ if (o->hasProperty(engine->id_set()->toPropertyKey())) {
ScopedValue set(scope, o->get(engine->id_set()));
FunctionObject *f = set->as<FunctionObject>();
if (f || set->isUndefined()) {
@@ -700,7 +750,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_writable())) {
+ if (o->hasProperty(engine->id_writable()->toPropertyKey())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
@@ -710,7 +760,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(engine->id_value())) {
+ if (o->hasProperty(engine->id_value()->toPropertyKey())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
@@ -734,29 +784,28 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, c
// is the standard built-in constructor with that name.
ScopedObject o(scope, engine->newObject());
ScopedString s(scope);
+ ScopedValue v(scope);
- ScopedProperty pd(scope);
if (attrs.isData()) {
- pd->value = desc->value;
s = engine->newString(QStringLiteral("value"));
- o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
- pd->value = Primitive::fromBoolean(attrs.isWritable());
+ o->put(s, desc->value);
+ v = Primitive::fromBoolean(attrs.isWritable());
s = engine->newString(QStringLiteral("writable"));
- o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
+ o->put(s, v);
} else {
- pd->value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
+ v = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
s = engine->newString(QStringLiteral("get"));
- o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
- pd->value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
+ o->put(s, v);
+ v = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
s = engine->newString(QStringLiteral("set"));
- o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
+ o->put(s, v);
}
- pd->value = Primitive::fromBoolean(attrs.isEnumerable());
+ v = Primitive::fromBoolean(attrs.isEnumerable());
s = engine->newString(QStringLiteral("enumerable"));
- o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
- pd->value = Primitive::fromBoolean(attrs.isConfigurable());
+ o->put(s, v);
+ v = Primitive::fromBoolean(attrs.isConfigurable());
s = engine->newString(QStringLiteral("configurable"));
- o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
+ o->put(s, v);
return o.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 2b231d46ad..0314c05766 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -70,28 +70,31 @@ struct ObjectCtor: FunctionObject
{
V4_OBJECT2(ObjectCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc);
};
struct ObjectPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_getPrototypeOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_getOwnPropertyDescriptor(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_getOwnPropertyNames(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_assign(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_create(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_defineProperty(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_defineProperties(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_seal(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_defineProperty(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_freeze(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_preventExtensions(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_isSealed(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_isFrozen(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getOwnPropertyDescriptor(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getOwnPropertyNames(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getOwnPropertySymbols(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getPrototypeOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_is(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_isExtensible(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_isFrozen(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_isSealed(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_preventExtensions(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_seal(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_setPrototypeOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toLocaleString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 7fc74173e3..f8bc28160e 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -98,9 +98,9 @@ Page *allocatePage(PersistentValueStorage *storage)
p->header.freeList = 0;
insertInFront(storage, p);
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
- p->values[i].setEmpty(i + 1);
+ p->values[i] = Encode(i + 1);
}
- p->values[kEntriesPerPage - 1].setEmpty(-1);
+ p->values[kEntriesPerPage - 1] = Encode(-1);
return p;
}
@@ -226,7 +226,7 @@ void PersistentValueStorage::free(Value *v)
Page *p = getPage(v);
- v->setEmpty(p->header.freeList);
+ *v = Encode(p->header.freeList);
p->header.freeList = v - p->values;
if (!--p->header.refCount)
freePage(p);
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index 5fd200efc1..b337243204 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -78,7 +78,7 @@ Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(
void Profiler::stopProfiling()
{
featuresEnabled = 0;
- reportData(true);
+ reportData();
m_sentLocations.clear();
}
@@ -89,7 +89,7 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2)
(call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
}
-void Profiler::reportData(bool trackLocations)
+void Profiler::reportData()
{
std::sort(m_data.begin(), m_data.end());
QVector<FunctionCallProperties> properties;
@@ -100,12 +100,11 @@ void Profiler::reportData(bool trackLocations)
properties.append(call.properties());
Function *function = call.function();
SentMarker &marker = m_sentLocations[reinterpret_cast<quintptr>(function)];
- if (!trackLocations || !marker.isValid()) {
+ if (!marker.isValid()) {
FunctionLocation &location = locations[properties.constLast().id];
if (!location.isValid())
location = call.resolveLocation();
- if (trackLocations)
- marker.setFunction(function);
+ marker.setFunction(function);
}
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index e8c154e4e7..8461384e9a 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -251,7 +251,7 @@ public:
void stopProfiling();
void startProfiling(quint64 features);
- void reportData(bool trackLocations);
+ void reportData();
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 7cb106c424..26dc7a83c3 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -142,6 +142,19 @@ inline void Property::merge(PropertyAttributes &attrs, const Property *other, Pr
}
}
+struct PropertyIndex {
+ Heap::Base *base;
+ Value *slot;
+
+ void set(EngineBase *e, Value newVal) {
+ WriteBarrier::write(e, base, slot->data_ptr(), newVal.asReturnedValue());
+ }
+ const Value *operator->() const { return slot; }
+ const Value &operator*() const { return *slot; }
+ bool isNull() const { return !slot; }
+};
+
+
}
Q_DECLARE_TYPEINFO(QV4::Property, Q_MOVABLE_TYPE);
diff --git a/src/qml/jsruntime/qv4propertykey.cpp b/src/qml/jsruntime/qv4propertykey.cpp
new file mode 100644
index 0000000000..e5e96bedb8
--- /dev/null
+++ b/src/qml/jsruntime/qv4propertykey.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4propertykey_p.h"
+
+#include <QtCore/qstring.h>
+#include <qv4string_p.h>
+
+QV4::Heap::StringOrSymbol *QV4::PropertyKey::toStringOrSymbol(QV4::ExecutionEngine *e)
+{
+ if (isArrayIndex())
+ return Primitive::fromUInt32(asArrayIndex()).toString(e);
+ return static_cast<Heap::StringOrSymbol *>(asStringOrSymbol());
+}
+
+bool QV4::PropertyKey::isString() const {
+ Heap::StringOrSymbol *s = asStringOrSymbol();
+ return s && s->internalClass->vtable->isString;
+}
+
+bool QV4::PropertyKey::isSymbol() const {
+ Heap::Base *s = asStringOrSymbol();
+ return s && !s->internalClass->vtable->isString && s->internalClass->vtable->isStringOrSymbol;
+}
+
+QString QV4::PropertyKey::toQString() const
+{
+ if (isArrayIndex())
+ return QString::number(asArrayIndex());
+ Heap::Base *b = asStringOrSymbol();
+ Q_ASSERT(b->internalClass->vtable->isStringOrSymbol);
+ Heap::StringOrSymbol *s = static_cast<Heap::StringOrSymbol *>(b);
+ return s->toQString();
+}
diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
new file mode 100644
index 0000000000..00bf8fb195
--- /dev/null
+++ b/src/qml/jsruntime/qv4propertykey_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4PROPERTYKEY_H
+#define QV4PROPERTYKEY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace QV4 {
+
+struct PropertyKey
+{
+private:
+ // Property keys are Strings, Symbols or unsigned integers.
+ // For convenience we derive them from Values, allowing us to store them
+ // on the JS stack
+ //
+ // They do however behave somewhat different than a Value:
+ // * If the key is a String, the pointer to the string is stored in the identifier
+ // table and thus unique.
+ // * If the key is a Symbol it simply points to the referenced symbol object
+ // * if the key is an array index (a uint < UINT_MAX), it's encoded as an
+ // integer value
+ quint64 val;
+
+ // Important: Always keep this in sync with the definitions for Integers and heap objects in Value
+ static const quint64 ArrayIndexMask = 0x3800000000000ull;
+ enum {
+ IsManagedOrUndefined_Shift = 64-15,
+ };
+ inline bool isManaged() const { return (val >> IsManagedOrUndefined_Shift) == 0; }
+ inline quint32 value() const { return val & quint64(~quint32(0)); }
+
+#if QT_POINTER_SIZE == 8
+ QML_NEARLY_ALWAYS_INLINE Heap::StringOrSymbol *m() const
+ {
+ Heap::StringOrSymbol *b;
+ memcpy(&b, &val, 8);
+ return b;
+ }
+ QML_NEARLY_ALWAYS_INLINE void setM(Heap::StringOrSymbol *b)
+ {
+ memcpy(&val, &b, 8);
+ }
+#elif QT_POINTER_SIZE == 4
+ QML_NEARLY_ALWAYS_INLINE Heap::StringOrSymbol *m() const
+ {
+ Q_STATIC_ASSERT(sizeof(Heap::StringOrSymbol*) == sizeof(quint32));
+ Heap::StringOrSymbol *b;
+ quint32 v = value();
+ memcpy(&b, &v, 4);
+ return b;
+ }
+ QML_NEARLY_ALWAYS_INLINE void setM(Heap::StringOrSymbol *b)
+ {
+ quint32 v;
+ memcpy(&v, &b, 4);
+ val = v;
+ }
+#endif
+
+public:
+ static PropertyKey invalid() { PropertyKey key; key.val = 0; return key; }
+ static PropertyKey fromArrayIndex(uint idx) { PropertyKey key; key.val = ArrayIndexMask | static_cast<quint64>(idx); return key; }
+ bool isStringOrSymbol() const { return isManaged() && val != 0; }
+ uint asArrayIndex() const { return (isManaged() || val == 0) ? std::numeric_limits<uint>::max() : static_cast<uint>(val & 0xffffffff); }
+ uint isArrayIndex() const { return !isManaged() && val != 0; }
+ bool isValid() const { return val != 0; }
+ static PropertyKey fromStringOrSymbol(Heap::StringOrSymbol *b)
+ { PropertyKey key; key.setM(b); return key; }
+ Heap::StringOrSymbol *asStringOrSymbol() const {
+ if (!isManaged())
+ return nullptr;
+ return m();
+ }
+
+ bool isString() const;
+ bool isSymbol() const;
+
+ Q_QML_EXPORT QString toQString() const;
+ Heap::StringOrSymbol *toStringOrSymbol(ExecutionEngine *e);
+ quint64 id() const { return val; }
+
+ bool operator ==(const PropertyKey &other) const { return val == other.val; }
+ bool operator !=(const PropertyKey &other) const { return val != other.val; }
+ bool operator <(const PropertyKey &other) const { return val < other.val; }
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
new file mode 100644
index 0000000000..794aee8c24
--- /dev/null
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -0,0 +1,553 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qv4proxy_p.h"
+#include "qv4symbol_p.h"
+#include "qv4jscall_p.h"
+#include "qv4objectproto_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(ProxyObject);
+
+void Heap::ProxyObject::init(const QV4::Object *target, const QV4::Object *handler)
+{
+ Object::init();
+ ExecutionEngine *e = internalClass->engine;
+ this->target.set(e, target->d());
+ this->handler.set(e, handler->d());
+}
+
+ReturnedValue ProxyObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedValue trap(scope, handler->get(scope.engine->id_get()));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->get(id, receiver, hasProperty);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+ if (hasProperty)
+ *hasProperty = true;
+
+ JSCallData cdata(scope, 3, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.toStringOrSymbol(scope.engine);
+ cdata.args[2] = *receiver;
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
+ if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
+ if (attributes.isData() && !attributes.isWritable()) {
+ if (!trapResult->sameValue(targetDesc->value))
+ return scope.engine->throwTypeError();
+ }
+ if (attributes.isAccessor() && targetDesc->value.isUndefined()) {
+ if (!trapResult->isUndefined())
+ return scope.engine->throwTypeError();
+ }
+ }
+ return trapResult->asReturnedValue();
+}
+
+bool ProxyObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedValue trap(scope, handler->get(scope.engine->id_set()));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->put(id, value, receiver);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 4, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.toStringOrSymbol(scope.engine);
+ cdata.args[2] = value;
+ cdata.args[3] = *receiver;
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->toBoolean())
+ return false;
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
+ if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
+ if (attributes.isData() && !attributes.isWritable()) {
+ if (!value.sameValue(targetDesc->value))
+ return scope.engine->throwTypeError();
+ }
+ if (attributes.isAccessor() && targetDesc->set.isUndefined())
+ return scope.engine->throwTypeError();
+ }
+ return true;
+}
+
+bool ProxyObject::virtualDeleteProperty(Managed *m, PropertyKey id)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString deleteProp(scope, scope.engine->newString(QStringLiteral("deleteProperty")));
+ ScopedValue trap(scope, handler->get(deleteProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->deleteProperty(id);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 3, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.toStringOrSymbol(scope.engine);
+ cdata.args[2] = o->d(); // ### fix receiver handling
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->toBoolean())
+ return false;
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
+ if (attributes == Attr_Invalid)
+ return true;
+ if (!attributes.isConfigurable())
+ return scope.engine->throwTypeError();
+ return true;
+}
+
+bool ProxyObject::virtualHasProperty(const Managed *m, PropertyKey id)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString hasProp(scope, scope.engine->newString(QStringLiteral("has")));
+ ScopedValue trap(scope, handler->get(hasProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->hasProperty(id);
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 2, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.isArrayIndex() ? Primitive::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (!result) {
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
+ if (attributes != Attr_Invalid) {
+ if (!attributes.isConfigurable() || !target->isExtensible())
+ return scope.engine->throwTypeError();
+ }
+ }
+ return result;
+}
+
+PropertyAttributes ProxyObject::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString deleteProp(scope, scope.engine->newString(QStringLiteral("getOwnPropertyDescriptor")));
+ ScopedValue trap(scope, handler->get(deleteProp));
+ if (scope.hasException())
+ return Attr_Invalid;
+ if (trap->isNullOrUndefined())
+ return target->getOwnProperty(id, p);
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+
+ JSCallData cdata(scope, 2, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.isArrayIndex() ? Primitive::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->isObject() && !trapResult->isUndefined()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes targetAttributes = target->getOwnProperty(id, targetDesc);
+ if (trapResult->isUndefined()) {
+ p->value = Encode::undefined();
+ if (targetAttributes == Attr_Invalid) {
+ p->value = Encode::undefined();
+ return Attr_Invalid;
+ }
+ if (!targetAttributes.isConfigurable() || !target->isExtensible()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+ return Attr_Invalid;
+ }
+
+ //bool extensibleTarget = target->isExtensible();
+ ScopedProperty resultDesc(scope);
+ PropertyAttributes resultAttributes;
+ ObjectPrototype::toPropertyDescriptor(scope.engine, trapResult, resultDesc, &resultAttributes);
+ resultDesc->fullyPopulated(&resultAttributes);
+
+ // ###
+ //Let valid be IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc).
+ //If valid is false, throw a TypeError exception.
+
+ if (!resultAttributes.isConfigurable()) {
+ if (targetAttributes == Attr_Invalid || !targetAttributes.isConfigurable()) {
+ scope.engine->throwTypeError();
+ return Attr_Invalid;
+ }
+ }
+
+ p->value = resultDesc->value;
+ p->set = resultDesc->set;
+ return resultAttributes;
+}
+
+bool ProxyObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString prop(scope, scope.engine->newString(QStringLiteral("defineProperty")));
+ ScopedValue trap(scope, handler->get(prop));
+ if (scope.hasException())
+ return false;
+ if (trap->isNullOrUndefined())
+ return target->defineOwnProperty(id, p, attrs);
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ JSCallData cdata(scope, 3, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = id.isArrayIndex() ? Primitive::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+ cdata.args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs);
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (!result)
+ return false;
+
+ ScopedProperty targetDesc(scope);
+ PropertyAttributes targetAttributes = target->getOwnProperty(id, targetDesc);
+ bool extensibleTarget = target->isExtensible();
+ bool settingConfigFalse = attrs.hasConfigurable() && !attrs.isConfigurable();
+ if (targetAttributes == Attr_Invalid) {
+ if (!extensibleTarget || settingConfigFalse) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ } else {
+ // ###
+ // if IsCompatiblePropertyDescriptor(extensibleTarget, Desc, targetDesc) is false throw a type error.
+ if (settingConfigFalse && targetAttributes.isConfigurable()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ProxyObject::virtualIsExtensible(const Managed *m)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString hasProp(scope, scope.engine->newString(QStringLiteral("isExtensible")));
+ ScopedValue trap(scope, handler->get(hasProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->isExtensible();
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 1, nullptr, handler);
+ cdata.args[0] = target;
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (result != target->isExtensible()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ return result;
+}
+
+bool ProxyObject::virtualPreventExtensions(Managed *m)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString hasProp(scope, scope.engine->newString(QStringLiteral("preventExtensions")));
+ ScopedValue trap(scope, handler->get(hasProp));
+ if (scope.hasException())
+ return Encode::undefined();
+ if (trap->isNullOrUndefined())
+ return target->preventExtensions();
+ if (!trap->isFunctionObject())
+ return scope.engine->throwTypeError();
+
+ JSCallData cdata(scope, 1, nullptr, handler);
+ cdata.args[0] = target;
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (result && target->isExtensible()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ return result;
+}
+
+Heap::Object *ProxyObject::virtualGetPrototypeOf(const Managed *m)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString name(scope, scope.engine->newString(QStringLiteral("getPrototypeOf")));
+ ScopedValue trap(scope, handler->get(name));
+ if (scope.hasException())
+ return nullptr;
+ if (trap->isNullOrUndefined())
+ return target->getPrototypeOf();
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+
+ JSCallData cdata(scope, 1, nullptr, handler);
+ cdata.args[0] = target;
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ if (!trapResult->isNull() && !trapResult->isObject()) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+ Heap::Object *proto = trapResult->isNull() ? nullptr : static_cast<Heap::Object *>(trapResult->heapObject());
+ if (!target->isExtensible()) {
+ Heap::Object *targetProto = target->getPrototypeOf();
+ if (proto != targetProto) {
+ scope.engine->throwTypeError();
+ return nullptr;
+ }
+ }
+ return proto;
+}
+
+bool ProxyObject::virtualSetPrototypeOf(Managed *m, const Object *p)
+{
+ Scope scope(m);
+ const ProxyObject *o = static_cast<const ProxyObject *>(m);
+ if (!o->d()->handler) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ ScopedObject target(scope, o->d()->target);
+ Q_ASSERT(target);
+ ScopedObject handler(scope, o->d()->handler);
+ ScopedString name(scope, scope.engine->newString(QStringLiteral("setPrototypeOf")));
+ ScopedValue trap(scope, handler->get(name));
+ if (scope.hasException())
+ return false;
+ if (trap->isNullOrUndefined())
+ return target->setPrototypeOf(p);
+ if (!trap->isFunctionObject()) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+
+ JSCallData cdata(scope, 2, nullptr, handler);
+ cdata.args[0] = target;
+ cdata.args[1] = p ? p->asReturnedValue() : Encode::null();
+
+ ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
+ bool result = trapResult->toBoolean();
+ if (!result)
+ return false;
+ if (!target->isExtensible()) {
+ Heap::Object *targetProto = target->getPrototypeOf();
+ if (p->d() != targetProto) {
+ scope.engine->throwTypeError();
+ return false;
+ }
+ }
+ return true;
+}
+
+//ReturnedValue ProxyObject::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+//{
+
+//}
+
+//ReturnedValue ProxyObject::call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+//{
+
+//}
+
+DEFINE_OBJECT_VTABLE(Proxy);
+
+void Heap::Proxy::init(QV4::ExecutionContext *ctx)
+{
+ Heap::FunctionObject::init(ctx, QStringLiteral("Proxy"));
+
+ Scope scope(ctx);
+ Scoped<QV4::Proxy> ctor(scope, this);
+ ctor->defineDefaultProperty(QStringLiteral("revocable"), QV4::Proxy::method_revocable, 2);
+ ctor->defineReadonlyConfigurableProperty(scope.engine->id_length(), Primitive::fromInt32(2));
+}
+
+ReturnedValue Proxy::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+{
+ Scope scope(f);
+ if (argc < 2 || !argv[0].isObject() || !argv[1].isObject())
+ return scope.engine->throwTypeError();
+
+ const Object *target = static_cast<const Object *>(argv);
+ const Object *handler = static_cast<const Object *>(argv + 1);
+ if (const ProxyObject *ptarget = target->as<ProxyObject>())
+ if (!ptarget->d()->handler)
+ return scope.engine->throwTypeError();
+ if (const ProxyObject *phandler = handler->as<ProxyObject>())
+ if (!phandler->d()->handler)
+ return scope.engine->throwTypeError();
+
+ ScopedObject o(scope, scope.engine->memoryManager->allocate<ProxyObject>(target, handler));
+ return o->asReturnedValue();
+}
+
+ReturnedValue Proxy::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
+{
+ return f->engine()->throwTypeError();
+}
+
+ReturnedValue Proxy::method_revocable(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ ScopedObject proxy(scope, Proxy::virtualCallAsConstructor(f, argv, argc, f));
+ if (scope.hasException())
+ return Encode::undefined();
+
+ ScopedString revoke(scope, scope.engine->newString(QStringLiteral("revoke")));
+ ScopedFunctionObject revoker(scope, createBuiltinFunction(scope.engine, revoke, method_revoke, 0));
+ revoker->defineDefaultProperty(scope.engine->symbol_revokableProxy(), proxy);
+
+ ScopedObject o(scope, scope.engine->newObject());
+ ScopedString p(scope, scope.engine->newString(QStringLiteral("proxy")));
+ o->defineDefaultProperty(p, proxy);
+ o->defineDefaultProperty(revoke, revoker);
+ return o->asReturnedValue();
+}
+
+ReturnedValue Proxy::method_revoke(const FunctionObject *f, const Value *, const Value *, int)
+{
+ Scope scope(f);
+ Scoped<ProxyObject> proxy(scope, f->get(scope.engine->symbol_revokableProxy()));
+ Q_ASSERT(proxy);
+
+ proxy->d()->target.set(scope.engine, nullptr);
+ proxy->d()->handler.set(scope.engine, nullptr);
+ return Encode::undefined();
+}
diff --git a/src/qml/jsruntime/qv4proxy_p.h b/src/qml/jsruntime/qv4proxy_p.h
new file mode 100644
index 0000000000..4d631e882c
--- /dev/null
+++ b/src/qml/jsruntime/qv4proxy_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4PROXY_P_H
+#define QV4PROXY_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 "qv4object_p.h"
+#include "qv4functionobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Heap {
+
+#define ProxyObjectMembers(class, Member) \
+ Member(class, Pointer, Object *, target) \
+ Member(class, Pointer, Object *, handler)
+
+DECLARE_HEAP_OBJECT(ProxyObject, Object) {
+ DECLARE_MARKOBJECTS(ProxyObject)
+
+ void init(const QV4::Object *target, const QV4::Object *handler);
+};
+
+#define ProxyMembers(class, Member) \
+ Member(class, Pointer, Symbol *, revokableProxySymbol) \
+
+DECLARE_HEAP_OBJECT(Proxy, FunctionObject) {
+ DECLARE_MARKOBJECTS(Proxy)
+
+ void init(QV4::ExecutionContext *ctx);
+};
+
+}
+
+struct ProxyObject: Object {
+ V4_OBJECT2(ProxyObject, Object)
+ Q_MANAGED_TYPE(ProxyObject)
+ V4_INTERNALCLASS(ProxyObject)
+
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static bool virtualDeleteProperty(Managed *m, PropertyKey id);
+ static bool virtualHasProperty(const Managed *m, PropertyKey id);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs);
+ static bool virtualIsExtensible(const Managed *m);
+ static bool virtualPreventExtensions(Managed *);
+ static Heap::Object *virtualGetPrototypeOf(const Managed *);
+ static bool virtualSetPrototypeOf(Managed *, const Object *);
+
+ // those might require a second proxy object that derives from FunctionObject...
+// static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+// static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct Proxy : FunctionObject
+{
+ V4_OBJECT2(Proxy, FunctionObject)
+
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_revocable(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_revoke(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4ECMAOBJECTS_P_H
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 040f060476..dc69016559 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -78,30 +78,25 @@ void Heap::QQmlContextWrapper::destroy()
Object::destroy();
}
-ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlContextWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlContextWrapper>());
+
+ if (!id.isString())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
const QQmlContextWrapper *resource = static_cast<const QQmlContextWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
- // In V8 the JS global object would come _before_ the QML global object,
- // so simulate that here.
- bool hasProp;
- QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp));
- if (hasProp) {
- if (hasProperty)
- *hasProperty = hasProp;
- return result->asReturnedValue();
- }
-
if (resource->d()->isNullWrapper)
- return Object::get(m, name, hasProperty);
+ return Object::virtualGet(m, id, receiver, hasProperty);
if (v4->callingQmlContext() != *resource->d()->context)
- return Object::get(m, name, hasProperty);
+ return Object::virtualGet(m, id, receiver, hasProperty);
- result = Object::get(m, name, &hasProp);
+ bool hasProp = false;
+ ScopedValue result(scope, Object::virtualGet(m, id, receiver, &hasProp));
if (hasProp) {
if (hasProperty)
*hasProperty = hasProp;
@@ -129,6 +124,7 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
QObject *scopeObject = resource->getScopeObject();
+ ScopedString name(scope, id.asStringOrSymbol());
if (context->imports && name->startsWithUpper()) {
// Search for attached properties, enums and imported scripts
QQmlTypeNameCache::Result r = context->imports->query(name, QQmlImport::AllowRecursion);
@@ -139,7 +135,7 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
if (r.scriptIndex != -1) {
QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
if (scripts)
- return scripts->getIndexed(r.scriptIndex);
+ return scripts->get(r.scriptIndex);
return QV4::Encode::null();
} else if (r.type.isValid()) {
return QQmlTypeWrapper::create(v4, scopeObject, r.type);
@@ -219,14 +215,27 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
context = context->parent;
}
+ // Do a lookup in the global object here to avoid expressionContext->unresolvedNames becoming
+ // true if we access properties of the global object.
+ result = v4->globalObject->get(name, &hasProp);
+ if (hasProp) {
+ if (hasProperty)
+ *hasProperty = hasProp;
+ return result->asReturnedValue();
+ }
+
expressionContext->unresolvedNames = true;
return Encode::undefined();
}
-bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
Q_ASSERT(m->as<QQmlContextWrapper>());
+
+ if (id.isSymbol() || id.isArrayIndex())
+ return Object::virtualPut(m, id, value, receiver);
+
QQmlContextWrapper *resource = static_cast<QQmlContextWrapper *>(m);
ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
@@ -234,20 +243,20 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
return false;
QV4::Scoped<QQmlContextWrapper> wrapper(scope, resource);
- uint member = wrapper->internalClass()->find(name);
+ uint member = wrapper->internalClass()->find(id);
if (member < UINT_MAX)
return wrapper->putValue(member, value);
if (wrapper->d()->isNullWrapper) {
if (wrapper && wrapper->d()->readOnly) {
- QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
+ QString error = QLatin1String("Invalid write to global property \"") + id.toQString() +
QLatin1Char('"');
ScopedString e(scope, v4->newString(error));
v4->throwError(e);
return false;
}
- return Object::put(m, name, value);
+ return Object::virtualPut(m, id, value, receiver);
}
// It's possible we could delay the calculation of the "actual" context (in the case
@@ -261,6 +270,7 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
// See QV8ContextWrapper::Getter for resolution order
QObject *scopeObject = wrapper->getScopeObject();
+ ScopedString name(scope, id.asStringOrSymbol());
while (context) {
const QV4::IdentifierHash &properties = context->propertyNames();
@@ -291,7 +301,7 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
return false;
}
- return Object::put(m, name, value);
+ return Object::virtualPut(m, id, value, receiver);
}
void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml)
@@ -312,7 +322,7 @@ Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, cons
context->isInternal = true;
context->isJSContext = true;
- Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)nullptr));
+ Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, (QObject*)nullptr));
qml->d()->isNullWrapper = true;
qml->setReadOnly(false);
@@ -330,7 +340,7 @@ Heap::QmlContext *QmlContext::create(ExecutionContext *parent, QQmlContextData *
{
Scope scope(parent);
- Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, scopeObject));
+ Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, scopeObject));
Heap::QmlContext *c = scope.engine->memoryManager->alloc<QmlContext>(parent, qml);
Q_ASSERT(c->vtable() == staticVTable());
return c;
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 647bef7fc1..b9061a3f58 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -98,8 +98,8 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
void setReadOnly(bool b) { d()->readOnly = b; }
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index d63d42478a..a17de5d94d 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -56,7 +56,11 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4runtime_p.h>
#include <private/qv4variantobject_p.h>
+
+#if QT_CONFIG(qml_sequence_object)
#include <private/qv4sequenceobject_p.h>
+#endif
+
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
@@ -181,11 +185,13 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType()))
return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, property.propType());
} else {
+#if QT_CONFIG(qml_sequence_object)
// see if it's a sequence type
bool succeeded = false;
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType(), object, property.coreIndex(), &succeeded));
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType(), object, property.coreIndex(), !property.isWritable(), &succeeded));
if (succeeded)
return retn->asReturnedValue();
+#endif
}
if (property.propType() == QMetaType::UnknownType) {
@@ -242,7 +248,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
return QV4::QObjectMethod::create(global, object, property->coreIndex());
} else if (property->isSignalHandler()) {
QmlSignalHandler::initProto(engine);
- return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue();
+ return engine->memoryManager->allocate<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue();
} else {
ExecutionContext *global = engine->rootContext();
return QV4::QObjectMethod::create(global, object, property->coreIndex());
@@ -308,7 +314,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
}
}
}
- return QV4::Object::get(this, name, hasProperty);
+ return QV4::Object::virtualGet(this, name->propertyKey(), this, hasProperty);
}
QQmlData *ddata = QQmlData::get(d()->object(), false);
@@ -661,7 +667,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int p
return setProperty(engine, object, property, value);
}
-bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
+bool QObjectWrapper::virtualIsEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QObjectWrapper>());
QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a);
@@ -684,60 +690,77 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
return result;
}
}
- return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue();
+ return (engine->memoryManager->allocate<QV4::QObjectWrapper>(object))->asReturnedValue();
}
-QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
+ if (!id.isString())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ Scope scope(that);
+ ScopedString n(scope, id.asStringOrSymbol());
QQmlContextData *qmlContext = that->engine()->callingQmlContext();
- return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
+ return that->getQmlProperty(qmlContext, n, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
-bool QObjectWrapper::put(Managed *m, String *name, const Value &value)
+bool QObjectWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
+ if (!id.isString())
+ return Object::virtualPut(m, id, value, receiver);
+
+ Scope scope(m);
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- ExecutionEngine *v4 = that->engine();
+ ScopedString name(scope, id.asStringOrSymbol());
- if (v4->hasException || QQmlData::wasDeleted(that->d()->object()))
+ if (scope.engine->hasException || QQmlData::wasDeleted(that->d()->object()))
return false;
- QQmlContextData *qmlContext = v4->callingQmlContext();
- if (!setQmlProperty(v4, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
+ QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ if (!setQmlProperty(scope.engine, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object());
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
// as regular JavaScript properties, like on JavaScript objects.
if (ddata && ddata->context) {
QString error = QLatin1String("Cannot assign to non-existent property \"") +
name->toQString() + QLatin1Char('\"');
- v4->throwError(error);
+ scope.engine->throwError(error);
return false;
} else {
- return QV4::Object::put(m, name, value);
+ return QV4::Object::virtualPut(m, id, value, receiver);
}
}
return true;
}
-PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
+PropertyAttributes QObjectWrapper::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
{
- const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
- const QObject *thatObject = that->d()->object();
- if (QQmlData::wasDeleted(thatObject))
- return QV4::Object::query(m, name);
+ if (id.isString()) {
+ QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
+ const QObject *thatObject = that->d()->object();
+ if (!QQmlData::wasDeleted(thatObject)) {
+ Scope scope(m);
+ ScopedString n(scope, id.asStringOrSymbol());
+ QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlPropertyData local;
+ if (that->findProperty(scope.engine, qmlContext, n, IgnoreRevision, &local)
+ || n->equals(scope.engine->id_destroy()) || n->equals(scope.engine->id_toString())) {
+ if (p) {
+ // ### probably not the fastest implementation
+ bool hasProperty;
+ p->value = that->getQmlProperty(qmlContext, n, IgnoreRevision, &hasProperty, /*includeImports*/ true);
+ }
+ return QV4::Attr_Data;
+ }
+ }
+ }
- ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = engine->callingQmlContext();
- QQmlPropertyData local;
- if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local)
- || name->equals(engine->id_destroy()) || name->equals(engine->id_toString()))
- return QV4::Attr_Data;
- else
- return QV4::Object::query(m, name);
+ return QV4::Object::virtualGetOwnProperty(m, id, p);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
@@ -788,7 +811,7 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name
return;
}
}
- QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+ QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
namespace QV4 {
@@ -1619,6 +1642,7 @@ void CallArgument::initAsType(int callType)
}
}
+#if QT_CONFIG(qml_sequence_object)
template <class T, class M>
void CallArgument::fromContainerValue(const QV4::Object *object, int callType, M CallArgument::*member, bool &queryEngine)
{
@@ -1631,6 +1655,7 @@ void CallArgument::fromContainerValue(const QV4::Object *object, int callType, M
}
}
}
+#endif
void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const QV4::Value &value)
{
@@ -1685,7 +1710,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
uint length = array->getLength();
for (uint ii = 0; ii < length; ++ii) {
QObject *o = nullptr;
- qobjectWrapper = array->getIndexed(ii);
+ qobjectWrapper = array->get(ii);
if (!!qobjectWrapper)
o = qobjectWrapper->object();
qlistPtr->append(o);
@@ -1713,6 +1738,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == QMetaType::Void) {
*qvariantPtr = QVariant();
+#if QT_CONFIG(qml_sequence_object)
} else if (callType == qMetaTypeId<std::vector<int>>()
|| callType == qMetaTypeId<std::vector<qreal>>()
|| callType == qMetaTypeId<std::vector<bool>>()
@@ -1740,6 +1766,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
stdVectorQModelIndexPtr = nullptr;
fromContainerValue<std::vector<QModelIndex>>(object, callType, &CallArgument::stdVectorQModelIndexPtr, queryEngine);
}
+#endif
} else {
queryEngine = true;
}
@@ -1833,7 +1860,7 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocate<QObjectMethod>(scope));
method->d()->setObject(object);
if (QQmlData *ddata = QQmlData::get(object))
@@ -1846,7 +1873,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocate<QObjectMethod>(scope));
method->d()->setPropertyCache(valueType->d()->propertyCache());
method->d()->index = index;
method->d()->valueTypeWrapper.set(valueScope.engine, valueType->d());
@@ -1906,7 +1933,7 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionEngine *engine, c
return Encode::undefined();
}
-ReturnedValue QObjectMethod::call(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue QObjectMethod::virtualCall(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc)
{
const QObjectMethod *This = static_cast<const QObjectMethod*>(m);
return This->callInternal(thisObject, argv, argc);
@@ -2019,7 +2046,7 @@ void Heap::QMetaObjectWrapper::ensureConstructorsCache() {
ReturnedValue QMetaObjectWrapper::create(ExecutionEngine *engine, const QMetaObject* metaObject) {
QV4::Scope scope(engine);
- Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocObject<QV4::QMetaObjectWrapper>(metaObject)->asReturnedValue());
+ Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocate<QV4::QMetaObjectWrapper>(metaObject)->asReturnedValue());
mo->init(engine);
return mo->asReturnedValue();
}
@@ -2037,7 +2064,7 @@ void QMetaObjectWrapper::init(ExecutionEngine *) {
}
}
-ReturnedValue QMetaObjectWrapper::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue QMetaObjectWrapper::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
const QMetaObjectWrapper *This = static_cast<const QMetaObjectWrapper*>(f);
return This->constructInternal(argv, argc);
@@ -2068,7 +2095,7 @@ ReturnedValue QMetaObjectWrapper::constructInternal(const Value *argv, int argc)
}
Scoped<QMetaObjectWrapper> metaObject(scope, this);
object->defineDefaultProperty(v4->id_constructor(), metaObject);
- object->setPrototype(const_cast<QMetaObjectWrapper*>(this));
+ object->setPrototypeOf(const_cast<QMetaObjectWrapper*>(this));
return object.asReturnedValue();
}
@@ -2143,7 +2170,7 @@ ReturnedValue QMetaObjectWrapper::callOverloadedConstructor(QV4::ExecutionEngine
}
}
-bool QMetaObjectWrapper::isEqualTo(Managed *a, Managed *b)
+bool QMetaObjectWrapper::virtualIsEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QMetaObjectWrapper>());
QMetaObjectWrapper *aMetaObject = a->as<QMetaObjectWrapper>();
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 1455acc1b3..7843289d33 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -183,7 +183,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
void destroyObject(bool lastCall);
protected:
- static bool isEqualTo(Managed *that, Managed *o);
+ static bool virtualIsEqualTo(Managed *that, Managed *o);
static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired = true);
static void setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value);
@@ -193,10 +193,10 @@ protected:
static QQmlPropertyData *findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local);
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
- static PropertyAttributes query(const Managed *, String *name);
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_connect(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_disconnect(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
@@ -237,7 +237,7 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
QV4::ReturnedValue method_toString(QV4::ExecutionEngine *engine) const;
QV4::ReturnedValue method_destroy(QV4::ExecutionEngine *ctx, const Value *args, int argc) const;
- static ReturnedValue call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCall(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
ReturnedValue callInternal(const Value *thisObject, const Value *argv, int argc) const;
@@ -251,11 +251,12 @@ struct Q_QML_EXPORT QMetaObjectWrapper : public QV4::FunctionObject
V4_NEEDS_DESTROY
static ReturnedValue create(ExecutionEngine *engine, const QMetaObject* metaObject);
- static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc);
- static bool isEqualTo(Managed *a, Managed *b);
-
const QMetaObject *metaObject() const { return d()->metaObject; }
+protected:
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
+ static bool virtualIsEqualTo(Managed *a, Managed *b);
+
private:
void init(ExecutionEngine *engine);
ReturnedValue constructInternal(const Value *argv, int argc) const;
diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp
new file mode 100644
index 0000000000..20ea39d4e5
--- /dev/null
+++ b/src/qml/jsruntime/qv4reflect.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4reflect_p.h"
+#include "qv4symbol_p.h"
+#include "qv4runtimeapi_p.h"
+#include "qv4objectproto_p.h"
+#include "qv4propertykey_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(Reflect);
+
+void Heap::Reflect::init()
+{
+ Object::init();
+ Scope scope(internalClass->engine);
+ ScopedObject r(scope, this);
+
+ r->defineDefaultProperty(QStringLiteral("apply"), QV4::Reflect::method_apply, 3);
+ r->defineDefaultProperty(QStringLiteral("construct"), QV4::Reflect::method_construct, 2);
+ r->defineDefaultProperty(QStringLiteral("defineProperty"), QV4::Reflect::method_defineProperty, 3);
+ r->defineDefaultProperty(QStringLiteral("deleteProperty"), QV4::Reflect::method_deleteProperty, 2);
+ r->defineDefaultProperty(QStringLiteral("get"), QV4::Reflect::method_get, 2);
+ r->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), QV4::Reflect::method_getOwnPropertyDescriptor, 2);
+ r->defineDefaultProperty(QStringLiteral("getPrototypeOf"), QV4::Reflect::method_getPrototypeOf, 1);
+ r->defineDefaultProperty(QStringLiteral("has"), QV4::Reflect::method_has, 2);
+ r->defineDefaultProperty(QStringLiteral("isExtensible"), QV4::Reflect::method_isExtensible, 1);
+ r->defineDefaultProperty(QStringLiteral("ownKeys"), QV4::Reflect::method_ownKeys, 1);
+ r->defineDefaultProperty(QStringLiteral("preventExtensions"), QV4::Reflect::method_preventExtensions, 1);
+ r->defineDefaultProperty(QStringLiteral("set"), QV4::Reflect::method_set, 3);
+ r->defineDefaultProperty(QStringLiteral("setPrototypeOf"), QV4::Reflect::method_setPrototypeOf, 2);
+}
+
+struct CallArgs {
+ Value *argv;
+ int argc;
+};
+
+static CallArgs createListFromArrayLike(Scope &scope, const Object *o)
+{
+ int len = o->getLength();
+ Value *arguments = scope.alloc(len);
+
+ for (int i = 0; i < len; ++i) {
+ arguments[i] = o->get(i);
+ if (scope.hasException())
+ return { nullptr, 0 };
+ }
+ return { arguments, len };
+}
+
+ReturnedValue Reflect::method_apply(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (argc < 3 || !argv[0].isFunctionObject() || !argv[2].isObject())
+ return scope.engine->throwTypeError();
+
+ const Object *o = static_cast<const Object *>(argv + 2);
+ CallArgs arguments = createListFromArrayLike(scope, o);
+ if (scope.hasException())
+ return Encode::undefined();
+
+ return static_cast<const FunctionObject &>(argv[0]).call(&argv[1], arguments.argv, arguments.argc);
+}
+
+ReturnedValue Reflect::method_construct(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (argc < 2 || !argv[0].isFunctionObject() || !argv[1].isObject())
+ return scope.engine->throwTypeError();
+
+ const Object *o = static_cast<const Object *>(argv + 1);
+ CallArgs arguments = createListFromArrayLike(scope, o);
+ if (scope.hasException())
+ return Encode::undefined();
+
+ return static_cast<const FunctionObject &>(argv[0]).callAsConstructor(arguments.argv, arguments.argc);
+}
+
+ReturnedValue Reflect::method_defineProperty(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (!argc || !argv[0].isObject())
+ return scope.engine->throwTypeError();
+
+ ScopedObject O(scope, argv[0]);
+ ScopedPropertyKey name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
+ if (scope.engine->hasException)
+ return QV4::Encode::undefined();
+
+ ScopedValue attributes(scope, argc > 2 ? argv[2] : Primitive::undefinedValue());
+ ScopedProperty pd(scope);
+ PropertyAttributes attrs;
+ ObjectPrototype::toPropertyDescriptor(scope.engine, attributes, pd, &attrs);
+ if (scope.engine->hasException)
+ return QV4::Encode::undefined();
+
+ bool result = O->defineOwnProperty(name, pd, attrs);
+
+ return Encode(result);
+}
+
+ReturnedValue Reflect::method_deleteProperty(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ ExecutionEngine *e = f->engine();
+ if (!argc || !argv[0].isObject())
+ return e->throwTypeError();
+
+ bool result = Runtime::method_deleteProperty(e, argv[0], argc > 1 ? argv[1] : Primitive::undefinedValue());
+ return Encode(result);
+}
+
+ReturnedValue Reflect::method_get(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (!argc || !argv[0].isObject())
+ return scope.engine->throwTypeError();
+
+ ScopedObject o(scope, static_cast<const Object *>(argv));
+ Value undef = Primitive::undefinedValue();
+ const Value *index = argc > 1 ? &argv[1] : &undef;
+ ScopedPropertyKey name(scope, index->toPropertyKey(scope.engine));
+ if (scope.hasException())
+ return Encode::undefined();
+ ScopedValue receiver(scope, argc > 2 ? argv[2] : *o);
+
+ return Encode(o->get(name, receiver));
+}
+
+ReturnedValue Reflect::method_getOwnPropertyDescriptor(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ if (!argc || !argv[0].isObject())
+ return f->engine()->throwTypeError();
+
+ return ObjectPrototype::method_getOwnPropertyDescriptor(f, thisObject, argv, argc);
+}
+
+ReturnedValue Reflect::method_getPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ if (!argc || !argv[0].isObject())
+ return f->engine()->throwTypeError();
+
+ const Object *o = static_cast<const Object *>(argv);
+ Heap::Object *p = o->getPrototypeOf();
+ return (p ? p->asReturnedValue() : Encode::null());
+}
+
+ReturnedValue Reflect::method_has(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (!argc || !argv[0].isObject())
+ return scope.engine->throwTypeError();
+
+ ScopedObject o(scope, static_cast<const Object *>(argv));
+ Value undef = Primitive::undefinedValue();
+ const Value *index = argc > 1 ? &argv[1] : &undef;
+
+ ScopedPropertyKey name(scope, index->toPropertyKey(scope.engine));
+ if (scope.engine->hasException)
+ return false;
+
+ bool hasProperty = false;
+ (void) o->get(name, nullptr, &hasProperty);
+ return Encode(hasProperty);
+}
+
+ReturnedValue Reflect::method_isExtensible(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ if (!argc || !argv[0].isObject())
+ return f->engine()->throwTypeError();
+
+ const Object *o = static_cast<const Object *>(argv);
+ return Encode(o->isExtensible());
+}
+
+
+ReturnedValue Reflect::method_ownKeys(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ if (!argc || !argv[0].isObject())
+ return f->engine()->throwTypeError();
+
+ return ObjectPrototype::method_getOwnPropertyNames(f, thisObject, argv, argc);
+}
+
+ReturnedValue Reflect::method_preventExtensions(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (!argc || !argv[0].isObject())
+ return scope.engine->throwTypeError();
+
+ ScopedObject o(scope, static_cast<const Object *>(argv));
+ return Encode(o->preventExtensions());
+}
+
+ReturnedValue Reflect::method_set(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ if (!argc || !argv[0].isObject())
+ return scope.engine->throwTypeError();
+
+ ScopedObject o(scope, static_cast<const Object *>(argv));
+ Value undef = Primitive::undefinedValue();
+ const Value *index = argc > 1 ? &argv[1] : &undef;
+ const Value &val = argc > 2 ? argv[2] : undef;
+ ScopedValue receiver(scope, argc >3 ? argv[3] : argv[0]);
+
+ ScopedPropertyKey propertyKey(scope, index->toPropertyKey(scope.engine));
+ if (scope.engine->hasException)
+ return false;
+ bool result = o->put(propertyKey, val, receiver);
+ return Encode(result);
+}
+
+ReturnedValue Reflect::method_setPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ if (argc < 2 || !argv[0].isObject() || (!argv[1].isNull() && !argv[1].isObject()))
+ return f->engine()->throwTypeError();
+
+ Scope scope(f);
+ ScopedObject o(scope, static_cast<const Object *>(argv));
+ const Object *proto = argv[1].isNull() ? nullptr : static_cast<const Object *>(argv + 1);
+ return Encode(o->setPrototypeOf(proto));
+}
diff --git a/src/qml/jsruntime/qv4reflect_p.h b/src/qml/jsruntime/qv4reflect_p.h
new file mode 100644
index 0000000000..d480e1d914
--- /dev/null
+++ b/src/qml/jsruntime/qv4reflect_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4REFLECT_H
+#define QV4REFLECT_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 "qv4object_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Heap {
+
+struct Reflect : Object {
+ void init();
+};
+
+}
+
+struct Reflect : Object {
+ V4_OBJECT2(Reflect, Object)
+
+ static ReturnedValue method_apply(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_construct(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_defineProperty(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_deleteProperty(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_get(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getOwnPropertyDescriptor(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_getPrototypeOf(const FunctionObject *, const Value *, const Value *argv, int argc);
+ static ReturnedValue method_has(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_isExtensible(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_ownKeys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_preventExtensions(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_set(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_setPrototypeOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 000e2c3a7e..8429b96baa 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -45,10 +45,6 @@
#include "qv4scopedvalue_p.h"
#include "qv4jscall_p.h"
-#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
#include "private/qlocale_tools_p.h"
#include <QtCore/QDebug>
@@ -214,7 +210,7 @@ void Heap::RegExpCtor::clearLastMatch()
lastMatchEnd = 0;
}
-ReturnedValue RegExpCtor::callAsConstructor(const FunctionObject *fo, const Value *argv, int argc)
+ReturnedValue RegExpCtor::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *)
{
Scope scope(fo->engine());
ScopedValue r(scope, argc ? argv[0] : Primitive::undefinedValue());
@@ -263,14 +259,14 @@ ReturnedValue RegExpCtor::callAsConstructor(const FunctionObject *fo, const Valu
return Encode(scope.engine->newRegExpObject(regexp));
}
-ReturnedValue RegExpCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue RegExpCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
if (argc > 0 && argv[0].as<RegExpObject>()) {
if (argc == 1 || argv[1].isUndefined())
return Encode(argv[0]);
}
- return callAsConstructor(f, argv, argc);
+ return virtualCallAsConstructor(f, argv, argc, f);
}
void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
@@ -280,7 +276,8 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
ScopedObject ctor(scope, constructor);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(2));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(2));
+ ctor->addSymbolSpecies();
// Properties deprecated in the spec but required by "the web" :(
ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, nullptr);
@@ -387,7 +384,7 @@ ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value
}
// fill in result data
- ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses[EngineBase::Class_RegExpExecArray], scope.engine->arrayPrototype()));
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses(EngineBase::Class_RegExpExecArray)));
int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
@@ -442,12 +439,12 @@ ReturnedValue RegExpPrototype::method_compile(const FunctionObject *b, const Val
return Encode::undefined();
}
-template <int index>
+template <uint index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(const FunctionObject *b, const Value *, const Value *, int)
{
Scope scope(b);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch());
- ScopedValue res(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
+ ScopedValue res(scope, lastMatch ? lastMatch->get(index) : Encode::undefined());
if (res->isUndefined())
res = scope.engine->newString();
return res->asReturnedValue();
@@ -457,7 +454,7 @@ ReturnedValue RegExpPrototype::method_get_lastParen(const FunctionObject *b, con
{
Scope scope(b);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch());
- ScopedValue res(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
+ ScopedValue res(scope, lastMatch ? lastMatch->get(lastMatch->getLength() - 1) : Encode::undefined());
if (res->isUndefined())
res = scope.engine->newString();
return res->asReturnedValue();
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 181628241b..0d4fe760eb 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -129,11 +129,11 @@ struct RegExpObject: Object {
void initProperties();
int lastIndex() const {
- Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()));
+ Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()->propertyKey()));
return propertyData(Index_LastIndex)->toInt32();
}
void setLastIndex(int index) {
- Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()));
+ Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()->propertyKey()));
return setProperty(Index_LastIndex, Primitive::fromInt32(index));
}
@@ -152,8 +152,8 @@ struct RegExpCtor: FunctionObject
int lastMatchStart() { return d()->lastMatchStart; }
int lastMatchEnd() { return d()->lastMatchEnd; }
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct RegExpPrototype: RegExpObject
@@ -165,7 +165,7 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_compile(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- template <int index>
+ template <uint index>
static ReturnedValue method_get_lastMatch_n(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_lastParen(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_input(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 9729228511..f387285e37 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -61,6 +61,8 @@
#include <private/qqmlengine_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include "qv4qobjectwrapper_p.h"
+#include "qv4symbol_p.h"
+#include "qv4generatorobject_p.h"
#include <private/qv8engine_p.h>
#endif
@@ -314,37 +316,23 @@ ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId)
QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId];
Q_ASSERT(clos);
ExecutionContext *current = static_cast<ExecutionContext *>(&engine->currentStackFrame->jsFrame->context);
+ if (clos->isGenerator())
+ return GeneratorFunction::create(current, clos)->asReturnedValue();
return FunctionObject::createScriptFunction(current, clos)->asReturnedValue();
}
-bool Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, const Value &index)
+bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base, const Value &index)
{
Scope scope(engine);
- ScopedObject o(scope, base);
- if (o) {
- uint n = index.asArrayIndex();
- if (n < UINT_MAX)
- return o->deleteIndexedProperty(n);
- }
-
- ScopedString name(scope, index.toString(engine));
- return method_deleteMemberString(engine, base, name);
-}
-
-bool Runtime::method_deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex)
-{
- Scope scope(engine);
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- return method_deleteMemberString(engine, base, name);
-}
-
-bool Runtime::method_deleteMemberString(ExecutionEngine *engine, const Value &base, String *name)
-{
- Scope scope(engine);
- ScopedObject obj(scope, base.toObject(engine));
+ ScopedObject o(scope, base.toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
- return obj->deleteProperty(name);
+ Q_ASSERT(o);
+
+ ScopedPropertyKey key(scope, index.toPropertyKey(engine));
+ if (engine->hasException)
+ return false;
+ return o->deleteProperty(key);
}
bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex)
@@ -361,8 +349,16 @@ QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Val
if (!rhs)
return engine->throwTypeError();
- // 11.8.6, 7: call "HasInstance", which we term instanceOf, and return the result.
- return rhs->instanceOf(lval);
+ Scope scope(engine);
+ ScopedValue hasInstance(scope, rhs->get(engine->symbol_hasInstance()));
+ if (hasInstance->isUndefined())
+ return rhs->instanceOf(lval);
+ FunctionObject *f = hasInstance->as<FunctionObject>();
+ if (!f)
+ return engine->throwTypeError();
+
+ ScopedValue result(scope, f->call(&rval, &lval, 1));
+ return Encode(result->toBoolean());
}
QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right)
@@ -371,7 +367,7 @@ QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left
if (!ro)
return engine->throwTypeError();
Scope scope(engine);
- ScopedString s(scope, left.toString(engine));
+ ScopedPropertyKey s(scope, left.toPropertyKey(engine));
if (scope.hasException())
return Encode::undefined();
bool r = ro->hasProperty(s);
@@ -408,27 +404,59 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n
ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint)
{
- if (typeHint == PREFERREDTYPE_HINT) {
- if (object->as<DateObject>())
- typeHint = STRING_HINT;
- else
- typeHint = NUMBER_HINT;
+ ExecutionEngine *engine = object->internalClass()->engine;
+ if (engine->hasException)
+ return Encode::undefined();
+
+ String *hint;
+ switch (typeHint) {
+ case STRING_HINT:
+ hint = engine->id_string();
+ break;
+ case NUMBER_HINT:
+ hint = engine->id_number();
+ break;
+ default:
+ hint = engine->id_default();
+ break;
}
- ExecutionEngine *engine = object->internalClass()->engine;
+ Scope scope(engine);
+ ScopedFunctionObject toPrimitive(scope, object->get(engine->symbol_toPrimitive()));
if (engine->hasException)
return Encode::undefined();
+ if (toPrimitive) {
+ ScopedValue result(scope, toPrimitive->call(object, hint, 1));
+ if (engine->hasException)
+ return Encode::undefined();
+ if (!result->isPrimitive())
+ return engine->throwTypeError();
+ return result->asReturnedValue();
+ }
+
+ if (hint == engine->id_default())
+ hint = engine->id_number();
+ return ordinaryToPrimitive(engine, object, hint);
+}
+
+
+ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const Object *object, String *typeHint)
+{
+ Q_ASSERT(!engine->hasException);
String *meth1 = engine->id_toString();
String *meth2 = engine->id_valueOf();
- if (typeHint == NUMBER_HINT)
+ if (typeHint->propertyKey() == engine->id_number()->propertyKey()) {
qSwap(meth1, meth2);
+ } else {
+ Q_ASSERT(typeHint->propertyKey() == engine->id_string()->propertyKey());
+ }
Scope scope(engine);
ScopedValue result(scope);
- ScopedValue conv(scope, object->get(meth1));
+ ScopedValue conv(scope, object->get(meth1));
if (FunctionObject *o = conv->as<FunctionObject>()) {
result = o->call(object, nullptr, 0);
if (result->isPrimitive())
@@ -449,19 +477,22 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH
}
-
Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Value &value)
{
Q_ASSERT(!value.isObject());
switch (value.type()) {
case Value::Undefined_Type:
+ engine->throwTypeError(QLatin1String("Value is undefined and could not be converted to an object"));
+ return nullptr;
case Value::Null_Type:
- engine->throwTypeError();
+ engine->throwTypeError(QLatin1String("Value is null and could not be converted to an object"));
return nullptr;
case Value::Boolean_Type:
return engine->newBooleanObject(value.booleanValue());
case Value::Managed_Type:
- Q_ASSERT(value.isString());
+ Q_ASSERT(value.isStringOrSymbol());
+ if (!value.isString())
+ return engine->newSymbolObject(value.symbolValue());
return engine->newStringObject(value.stringValue());
case Value::Integer_Type:
default: // double
@@ -488,6 +519,10 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, Value val
case Value::Managed_Type: {
if (value.isString())
return static_cast<const String &>(value).d();
+ if (value.isSymbol()) {
+ engine->throwTypeError(QLatin1String("Cannot convert a symbol to a string."));
+ return nullptr;
+ }
value = Primitive::fromReturnedValue(RuntimeHelpers::toPrimitive(value, hint));
Q_ASSERT(value.isPrimitive());
if (value.isString())
@@ -539,14 +574,14 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu
return Encode(x + y);
}
-bool Runtime::method_storeProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
+void Runtime::method_storeProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ QV4::Function *v4Function = engine->currentStackFrame->v4Function;
+ ScopedString name(scope, v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object.toObject(engine));
- if (!o)
- return false;
- return o->put(name, value);
+ if ((!o || !o->put(name, value)) && v4Function->isStrict())
+ engine->throwTypeError();
}
static Q_NEVER_INLINE ReturnedValue getElementIntFallback(ExecutionEngine *engine, const Value &object, uint idx)
@@ -579,12 +614,13 @@ static Q_NEVER_INLINE ReturnedValue getElementIntFallback(ExecutionEngine *engin
return v->asReturnedValue();
}
- return o->getIndexed(idx);
+ return o->get(idx);
}
static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine, const Value &object, const Value &index)
{
- Q_ASSERT(index.asArrayIndex() == UINT_MAX);
+ Q_ASSERT(!index.isPositiveInt());
+
Scope scope(engine);
ScopedObject o(scope, object);
@@ -598,26 +634,18 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine,
Q_ASSERT(!!o); // can't fail as null/undefined is covered above
}
- ScopedString name(scope, index.toString(engine));
+ ScopedPropertyKey name(scope, index.toPropertyKey(engine));
if (scope.hasException())
return Encode::undefined();
return o->get(name);
}
-/* load element:
-
- Managed *m = object.heapObject();
- if (m)
- return m->internalClass->getIndexed(m, index);
- return getIndexedFallback(object, index);
-*/
-
ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index)
{
- uint idx = 0;
- if (index.asArrayIndex(idx)) {
+ if (index.isPositiveInt()) {
+ uint idx = static_cast<uint>(index.int_32());
if (Heap::Base *b = object.heapObject()) {
- if (b->vtable()->isObject) {
+ if (b->internalClass->vtable->isObject) {
Heap::Object *o = static_cast<Heap::Object *>(b);
if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
@@ -640,8 +668,8 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val
if (engine->hasException)
return false;
- uint idx = 0;
- if (index.asArrayIndex(idx)) {
+ if (index.isPositiveInt()) {
+ uint idx = static_cast<uint>(index.int_32());
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->values.size) {
@@ -649,53 +677,136 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val
return true;
}
}
- return o->putIndexed(idx, value);
+ return o->put(idx, value);
}
- ScopedString name(scope, index.toString(engine));
+ ScopedPropertyKey name(scope, index.toPropertyKey(engine));
+ if (engine->hasException)
+ return false;
return o->put(name, value);
}
-bool Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
+void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
- uint idx = 0;
- if (index.asArrayIndex(idx)) {
+ if (index.isPositiveInt()) {
+ uint idx = static_cast<uint>(index.int_32());
if (Heap::Base *b = object.heapObject()) {
- if (b->vtable()->isObject) {
+ if (b->internalClass->vtable->isObject) {
Heap::Object *o = static_cast<Heap::Object *>(b);
if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->values.size) {
s->setData(engine, idx, value);
- return true;
+ return;
}
}
}
}
}
- return setElementFallback(engine, object, index, value);
+ if (!setElementFallback(engine, object, index, value) && engine->currentStackFrame->v4Function->isStrict())
+ engine->throwTypeError();
}
-ReturnedValue Runtime::method_foreachIterator(ExecutionEngine *engine, const Value &in)
+ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &in, int iterator)
{
Scope scope(engine);
ScopedObject o(scope, (Object *)nullptr);
if (!in.isNullOrUndefined())
o = in.toObject(engine);
- return engine->newForEachIteratorObject(o)->asReturnedValue();
+ if (engine->hasException)
+ return Encode::undefined();
+ if (iterator) {
+ if (!o)
+ return engine->throwTypeError();
+ ScopedFunctionObject f(scope, o->get(engine->symbol_iterator()));
+ if (!f)
+ return engine->throwTypeError();
+ JSCallData cData(scope, 0, nullptr, o);
+ ScopedObject it(scope, f->call(cData));
+ if (!it)
+ return engine->throwTypeError();
+ return it->asReturnedValue();
+ }
+ return engine->newForInIteratorObject(o)->asReturnedValue();
}
-ReturnedValue Runtime::method_foreachNextPropertyName(const Value &foreach_iterator)
+ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value &iterator, Value *value)
{
- Q_ASSERT(foreach_iterator.isObject());
+ Q_ASSERT(iterator.isObject());
- ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator.objectValue());
- Q_ASSERT(it->as<ForEachIteratorObject>());
+ Scope scope(engine);
+ ScopedFunctionObject f(scope, static_cast<const Object &>(iterator).get(engine->id_next()));
+ if (!f)
+ return engine->throwTypeError();
+ JSCallData cData(scope, 0, nullptr, &iterator);
+ ScopedObject o(scope, f->call(cData));
+ if (!o)
+ return engine->throwTypeError();
+ ScopedValue d(scope, o->get(engine->id_done()));
+ bool done = d->toBoolean();
+ if (done) {
+ *value = Encode::undefined();
+ } else {
+ *value = o->get(engine->id_value());
+ }
+ return Encode(done);
+}
- return it->nextPropertyName();
+ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value &iterator, const Value &done)
+{
+ Q_ASSERT(iterator.isObject());
+ Q_ASSERT(done.isBoolean());
+ if (done.booleanValue())
+ return Encode::undefined();
+
+ Scope scope(engine);
+ bool hadException = engine->hasException;
+ ScopedValue e(scope);
+ if (hadException) {
+ e = *engine->exceptionValue;
+ engine->hasException = false;
+ }
+ ScopedFunctionObject f(scope, static_cast<const Object &>(iterator).get(engine->id_return()));
+ ScopedObject o(scope);
+ if (f) {
+ JSCallData cData(scope, 0, nullptr, &iterator);
+ o = f->call(cData);
+ }
+ if (hadException || !f) {
+ *engine->exceptionValue = e;
+ engine->hasException = hadException;
+ return Encode::undefined();
+ }
+ if (engine->hasException)
+ return Encode::undefined();
+
+ if (!o)
+ return engine->throwTypeError();
+ return Encode::undefined();
}
+ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, const Value &iterator)
+{
+ Q_ASSERT(iterator.isObject());
+
+ Scope scope(engine);
+ ScopedArrayObject array(scope, engine->newArrayObject());
+ array->arrayCreate();
+ uint index = 0;
+ while (1) {
+ ScopedValue n(scope);
+ ScopedValue done(scope, method_iteratorNext(engine, iterator, n));
+ if (engine->hasException)
+ return Encode::undefined();
+ Q_ASSERT(done->isBoolean());
+ if (done->booleanValue())
+ break;
+ array->arraySet(index, n);
+ ++index;
+ }
+ return array->asReturnedValue();
+}
void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, const Value &value)
{
@@ -745,6 +856,42 @@ ReturnedValue Runtime::method_loadName(ExecutionEngine *engine, int nameIndex)
return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name);
}
+ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const Value &property)
+{
+ Scope scope(engine);
+ ScopedObject base(scope, engine->currentStackFrame->thisObject());
+ if (!base)
+ return engine->throwTypeError();
+ ScopedObject proto(scope, base->getPrototypeOf());
+ if (!proto)
+ return engine->throwTypeError();
+ ScopedPropertyKey key(scope, property.toPropertyKey(engine));
+ if (engine->hasException)
+ return Encode::undefined();
+ return proto->get(key, base);
+}
+
+void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &property, const Value &value)
+{
+ Scope scope(engine);
+ ScopedObject base(scope, engine->currentStackFrame->thisObject());
+ if (!base) {
+ engine->throwTypeError();
+ return;
+ }
+ ScopedObject proto(scope, base->getPrototypeOf());
+ if (!proto) {
+ engine->throwTypeError();
+ return;
+ }
+ ScopedPropertyKey key(scope, property.toPropertyKey(engine));
+ if (engine->hasException)
+ return;
+ bool result = proto->put(key, value, base);
+ if (!result && engine->currentStackFrame->v4Function->isStrict())
+ engine->throwTypeError();
+}
+
#endif // V4_BOOTSTRAP
uint RuntimeHelpers::equalHelper(const Value &x, const Value &y)
@@ -1033,24 +1180,31 @@ ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, V
ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)
{
Scope scope(engine);
+ ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedObject lookupObject(scope, base);
- if (!base->isObject()) {
+ if (!lookupObject) {
Q_ASSERT(!base->isEmpty());
if (base->isNullOrUndefined()) {
QString message = QStringLiteral("Cannot call method '%1' of %2")
- .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(),
- base->toQStringNoThrow());
+ .arg(name->toQString(), base->toQStringNoThrow());
return engine->throwTypeError(message);
}
- ScopedValue thisObject(scope, RuntimeHelpers::convertToObject(engine, *base));
- if (engine->hasException) // type error
- return Encode::undefined();
- base = thisObject;
+ if (base->isManaged()) {
+ Managed *m = static_cast<Managed *>(base);
+ lookupObject = m->internalClass()->prototype;
+ Q_ASSERT(m->internalClass()->prototype);
+ } else {
+ lookupObject = RuntimeHelpers::convertToObject(engine, *base);
+ if (engine->hasException) // type error
+ return Encode::undefined();
+ if (!engine->currentStackFrame->v4Function->isStrict())
+ base = lookupObject;
+ }
}
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(name));
+ ScopedFunctionObject f(scope, static_cast<Object *>(lookupObject)->get(name));
if (!f) {
QString error = QStringLiteral("Property '%1' of object %2 is not a function")
@@ -1080,7 +1234,7 @@ ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base,
ScopedValue thisObject(scope, base->toObject(engine));
base = thisObject;
- ScopedString str(scope, index.toString(engine));
+ ScopedPropertyKey str(scope, index.toPropertyKey(engine));
if (engine->hasException)
return Encode::undefined();
@@ -1130,12 +1284,80 @@ ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engi
return fo->call(qmlContextValue, argv, argc);
}
-ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &function, Value *argv, int argc)
+struct CallArgs {
+ Value *argv;
+ int argc;
+};
+
+static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
+{
+ ScopedValue it(scope);
+ ScopedValue done(scope);
+
+ int argCount = 0;
+
+ Value *v = scope.alloc<Scope::Uninitialized>();
+ Value *arguments = v;
+ for (int i = 0; i < argc; ++i) {
+ if (!argv[i].isEmpty()) {
+ *v = argv[i];
+ ++argCount;
+ v = scope.alloc<Scope::Uninitialized>();
+ continue;
+ }
+ // spread element
+ ++i;
+ it = Runtime::method_getIterator(scope.engine, argv[i], /* ForInIterator */ 1);
+ if (scope.engine->hasException)
+ return { nullptr, 0 };
+ while (1) {
+ done = Runtime::method_iteratorNext(scope.engine, it, v);
+ if (scope.engine->hasException)
+ return { nullptr, 0 };
+ Q_ASSERT(done->isBoolean());
+ if (done->booleanValue())
+ break;
+ ++argCount;
+ v = scope.alloc<Scope::Uninitialized>();
+ }
+ }
+ return { arguments, argCount };
+}
+
+ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc)
+{
+ Q_ASSERT(argc >= 1);
+ if (!function.isFunctionObject())
+ return engine->throwTypeError();
+
+ Scope scope(engine);
+ CallArgs arguments = createSpreadArguments(scope, argv, argc);
+ if (engine->hasException)
+ return Encode::undefined();
+
+ return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc);
+}
+
+ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
{
if (!function.isFunctionObject())
return engine->throwTypeError();
- return static_cast<const FunctionObject &>(function).callAsConstructor(argv, argc);
+ return static_cast<const FunctionObject &>(function).callAsConstructor(argv, argc, &newTarget);
+}
+
+ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
+{
+ Q_UNIMPLEMENTED();
+ if (!function.isFunctionObject())
+ return engine->throwTypeError();
+
+ Scope scope(engine);
+ CallArgs arguments = createSpreadArguments(scope, argv, argc);
+ if (engine->hasException)
+ return Encode::undefined();
+
+ return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget);
}
void Runtime::method_throwException(ExecutionEngine *engine, const Value &value)
@@ -1161,6 +1383,8 @@ ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &
case Value::Managed_Type:
if (value.isString())
res = engine->id_string();
+ else if (value.isSymbol())
+ res = engine->id_symbol();
else if (value.objectValue()->as<FunctionObject>())
res = engine->id_function();
else
@@ -1183,25 +1407,54 @@ QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameI
return method_typeofValue(engine, prop);
}
-/* The next three methods are a bit tricky. They can't open up a Scope, as that
- * would mess up the pushing of the context.
- *
- * Instead the push/pop pair acts as a non local scope.
- */
-ReturnedValue Runtime::method_createWithContext(ExecutionContext *parent, const Value &o)
+ReturnedValue Runtime::method_createWithContext(ExecutionEngine *engine, Value *jsStackFrame)
{
- Q_ASSERT(o.isObject());
- const Object &obj = static_cast<const Object &>(o);
- return parent->newWithContext(obj.d())->asReturnedValue();
+ QV4::Value &accumulator = jsStackFrame[CallData::Accumulator];
+ accumulator = accumulator.toObject(engine);
+ if (engine->hasException)
+ return Encode::undefined();
+ Q_ASSERT(accumulator.isObject());
+ const Object &obj = static_cast<const Object &>(accumulator);
+ ExecutionContext *context = static_cast<ExecutionContext *>(jsStackFrame + CallData::Context);
+ return context->newWithContext(obj.d())->asReturnedValue();
}
-ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int exceptionVarNameIndex)
+ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)
{
ExecutionEngine *e = parent->engine();
- return parent->newCatchContext(e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex],
- e->catchException(nullptr))->asReturnedValue();
+ return parent->newCatchContext(e->currentStackFrame, blockIndex,
+ e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex])->asReturnedValue();
}
+ReturnedValue Runtime::method_createBlockContext(ExecutionContext *parent, int index)
+{
+ ExecutionEngine *e = parent->engine();
+ return parent->newBlockContext(e->currentStackFrame, index)->asReturnedValue();
+}
+
+ReturnedValue Runtime::method_cloneBlockContext(ExecutionContext *previous)
+{
+ return ExecutionContext::cloneBlockContext(static_cast<Heap::CallContext *>(previous->d()))->asReturnedValue();
+}
+
+
+ReturnedValue Runtime::method_createScriptContext(ExecutionEngine *engine, int index)
+{
+ Q_ASSERT(engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_GlobalContext ||
+ engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_QmlContext);
+ ReturnedValue c = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue();
+ engine->setScriptContext(c);
+ return c;
+}
+
+ReturnedValue Runtime::method_popScriptContext(ExecutionEngine *engine)
+{
+ ReturnedValue root = engine->rootContext()->asReturnedValue();
+ engine->setScriptContext(root);
+ return root;
+}
+
+
void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
{
Scope scope(engine);
@@ -1214,61 +1467,160 @@ ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *value
return engine->newArrayObject(values, length)->asReturnedValue();
}
-ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
+ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId, int argc, const QV4::Value *args)
{
Scope scope(engine);
- QV4::InternalClass *klass = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeClasses[classId];
- ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
+ Scoped<InternalClass> klass(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]);
+ ScopedObject o(scope, engine->newObject(klass->d()));
- {
- bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
- if (needSparseArray)
- o->initSparseArray();
- }
+ Q_ASSERT(uint(argc) >= klass->d()->size);
- for (uint i = 0; i < klass->size; ++i)
+ for (uint i = 0; i < klass->d()->size; ++i)
o->setProperty(i, *args++);
- if (arrayValueCount > 0) {
- ScopedValue entry(scope);
- for (int i = 0; i < arrayValueCount; ++i) {
- uint idx = args->toUInt32();
- ++args;
- entry = *args++;
- o->arraySet(idx, entry);
+ Q_ASSERT((argc - klass->d()->size) % 3 == 0);
+ int additionalArgs = (argc - int(klass->d()->size))/3;
+
+ if (!additionalArgs)
+ return o->asReturnedValue();
+
+ ScopedPropertyKey name(scope);
+ ScopedProperty pd(scope);
+ for (int i = 0; i < additionalArgs; ++i) {
+ Q_ASSERT(args->isInteger());
+ ObjectLiteralArgument arg = ObjectLiteralArgument(args->integerValue());
+ name = args[1].toPropertyKey(engine);
+ if (engine->hasException)
+ return Encode::undefined();
+ Q_ASSERT(arg == ObjectLiteralArgument::Value || args[2].isFunctionObject());
+ if (arg == ObjectLiteralArgument::Value || arg == ObjectLiteralArgument::Getter) {
+ pd->value = args[2];
+ pd->set = Primitive::emptyValue();
+ } else {
+ pd->value = Primitive::emptyValue();
+ pd->set = args[2];
}
+ bool ok = o->defineOwnProperty(name, pd, (arg == ObjectLiteralArgument::Value ? Attr_Data : Attr_Accessor));
+ if (!ok)
+ return engine->throwTypeError();
+
+ args += 3;
}
+ return o.asReturnedValue();
+}
+
+ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classIndex, const Value &superClass, const Value *computedNames)
+{
+ const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit;
+ const QV4::CompiledData::Class *cls = unit->data->classAt(classIndex);
- uint arrayGetterSetterCount = arrayGetterSetterCountAndFlags & ((1 << 30) - 1);
- if (arrayGetterSetterCount > 0) {
- ScopedProperty pd(scope);
- for (uint i = 0; i < arrayGetterSetterCount; ++i) {
- uint idx = args->toUInt32();
- ++args;
- pd->value = *args;
- ++args;
- pd->set = *args;
- ++args;
- o->arraySet(idx, pd, Attr_Accessor);
+ Scope scope(engine);
+ ScopedObject protoParent(scope, engine->objectPrototype());
+ ScopedObject constructorParent(scope, engine->functionPrototype());
+ if (!superClass.isEmpty()) {
+ if (superClass.isNull()) {
+ protoParent = Encode::null();
+ } else {
+ // ### check that the heritage object is a constructor
+ if (!superClass.isFunctionObject())
+ return engine->throwTypeError(QStringLiteral("The superclass is not a function object."));
+ const FunctionObject *s = static_cast<const FunctionObject *>(&superClass);
+ ScopedValue result(scope, s->get(scope.engine->id_prototype()));
+ if (!result->isObject() && !result->isNull())
+ return engine->throwTypeError(QStringLiteral("The value of the superclass's prototype property is not an object."));
+ protoParent = *result;
+ constructorParent = superClass;
}
}
- return o.asReturnedValue();
+ ScopedObject proto(scope, engine->newObject());
+ proto->setPrototypeUnchecked(protoParent);
+ ExecutionContext *current = static_cast<ExecutionContext *>(&engine->currentStackFrame->jsFrame->context);
+
+ ScopedFunctionObject constructor(scope);
+ QV4::Function *f = cls->constructorFunction != UINT_MAX ? unit->runtimeFunctions[cls->constructorFunction] : nullptr;
+ constructor = FunctionObject::createConstructorFunction(current, f, !superClass.isEmpty())->asReturnedValue();
+ constructor->setPrototypeUnchecked(constructorParent);
+ constructor->defineDefaultProperty(engine->id_prototype(), proto);
+ proto->defineDefaultProperty(engine->id_constructor(), constructor);
+
+ ScopedString name(scope);
+ if (cls->nameIndex != UINT_MAX) {
+ name = unit->runtimeStrings[cls->nameIndex];
+ constructor->defineReadonlyConfigurableProperty(engine->id_name(), name);
+ }
+
+ ScopedObject receiver(scope, *constructor);
+ ScopedPropertyKey propertyName(scope);
+ ScopedFunctionObject function(scope);
+ ScopedProperty property(scope);
+ const CompiledData::Method *methods = cls->methodTable();
+ for (uint i = 0; i < cls->nStaticMethods + cls->nMethods; ++i) {
+ if (i == cls->nStaticMethods)
+ receiver = proto;
+ if (methods[i].name == UINT_MAX) {
+ propertyName = computedNames->toPropertyKey(engine);
+ if (engine->hasException)
+ return Encode::undefined();
+ ++computedNames;
+ } else {
+ name = unit->runtimeStrings[methods[i].name];
+ propertyName = name->toPropertyKey();
+ }
+ QV4::Function *f = unit->runtimeFunctions[methods[i].function];
+ Q_ASSERT(f);
+ if (f->isGenerator())
+ function = MemberGeneratorFunction::create(current, f);
+ else
+ function = FunctionObject::createMemberFunction(current, f);
+ Q_ASSERT(function);
+ PropertyAttributes attributes;
+ switch (methods[i].type) {
+ case CompiledData::Method::Getter:
+ property->setGetter(function);
+ property->set = Primitive::emptyValue();
+ attributes = Attr_Accessor|Attr_NotEnumerable;
+ break;
+ case CompiledData::Method::Setter:
+ property->value = Primitive::emptyValue();
+ property->setSetter(function);
+ attributes = Attr_Accessor|Attr_NotEnumerable;
+ break;
+ default: // Regular
+ property->value = function;
+ property->set = Primitive::emptyValue();
+ attributes = Attr_Data|Attr_NotEnumerable;
+ break;
+ }
+ receiver->defineOwnProperty(propertyName, property, attributes);
+ }
+
+ return constructor->asReturnedValue();
}
QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine)
{
Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext);
- QV4::InternalClass *ic = engine->internalClasses[EngineBase::Class_ArgumentsObject];
- return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), engine->currentStackFrame)->asReturnedValue();
+ Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_ArgumentsObject);
+ return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
}
QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine *engine)
{
- QV4::InternalClass *ic = engine->internalClasses[EngineBase::Class_StrictArgumentsObject];
- return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->objectPrototype(), engine->currentStackFrame)->asReturnedValue();
+ Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_StrictArgumentsObject);
+ return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
+}
+
+QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, int argIndex)
+{
+ const Value *values = engine->currentStackFrame->originalArguments + argIndex;
+ int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex;
+ if (nValues <= 0)
+ return engine->newArrayObject(0)->asReturnedValue();
+ return engine->newArrayObject(values, nValues)->asReturnedValue();
}
+
ReturnedValue Runtime::method_loadQmlContext(NoThrowEngine *engine)
{
Heap::QmlContext *ctx = engine->qmlContext();
@@ -1485,24 +1837,133 @@ ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
return Encode(r);
}
+struct LazyScope
+{
+ ExecutionEngine *engine = nullptr;
+ Value *stackMark = nullptr;
+ ~LazyScope() {
+ if (engine)
+ engine->jsStackTop = stackMark;
+ }
+ template <typename T>
+ void set(Value **scopedValue, T value, ExecutionEngine *e) {
+ if (!engine) {
+ engine = e;
+ stackMark = engine->jsStackTop;
+ }
+ if (!*scopedValue)
+ *scopedValue = e->jsAlloca(1);
+ **scopedValue = value;
+ }
+};
+
Bool Runtime::method_compareEqual(const Value &left, const Value &right)
{
TRACE2(left, right);
- if (left.rawValue() == right.rawValue())
- // NaN != NaN
- return !left.isNaN();
+ Value lhs = left;
+ Value rhs = right;
- if (left.type() == right.type()) {
- if (left.isDouble() && left.doubleValue() == 0 && right.doubleValue() == 0)
- return true; // this takes care of -0 == +0 (which obviously have different raw values)
- if (!left.isManaged())
- return false;
- if (left.isString() == right.isString())
- return left.cast<Managed>()->isEqualTo(right.cast<Managed>());
+#ifndef V4_BOOTSTRAP
+ LazyScope scope;
+ Value *lhsGuard = nullptr;
+ Value *rhsGuard = nullptr;
+#endif
+
+ redo:
+ if (lhs.asReturnedValue() == rhs.asReturnedValue())
+ return !lhs.isNaN();
+
+ int lt = lhs.quickType();
+ int rt = rhs.quickType();
+ if (rt < lt) {
+ qSwap(lhs, rhs);
+ qSwap(lt, rt);
}
- return RuntimeHelpers::equalHelper(left, right);
+ switch (lt) {
+ case QV4::Value::QT_ManagedOrUndefined:
+ if (lhs.isUndefined())
+ return rhs.isNullOrUndefined();
+ Q_FALLTHROUGH();
+ case QV4::Value::QT_ManagedOrUndefined1:
+ case QV4::Value::QT_ManagedOrUndefined2:
+ case QV4::Value::QT_ManagedOrUndefined3:
+ // LHS: Managed
+ switch (rt) {
+ case QV4::Value::QT_ManagedOrUndefined:
+ if (rhs.isUndefined())
+ return false;
+ Q_FALLTHROUGH();
+ case QV4::Value::QT_ManagedOrUndefined1:
+ case QV4::Value::QT_ManagedOrUndefined2:
+ case QV4::Value::QT_ManagedOrUndefined3: {
+#ifndef V4_BOOTSTRAP
+ // RHS: Managed
+ Heap::Base *l = lhs.m();
+ Heap::Base *r = rhs.m();
+ Q_ASSERT(l);
+ Q_ASSERT(r);
+ if (l->internalClass->vtable->isStringOrSymbol == r->internalClass->vtable->isStringOrSymbol)
+ return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs));
+ if (l->internalClass->vtable->isStringOrSymbol) {
+ scope.set(&rhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT), r->internalClass->engine);
+ rhs = rhsGuard->asReturnedValue();
+ break;
+ } else {
+ Q_ASSERT(r->internalClass->vtable->isStringOrSymbol);
+ scope.set(&lhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT), l->internalClass->engine);
+ lhs = lhsGuard->asReturnedValue();
+ break;
+ }
+#endif
+ return false;
+ }
+ case QV4::Value::QT_Empty:
+ Q_UNREACHABLE();
+ case QV4::Value::QT_Null:
+ return false;
+ case QV4::Value::QT_Bool:
+ case QV4::Value::QT_Int:
+ rhs = Primitive::fromDouble(rhs.int_32());
+ // fall through
+ default: // double
+#ifndef V4_BOOTSTRAP
+ if (lhs.m()->internalClass->vtable->isStringOrSymbol) {
+ return lhs.m()->internalClass->vtable->isString ? (RuntimeHelpers::toNumber(lhs) == rhs.doubleValue()) : false;
+ } else {
+ scope.set(&lhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT), lhs.m()->internalClass->engine);
+ lhs = lhsGuard->asReturnedValue();
+ }
+#else
+ Q_UNIMPLEMENTED();
+#endif
+ }
+ goto redo;
+ case QV4::Value::QT_Empty:
+ Q_UNREACHABLE();
+ case QV4::Value::QT_Null:
+ return rhs.isNull();
+ case QV4::Value::QT_Bool:
+ case QV4::Value::QT_Int:
+ switch (rt) {
+ case QV4::Value::QT_ManagedOrUndefined:
+ case QV4::Value::QT_ManagedOrUndefined1:
+ case QV4::Value::QT_ManagedOrUndefined2:
+ case QV4::Value::QT_ManagedOrUndefined3:
+ case QV4::Value::QT_Empty:
+ case QV4::Value::QT_Null:
+ Q_UNREACHABLE();
+ case QV4::Value::QT_Bool:
+ case QV4::Value::QT_Int:
+ return lhs.int_32() == rhs.int_32();
+ default: // double
+ return lhs.int_32() == rhs.doubleValue();
+ }
+ default: // double
+ Q_ASSERT(rhs.isDouble());
+ return lhs.doubleValue() == rhs.doubleValue();
+ }
}
ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 3a26c23990..72af90d1dc 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -100,6 +100,7 @@ enum TypeHint {
struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
static ReturnedValue objectDefaultValue(const Object *object, int typeHint);
static ReturnedValue toPrimitive(const Value &value, TypeHint typeHint);
+ static ReturnedValue ordinaryToPrimitive(ExecutionEngine *engine, const Object *object, String *typeHint);
static double stringToNumber(const QString &s);
static Heap::String *stringFromNumber(ExecutionEngine *engine, double number);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index 91232256a9..3f65e6c6d6 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -99,33 +99,39 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, callElement, (ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)) \
F(ReturnedValue, callValue, (ExecutionEngine *engine, const Value &func, Value *argv, int argc)) \
F(ReturnedValue, callPossiblyDirectEval, (ExecutionEngine *engine, Value *argv, int argc)) \
+ F(ReturnedValue, callWithSpread, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \
\
/* construct */ \
- F(ReturnedValue, construct, (ExecutionEngine *engine, const Value &func, Value *argv, int argc)) \
+ F(ReturnedValue, construct, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \
+ F(ReturnedValue, constructWithSpread, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \
\
/* load & store */ \
F(void, storeNameStrict, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
F(void, storeNameSloppy, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
- F(bool, storeProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \
- F(bool, storeElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \
+ F(void, storeProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \
+ F(void, storeElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \
F(ReturnedValue, loadProperty, (ExecutionEngine *engine, const Value &object, int nameIndex)) \
F(ReturnedValue, loadName, (ExecutionEngine *engine, int nameIndex)) \
F(ReturnedValue, loadElement, (ExecutionEngine *engine, const Value &object, const Value &index)) \
+ F(ReturnedValue, loadSuperProperty, (ExecutionEngine *engine, const Value &property)) \
+ F(void, storeSuperProperty, (ExecutionEngine *engine, const Value &property, const Value &value)) \
\
/* typeof */ \
F(ReturnedValue, typeofValue, (ExecutionEngine *engine, const Value &val)) \
F(ReturnedValue, typeofName, (ExecutionEngine *engine, int nameIndex)) \
\
/* delete */ \
- F(bool, deleteElement, (ExecutionEngine *engine, const Value &base, const Value &index)) \
- F(bool, deleteMember, (ExecutionEngine *engine, const Value &base, int nameIndex)) \
- F(bool, deleteMemberString, (ExecutionEngine *engine, const Value &base, String *name)) \
+ F(bool, deleteProperty, (ExecutionEngine *engine, const Value &base, const Value &index)) \
F(bool, deleteName, (ExecutionEngine *engine, int nameIndex)) \
\
/* exceptions & scopes */ \
F(void, throwException, (ExecutionEngine *engine, const Value &value)) \
- F(ReturnedValue, createWithContext, (ExecutionContext *parent, const Value &o)) \
- F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int exceptionVarNameIndex)) \
+ F(ReturnedValue, createWithContext, (ExecutionEngine *, Value *jsStackFrame)) \
+ F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)) \
+ F(ReturnedValue, createBlockContext, (ExecutionContext *parent, int index)) \
+ F(ReturnedValue, createScriptContext, (ExecutionEngine *engine, int index)) \
+ F(ReturnedValue, cloneBlockContext, (ExecutionContext *previous)) \
+ F(ReturnedValue, popScriptContext, (ExecutionEngine *engine)) \
\
/* closures */ \
F(ReturnedValue, closure, (ExecutionEngine *engine, int functionId)) \
@@ -134,14 +140,18 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)) \
F(ReturnedValue, createMappedArgumentsObject, (ExecutionEngine *engine)) \
F(ReturnedValue, createUnmappedArgumentsObject, (ExecutionEngine *engine)) \
+ F(ReturnedValue, createRestParameter, (ExecutionEngine *engine, int argIndex)) \
\
/* literals */ \
F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \
- F(ReturnedValue, objectLiteral, (ExecutionEngine *engine, const Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)) \
- \
- /* foreach */ \
- F(ReturnedValue, foreachIterator, (ExecutionEngine *engine, const Value &in)) \
- F(ReturnedValue, foreachNextPropertyName, (const Value &foreach_iterator)) \
+ F(ReturnedValue, objectLiteral, (ExecutionEngine *engine, int classId, int argc, const Value *args)) \
+ F(ReturnedValue, createClass, (ExecutionEngine *engine, int classIndex, const Value &heritage, const Value *computedNames)) \
+ \
+ /* for-in, for-of and array destructuring */ \
+ F(ReturnedValue, getIterator, (ExecutionEngine *engine, const Value &in, int iterator)) \
+ F(ReturnedValue, iteratorNext, (ExecutionEngine *engine, const Value &iterator, Value *value)) \
+ F(ReturnedValue, iteratorClose, (ExecutionEngine *engine, const Value &iterator, const Value &done)) \
+ F(ReturnedValue, destructureRestElement, (ExecutionEngine *engine, const Value &iterator)) \
\
/* unary operators */ \
F(ReturnedValue, uMinus, (const Value &value)) \
diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp
index fe18ddf9ed..9866966936 100644
--- a/src/qml/jsruntime/qv4runtimecodegen.cpp
+++ b/src/qml/jsruntime/qv4runtimecodegen.cpp
@@ -52,13 +52,16 @@ void RuntimeCodegen::generateFromFunctionExpression(const QString &fileName,
_module->finalUrl = fileName;
_context = nullptr;
- Compiler::ScanFunctions scan(this, sourceCode, Compiler::GlobalCode);
+ Compiler::ScanFunctions scan(this, sourceCode, Compiler::ContextType::Global);
// fake a global environment
- scan.enterEnvironment(nullptr, Compiler::FunctionCode);
+ scan.enterEnvironment(nullptr, Compiler::ContextType::Function, QString());
scan(ast);
scan.leaveEnvironment();
- int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : nullptr);
+ if (hasError)
+ return;
+
+ int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body);
_module->rootContext = _module->functions.at(index);
}
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index bb20f384b3..1f66c4a47e 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -53,6 +53,7 @@
#include "qv4engine_p.h"
#include "qv4value_p.h"
#include "qv4property_p.h"
+#include "qv4propertykey_p.h"
#ifdef V4_USE_VALGRIND
#include <valgrind/memcheck.h>
@@ -117,8 +118,45 @@ struct Scope {
engine->jsStackTop = mark;
}
- QML_NEARLY_ALWAYS_INLINE Value *alloc(int nValues) const {
- return engine->jsAlloca(nValues);
+ enum AllocMode {
+ Undefined,
+ Empty,
+ /* Be careful when using Uninitialized, the stack has to be fully initialized before calling into the memory manager again */
+ Uninitialized
+ };
+ template <AllocMode mode = Undefined>
+ QML_NEARLY_ALWAYS_INLINE Value *alloc(int nValues) const
+ {
+ Value *ptr = engine->jsAlloca(nValues);
+ switch (mode) {
+ case Undefined:
+ for (int i = 0; i < nValues; ++i)
+ ptr[i] = Primitive::undefinedValue();
+ break;
+ case Empty:
+ for (int i = 0; i < nValues; ++i)
+ ptr[i] = Primitive::emptyValue();
+ break;
+ case Uninitialized:
+ break;
+ }
+ return ptr;
+ }
+ template <AllocMode mode = Undefined>
+ QML_NEARLY_ALWAYS_INLINE Value *alloc() const
+ {
+ Value *ptr = engine->jsAlloca(1);
+ switch (mode) {
+ case Undefined:
+ *ptr = Primitive::undefinedValue();
+ break;
+ case Empty:
+ *ptr = Primitive::emptyValue();
+ break;
+ case Uninitialized:
+ break;
+ }
+ return ptr;
}
bool hasException() const {
@@ -136,31 +174,31 @@ struct ScopedValue
{
ScopedValue(const Scope &scope)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(0);
}
ScopedValue(const Scope &scope, const Value &v)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
*ptr = v;
}
ScopedValue(const Scope &scope, Heap::Base *o)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setM(o);
}
ScopedValue(const Scope &scope, Managed *m)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(m->asReturnedValue());
}
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(v);
}
@@ -203,6 +241,37 @@ struct ScopedValue
Value *ptr;
};
+
+struct ScopedPropertyKey
+{
+ ScopedPropertyKey(const Scope &scope)
+ {
+ ptr = reinterpret_cast<PropertyKey *>(scope.alloc<Scope::Uninitialized>());
+ *ptr = PropertyKey::invalid();
+ }
+
+ ScopedPropertyKey(const Scope &scope, const PropertyKey &v)
+ {
+ ptr = reinterpret_cast<PropertyKey *>(scope.alloc<Scope::Uninitialized>());
+ *ptr = v;
+ }
+
+ ScopedPropertyKey &operator=(const PropertyKey &other) {
+ *ptr = other;
+ return *this;
+ }
+
+ PropertyKey *operator->() {
+ return ptr;
+ }
+ operator PropertyKey() const {
+ return *ptr;
+ }
+
+ PropertyKey *ptr;
+};
+
+
template<typename T>
struct Scoped
{
@@ -214,66 +283,66 @@ struct Scoped
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Undefined>();
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value &v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v.as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, Heap::Base *o)
{
Value v;
v = o;
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v.as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ScopedValue &v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v.ptr->as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value &v, ConvertType)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(value_convert<T>(scope.engine, v));
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value *v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v ? v->as<T>() : nullptr);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, T *t)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(t);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const T *t)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(t);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, typename T::Data *t)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
*ptr = t;
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ReturnedValue &v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(QV4::Value::fromReturnedValue(v).as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ReturnedValue &v, ConvertType)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 5cd62c90f1..37c4f27ca9 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -57,10 +57,11 @@
#include <QtCore/QDebug>
#include <QtCore/QString>
+#include <QScopedValueRollback>
using namespace QV4;
-Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit)
+Script::Script(ExecutionEngine *v4, QmlContext *qml, const QQmlRefPointer<CompiledData::CompilationUnit> &compilationUnit)
: line(1), column(0), context(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
, compilationUnit(compilationUnit), vmFunction(nullptr), parseAsBinding(true)
{
@@ -128,7 +129,7 @@ void Script::parse()
RuntimeCodegen cg(v4, &jsGenerator, strictMode);
if (inheritContext)
cg.setUseFastLookups(false);
- cg.generateFromProgram(sourceFile, sourceFile, sourceCode, program, &module, compilationMode);
+ cg.generateFromProgram(sourceFile, sourceFile, sourceCode, program, &module, contextType);
if (v4->hasException)
return;
@@ -154,7 +155,7 @@ ReturnedValue Script::run(const QV4::Value *thisObject)
QV4::Scope valueScope(engine);
if (qmlContext.isUndefined()) {
- TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
+ QScopedValueRollback<Function*> savedGlobalCode(engine->globalCode, vmFunction);
return vmFunction->call(thisObject ? thisObject : engine->globalObject, nullptr, 0,
context);
@@ -171,19 +172,16 @@ Function *Script::function()
return vmFunction;
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compiler::Module *module, Compiler::JSUnitGenerator *unitGenerator,
+QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator,
const QString &fileName, const QString &finalUrl, const QString &source,
- QList<QQmlError> *reportedErrors, Directives *directivesCollector)
+ QList<QQmlError> *reportedErrors)
{
using namespace QV4::Compiler;
using namespace QQmlJS::AST;
- Engine ee;
- if (directivesCollector)
- ee.setDirectives(directivesCollector);
- Lexer lexer(&ee);
+ Lexer lexer(jsEngine);
lexer.setCode(source, /*line*/1, /*qml mode*/false);
- Parser parser(&ee);
+ Parser parser(jsEngine);
parser.parseProgram();
@@ -219,7 +217,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compi
Codegen cg(unitGenerator, /*strict mode*/false);
cg.setUseFastLookups(false);
- cg.generateFromProgram(fileName, finalUrl, source, program, module, GlobalCode);
+ cg.generateFromProgram(fileName, finalUrl, source, program, module, ContextType::Global);
errors = cg.qmlErrors();
if (!errors.isEmpty()) {
if (reportedErrors)
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index b4ac150044..e7189664e2 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -62,12 +62,16 @@ QT_BEGIN_NAMESPACE
class QQmlContextData;
+namespace QQmlJS {
+class Engine;
+}
+
namespace QV4 {
struct Q_QML_EXPORT Script {
- Script(ExecutionContext *scope, QV4::Compiler::CompilationMode mode, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionContext *scope, QV4::Compiler::ContextType mode, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
- , context(scope), strictMode(false), inheritContext(false), parsed(false), compilationMode(mode)
+ , context(scope), strictMode(false), inheritContext(false), parsed(false), contextType(mode)
, vmFunction(nullptr), parseAsBinding(false) {}
Script(ExecutionEngine *engine, QmlContext *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
@@ -76,7 +80,7 @@ struct Q_QML_EXPORT Script {
if (qml)
qmlContext.set(engine, *qml);
}
- Script(ExecutionEngine *engine, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit);
+ Script(ExecutionEngine *engine, QmlContext *qml, const QQmlRefPointer<CompiledData::CompilationUnit> &compilationUnit);
~Script();
QString sourceFile;
int line;
@@ -86,7 +90,7 @@ struct Q_QML_EXPORT Script {
bool strictMode;
bool inheritContext;
bool parsed;
- QV4::Compiler::CompilationMode compilationMode = QV4::Compiler::EvalCode;
+ QV4::Compiler::ContextType contextType = QV4::Compiler::ContextType::Eval;
QV4::PersistentValue qmlContext;
QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit;
Function *vmFunction;
@@ -97,10 +101,9 @@ struct Q_QML_EXPORT Script {
Function *function();
- static QQmlRefPointer<CompiledData::CompilationUnit> precompile(
- QV4::Compiler::Module *module, Compiler::JSUnitGenerator *unitGenerator,
+ static QQmlRefPointer<CompiledData::CompilationUnit> precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator,
const QString &fileName, const QString &finalUrl, const QString &source,
- QList<QQmlError> *reportedErrors = nullptr, QQmlJS::Directives *directivesCollector = nullptr);
+ QList<QQmlError> *reportedErrors = nullptr);
static Script *createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl, QString *error);
static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext);
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 7d29d0b517..1ba889ee82 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -227,7 +227,7 @@ namespace Heap {
template <typename Container>
struct QQmlSequence : Object {
void init(const Container &container);
- void init(QObject *object, int propertyIndex);
+ void init(QObject *object, int propertyIndex, bool readOnly);
void destroy() {
delete container;
object.destroy();
@@ -237,7 +237,8 @@ struct QQmlSequence : Object {
mutable Container *container;
QQmlQPointer<QObject> object;
int propertyIndex;
- bool isReference;
+ bool isReference : 1;
+ bool isReadOnly : 1;
};
}
@@ -294,6 +295,9 @@ public:
return false;
}
+ if (d()->isReadOnly)
+ return false;
+
if (d()->isReference) {
if (!d()->object)
return false;
@@ -345,7 +349,7 @@ public:
if (d()->isReference) {
if (!d()->object) {
- QV4::Object::advanceIterator(this, it, name, index, p, attrs);
+ QV4::Object::virtualAdvanceIterator(this, it, name, index, p, attrs);
return;
}
loadReference();
@@ -358,7 +362,7 @@ public:
p->value = convertElementToValue(engine(), d()->container->at(*index));
return;
}
- QV4::Object::advanceIterator(this, it, name, index, p, attrs);
+ QV4::Object::virtualAdvanceIterator(this, it, name, index, p, attrs);
}
bool containerDeleteIndexedProperty(uint index)
@@ -366,6 +370,8 @@ public:
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX)
return false;
+ if (d()->isReadOnly)
+ return false;
if (d()->isReference) {
if (!d()->object)
return false;
@@ -432,11 +438,13 @@ public:
const QV4::Value *m_compareFn;
};
- void sort(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ bool sort(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
+ if (d()->isReadOnly)
+ return false;
if (d()->isReference) {
if (!d()->object)
- return;
+ return false;
loadReference();
}
@@ -450,6 +458,8 @@ public:
if (d()->isReference)
storeReference();
+
+ return true;
}
static QV4::ReturnedValue method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -480,6 +490,10 @@ public:
generateWarning(scope.engine, QLatin1String("Index out of range during length set"));
RETURN_UNDEFINED();
}
+
+ if (This->d()->isReadOnly)
+ THROW_TYPE_ERROR();
+
/* Read the sequence from the QObject property if we're a reference */
if (This->d()->isReference) {
if (!This->d()->object)
@@ -524,7 +538,7 @@ public:
quint32 length = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 i = 0; i < length; ++i)
- result.push_back(convertValueToElement<typename Container::value_type>((v = array->getIndexed(i))));
+ result.push_back(convertValueToElement<typename Container::value_type>((v = array->get(i))));
return QVariant::fromValue(result);
}
@@ -549,17 +563,31 @@ public:
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
- static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
- { return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
- static bool putIndexed(Managed *that, uint index, const QV4::Value &value)
- { return static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
+ static QV4::ReturnedValue virtualGet(const QV4::Managed *that, PropertyKey id, const Value *receiver, bool *hasProperty)
+ {
+ if (!id.isArrayIndex())
+ return Object::virtualGet(that, id, receiver, hasProperty);
+ return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(id.asArrayIndex(), hasProperty);
+ }
+ static bool virtualPut(Managed *that, PropertyKey id, const QV4::Value &value, Value *receiver)
+ {
+ if (id.isArrayIndex())
+ return static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(id.asArrayIndex(), value);
+ return Object::virtualPut(that, id, value, receiver);
+ }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
{ return static_cast<const QQmlSequence<Container> *>(that)->containerQueryIndexed(index); }
- static bool deleteIndexedProperty(QV4::Managed *that, uint index)
- { return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
- static bool isEqualTo(Managed *that, Managed *other)
+ static bool virtualDeleteProperty(QV4::Managed *that, PropertyKey id)
+ {
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index);
+ }
+ return Object::virtualDeleteProperty(that, id);
+ }
+ static bool virtualIsEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void virtualAdvanceIterator(Managed *that, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
};
@@ -572,6 +600,7 @@ void Heap::QQmlSequence<Container>::init(const Container &container)
this->container = new Container(container);
propertyIndex = -1;
isReference = false;
+ isReadOnly = false;
object.init();
QV4::Scope scope(internalClass->engine);
@@ -581,12 +610,13 @@ void Heap::QQmlSequence<Container>::init(const Container &container)
}
template <typename Container>
-void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex)
+void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex, bool readOnly)
{
Object::init();
this->container = new Container;
this->propertyIndex = propertyIndex;
isReference = true;
+ this->isReadOnly = readOnly;
this->object.init(object);
QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
@@ -668,7 +698,8 @@ ReturnedValue SequencePrototype::method_sort(const FunctionObject *b, const Valu
#define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \
- s->sort(b, thisObject, argv, argc); \
+ if (!s->sort(b, thisObject, argv, argc)) \
+ THROW_TYPE_ERROR(); \
} else
FOREACH_QML_SEQUENCE_TYPE(CALL_SORT)
@@ -691,11 +722,11 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(object, propertyIndex)); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QQml##ElementTypeName##List>(object, propertyIndex, readOnly)); \
return obj.asReturnedValue(); \
} else
-ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool *succeeded)
+ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool readOnly, bool *succeeded)
{
QV4::Scope scope(engine);
// This function is called when the property is a QObject Q_PROPERTY of
@@ -709,7 +740,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(v.value<SequenceType >())); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QQml##ElementTypeName##List>(v.value<SequenceType >())); \
return obj.asReturnedValue(); \
} else
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index e9bef2f604..da71215bed 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -59,6 +59,8 @@
#include "qv4context_p.h"
#include "qv4string_p.h"
+QT_REQUIRE_CONFIG(qml_sequence_object);
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -72,7 +74,7 @@ struct SequencePrototype : public QV4::Object
static ReturnedValue method_sort(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static bool isSequenceType(int sequenceTypeId);
- static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
+ static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool readOnly, bool *succeeded);
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
static int metaTypeForSequence(const Object *object);
static QVariant toVariant(Object *object);
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 14def49d0a..e151966306 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -40,13 +40,17 @@
#include "qv4serialize_p.h"
#include <private/qv8engine_p.h>
+#if QT_CONFIG(qml_list_model)
#include <private/qqmllistmodel_p.h>
#include <private/qqmllistmodelworkeragent_p.h>
+#endif
#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4regexpobject_p.h>
+#if QT_CONFIG(qml_sequence_object)
#include <private/qv4sequenceobject_p.h>
+#endif
#include <private/qv4objectproto_p.h>
#include <private/qv4qobjectwrapper_p.h>
@@ -82,8 +86,12 @@ enum Type {
WorkerNumber,
WorkerDate,
WorkerRegexp,
+#if QT_CONFIG(qml_list_model)
WorkerListModel,
+#endif
+#if QT_CONFIG(qml_sequence_object)
WorkerSequence
+#endif
};
static inline quint32 valueheader(Type type, quint32 size = 0)
@@ -189,7 +197,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
push(data, valueheader(WorkerArray, length));
ScopedValue val(scope);
for (uint ii = 0; ii < length; ++ii)
- serialize(data, (val = array->getIndexed(ii)), engine);
+ serialize(data, (val = array->get(ii)), engine);
} else if (v.isInteger()) {
reserve(data, 2 * sizeof(quint32));
push(data, valueheader(WorkerInt32));
@@ -228,6 +236,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
} else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
// XXX TODO: Generalize passing objects between the main thread and worker scripts so
// that others can trivially plug in their elements.
+#if QT_CONFIG(qml_list_model)
QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
if (lm && lm->agent()) {
QQmlListModelWorkerAgent *agent = lm->agent();
@@ -236,9 +245,13 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
push(data, (void *)agent);
return;
}
+#else
+ Q_UNUSED(qobjectWrapper);
+#endif
// No other QObject's are allowed to be sent
push(data, valueheader(WorkerUndefined));
} else if (const Object *o = v.as<Object>()) {
+#if QT_CONFIG(qml_sequence_object)
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
@@ -252,10 +265,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
serialize(data, QV4::Primitive::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
ScopedValue val(scope);
for (uint ii = 0; ii < seqLength; ++ii)
- serialize(data, (val = o->getIndexed(ii)), engine); // sequence elements
+ serialize(data, (val = o->get(ii)), engine); // sequence elements
return;
}
+#endif
// regular object
QV4::ScopedValue val(scope, v);
@@ -269,7 +283,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
QV4::ScopedValue s(scope);
for (quint32 ii = 0; ii < length; ++ii) {
- s = properties->getIndexed(ii);
+ s = properties->get(ii);
serialize(data, s, engine);
QV4::String *str = s->as<String>();
@@ -318,7 +332,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii) {
v = deserialize(data, engine);
- a->putIndexed(ii, v);
+ a->put(ii, v);
}
return a.asReturnedValue();
}
@@ -353,6 +367,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
data += ALIGN(length * sizeof(quint16));
return Encode(engine->newRegExpObject(pattern, flags));
}
+#if QT_CONFIG(qml_list_model)
case WorkerListModel:
{
void *ptr = popPtr(data);
@@ -369,6 +384,8 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
agent->setEngine(engine);
return rv->asReturnedValue();
}
+#endif
+#if QT_CONFIG(qml_sequence_object)
case WorkerSequence:
{
ScopedValue value(scope);
@@ -387,6 +404,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
return QV4::SequencePrototype::fromVariant(engine, seqVariant, &succeeded);
}
+#endif
}
Q_ASSERT(!"Unreachable");
return QV4::Encode::undefined();
diff --git a/src/qml/jsruntime/qv4setiterator.cpp b/src/qml/jsruntime/qv4setiterator.cpp
new file mode 100644
index 0000000000..4681a49bd6
--- /dev/null
+++ b/src/qml/jsruntime/qv4setiterator.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qv4iterator_p.h>
+#include <private/qv4estable_p.h>
+#include <private/qv4setiterator_p.h>
+#include <private/qv4setobject_p.h>
+#include <private/qv4symbol_p.h>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(SetIteratorObject);
+
+void SetIteratorPrototype::init(ExecutionEngine *e)
+{
+ defineDefaultProperty(QStringLiteral("next"), method_next, 0);
+
+ Scope scope(e);
+ ScopedString val(scope, e->newString(QLatin1String("Set Iterator")));
+ defineReadonlyConfigurableProperty(e->symbol_toStringTag(), val);
+}
+
+ReturnedValue SetIteratorPrototype::method_next(const FunctionObject *b, const Value *that, const Value *, int)
+{
+ Scope scope(b);
+ const SetIteratorObject *thisObject = that->as<SetIteratorObject>();
+ if (!thisObject)
+ return scope.engine->throwTypeError(QLatin1String("Not a Set Iterator instance"));
+
+ Scoped<SetObject> s(scope, thisObject->d()->iteratedSet);
+ uint index = thisObject->d()->setNextIndex;
+ IteratorKind itemKind = thisObject->d()->iterationKind;
+
+ if (!s) {
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+ }
+
+ Value *arguments = scope.alloc(2);
+
+ while (index < s->d()->esTable->size()) {
+ s->d()->esTable->iterate(index, &arguments[0], &arguments[1]);
+ thisObject->d()->setNextIndex = index + 1;
+
+ if (itemKind == KeyValueIteratorKind) {
+ ScopedArrayObject resultArray(scope, scope.engine->newArrayObject());
+ resultArray->arrayReserve(2);
+ resultArray->arrayPut(0, arguments[0]);
+ resultArray->arrayPut(1, arguments[0]); // yes, the key is repeated.
+ resultArray->setArrayLengthUnchecked(2);
+
+ return IteratorPrototype::createIterResultObject(scope.engine, resultArray, false);
+ }
+
+ return IteratorPrototype::createIterResultObject(scope.engine, arguments[0], false);
+ }
+
+ thisObject->d()->iteratedSet.set(scope.engine, nullptr);
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+}
+
diff --git a/src/qml/jsruntime/qv4setiterator_p.h b/src/qml/jsruntime/qv4setiterator_p.h
new file mode 100644
index 0000000000..78eda6d57b
--- /dev/null
+++ b/src/qml/jsruntime/qv4setiterator_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4SETITERATOR_P_H
+#define QV4SETITERATOR_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 "qv4object_p.h"
+#include "qv4iterator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Heap {
+
+#define SetIteratorObjectMembers(class, Member) \
+ Member(class, Pointer, Object *, iteratedSet) \
+ Member(class, NoMark, IteratorKind, iterationKind) \
+ Member(class, NoMark, quint32, setNextIndex)
+
+DECLARE_HEAP_OBJECT(SetIteratorObject, Object) {
+ DECLARE_MARKOBJECTS(SetIteratorObject);
+ void init(Object *obj, QV4::ExecutionEngine *engine)
+ {
+ Object::init();
+ this->iteratedSet.set(engine, obj);
+ this->setNextIndex = 0;
+ }
+};
+
+}
+
+struct SetIteratorPrototype : Object
+{
+ V4_PROTOTYPE(iteratorPrototype)
+ void init(ExecutionEngine *engine);
+
+ static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct SetIteratorObject : Object
+{
+ V4_OBJECT2(SetIteratorObject, Object)
+ Q_MANAGED_TYPE(SetIteratorObject)
+ V4_PROTOTYPE(setIteratorPrototype)
+
+ void init(ExecutionEngine *engine);
+};
+
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4SETITERATOR_P_H
+
diff --git a/src/qml/jsruntime/qv4setobject.cpp b/src/qml/jsruntime/qv4setobject.cpp
new file mode 100644
index 0000000000..30e849bfed
--- /dev/null
+++ b/src/qml/jsruntime/qv4setobject.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qv4setobject_p.h"
+#include "qv4setiterator_p.h"
+#include "qv4estable_p.h"
+#include "qv4symbol_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(SetCtor);
+DEFINE_OBJECT_VTABLE(SetObject);
+
+void Heap::SetCtor::init(QV4::ExecutionContext *scope)
+{
+ Heap::FunctionObject::init(scope, QStringLiteral("Set"));
+}
+
+ReturnedValue SetCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+{
+ Scope scope(f);
+ Scoped<SetObject> a(scope, scope.engine->memoryManager->allocate<SetObject>());
+
+ if (argc > 0) {
+ ScopedValue iterable(scope, argv[0]);
+ if (!iterable->isUndefined() && !iterable->isNull()) {
+ ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("add")))));
+ if (!adder)
+ return scope.engine->throwTypeError();
+ ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true));
+ CHECK_EXCEPTION();
+ if (!iter)
+ return a.asReturnedValue();
+
+ Value *nextValue = scope.alloc(1);
+ ScopedValue done(scope);
+ forever {
+ done = Runtime::method_iteratorNext(scope.engine, iter, nextValue);
+ CHECK_EXCEPTION();
+ if (done->toBoolean())
+ return a.asReturnedValue();
+
+ adder->call(a, nextValue, 1);
+ if (scope.engine->hasException) {
+ ScopedValue falsey(scope, Encode(false));
+ return Runtime::method_iteratorClose(scope.engine, iter, falsey);
+ }
+ }
+ }
+ }
+
+ return a.asReturnedValue();
+}
+
+ReturnedValue SetCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
+{
+ Scope scope(f);
+ return scope.engine->throwTypeError(QString::fromLatin1("Set requires new"));
+}
+
+void SetPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Scope scope(engine);
+ ScopedObject o(scope);
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->addSymbolSpecies();
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
+
+ defineDefaultProperty(QStringLiteral("add"), method_add, 1);
+ defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
+ defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
+ defineDefaultProperty(QStringLiteral("entries"), method_entries, 0);
+ defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
+ defineDefaultProperty(QStringLiteral("has"), method_has, 1);
+ defineAccessorProperty(QStringLiteral("size"), method_get_size, nullptr);
+
+ // Per the spec, the value for 'keys' is the same as 'values'.
+ ScopedString valString(scope, scope.engine->newIdentifier(QStringLiteral("values")));
+ ScopedFunctionObject valuesFn(scope, FunctionObject::createBuiltinFunction(engine, valString, SetPrototype::method_values, 0));
+ defineDefaultProperty(QStringLiteral("keys"), valuesFn);
+ defineDefaultProperty(QStringLiteral("values"), valuesFn);
+
+ defineDefaultProperty(engine->symbol_iterator(), valuesFn);
+
+ ScopedString val(scope, engine->newString(QLatin1String("Set")));
+ defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
+}
+
+void Heap::SetObject::init()
+{
+ Object::init();
+ esTable = new ESTable();
+}
+
+void Heap::SetObject::destroy()
+{
+ delete esTable;
+ esTable = 0;
+}
+
+void Heap::SetObject::markObjects(Heap::Base *that, MarkStack *markStack)
+{
+ SetObject *s = static_cast<SetObject *>(that);
+ s->esTable->markObjects(markStack);
+ Object::markObjects(that, markStack);
+}
+
+ReturnedValue SetPrototype::method_add(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ that->d()->esTable->set(argv[0], Primitive::undefinedValue());
+ return that.asReturnedValue();
+}
+
+ReturnedValue SetPrototype::method_clear(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ that->d()->esTable->clear();
+ return Encode::undefined();
+}
+
+ReturnedValue SetPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return Encode(that->d()->esTable->remove(argv[0]));
+}
+
+ReturnedValue SetPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ Scoped<SetIteratorObject> ao(scope, scope.engine->newSetIteratorObject(that));
+ ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue SetPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ ScopedFunctionObject callbackfn(scope, argv[0]);
+ if (!callbackfn)
+ return scope.engine->throwTypeError();
+
+ ScopedValue thisArg(scope, Primitive::undefinedValue());
+ if (argc > 1)
+ thisArg = ScopedValue(scope, argv[1]);
+
+ Value *arguments = scope.alloc(3);
+ for (uint i = 0; i < that->d()->esTable->size(); ++i) {
+ that->d()->esTable->iterate(i, &arguments[0], &arguments[1]); // fill in key (0), value (1)
+ arguments[1] = arguments[0]; // but for set, we want to return the key twice; value is always undefined.
+
+ arguments[2] = that;
+ callbackfn->call(thisArg, arguments, 3);
+ CHECK_EXCEPTION();
+ }
+ return Encode::undefined();
+}
+
+ReturnedValue SetPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return Encode(that->d()->esTable->has(argv[0]));
+}
+
+ReturnedValue SetPrototype::method_get_size(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ return Encode(that->d()->esTable->size());
+}
+
+ReturnedValue SetPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<SetObject> that(scope, thisObject);
+ if (!that)
+ return scope.engine->throwTypeError();
+
+ Scoped<SetIteratorObject> ao(scope, scope.engine->newSetIteratorObject(that));
+ ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
diff --git a/src/qml/jsruntime/qv4setobject_p.h b/src/qml/jsruntime/qv4setobject_p.h
new file mode 100644
index 0000000000..34649c3f01
--- /dev/null
+++ b/src/qml/jsruntime/qv4setobject_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Crimson AS <info@crimson.no>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4SETOBJECT_P_H
+#define QV4SETOBJECT_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 "qv4object_p.h"
+#include "qv4objectproto_p.h"
+#include "qv4functionobject_p.h"
+#include "qv4string_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+class ESTable;
+
+namespace Heap {
+
+struct SetCtor : FunctionObject {
+ void init(QV4::ExecutionContext *scope);
+};
+
+struct SetObject : Object {
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
+ void init();
+ void destroy();
+ ESTable *esTable;
+};
+
+}
+
+struct SetCtor: FunctionObject
+{
+ V4_OBJECT2(SetCtor, FunctionObject)
+
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct SetObject : Object
+{
+ V4_OBJECT2(SetObject, Object)
+ V4_PROTOTYPE(setPrototype)
+ V4_NEEDS_DESTROY
+};
+
+struct SetPrototype : Object
+{
+ void init(ExecutionEngine *engine, Object *ctor);
+
+ static ReturnedValue method_add(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_clear(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_delete(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_forEach(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_has(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_get_size(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+
+} // namespace QV4
+
+
+QT_END_NAMESPACE
+
+#endif // QV4SETOBJECT_P_H
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 2a3e28bf63..8930c9a94d 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -395,7 +395,7 @@ void SparseArray::freeTree(SparseArrayNode *root, int alignment)
SparseArray::SparseArray()
: numEntries(0)
{
- freeList = Primitive::emptyValue(UINT_MAX).asReturnedValue();
+ freeList = Encode(-1);
header.p = 0;
header.left = nullptr;
header.right = nullptr;
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 51869b259f..c1e50c8dcf 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -52,6 +52,7 @@
//
#include "qv4global_p.h"
+#include "qv4value_p.h"
#include <QtCore/qlist.h>
//#define Q_MAP_DEBUG
@@ -151,7 +152,7 @@ struct Q_QML_EXPORT SparseArray
SparseArray(const SparseArray &other);
- ReturnedValue freeList;
+ Value freeList;
private:
SparseArray &operator=(const SparseArray &other);
diff --git a/src/qml/jsruntime/qv4stackframe.cpp b/src/qml/jsruntime/qv4stackframe.cpp
new file mode 100644
index 0000000000..a716c53aea
--- /dev/null
+++ b/src/qml/jsruntime/qv4stackframe.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qv4stackframe_p.h"
+#include <QtCore/qstring.h>
+
+using namespace QV4;
+
+QString CppStackFrame::source() const
+{
+ return v4Function ? v4Function->sourceFile() : QString();
+}
+
+QString CppStackFrame::function() const
+{
+ return v4Function ? v4Function->name()->toQString() : QString();
+}
+
+int CppStackFrame::lineNumber() const
+{
+ if (!v4Function)
+ return -1;
+
+ auto findLine = [](const CompiledData::CodeOffsetToLine &entry, uint offset) {
+ return entry.codeOffset < offset;
+ };
+
+ const QV4::CompiledData::Function *cf = v4Function->compiledFunction;
+ uint offset = instructionPointer;
+ const CompiledData::CodeOffsetToLine *lineNumbers = cf->lineNumberTable();
+ uint nLineNumbers = cf->nLineNumbers;
+ const CompiledData::CodeOffsetToLine *line = std::lower_bound(lineNumbers, lineNumbers + nLineNumbers, offset, findLine) - 1;
+ return line->line;
+}
+
+ReturnedValue CppStackFrame::thisObject() const {
+ return jsFrame->thisObject.asReturnedValue();
+}
+
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h
new file mode 100644
index 0000000000..aa507d61a6
--- /dev/null
+++ b/src/qml/jsruntime/qv4stackframe_p.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4STACKFRAME_H
+#define QV4STACKFRAME_H
+
+#include <private/qv4context_p.h>
+#include <private/qv4enginebase_p.h>
+#ifndef V4_BOOTSTRAP
+#include <private/qv4function_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct CallData
+{
+ enum Offsets {
+ Function = 0,
+ Context = 1,
+ Accumulator = 2,
+ This = 3,
+ NewTarget = 4,
+ Argc = 5,
+
+ LastOffset = Argc,
+ OffsetCount = LastOffset + 1
+ };
+
+ Value function;
+ Value context;
+ Value accumulator;
+ Value thisObject;
+ Value newTarget;
+ Value _argc;
+
+ int argc() const {
+ Q_ASSERT(_argc.isInteger());
+ return _argc.int_32();
+ }
+
+ void setArgc(int argc) {
+ Q_ASSERT(argc >= 0);
+ _argc.setInt_32(argc);
+ }
+
+ inline ReturnedValue argument(int i) const {
+ return i < argc() ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
+ }
+
+ Value args[1];
+
+ static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); }
+};
+
+Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
+Q_STATIC_ASSERT(offsetof(CallData, function ) == CallData::Function * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, context ) == CallData::Context * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, accumulator) == CallData::Accumulator * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, thisObject ) == CallData::This * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, newTarget ) == CallData::NewTarget * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, _argc ) == CallData::Argc * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, args ) == 6 * sizeof(Value));
+
+struct Q_QML_EXPORT CppStackFrame {
+ EngineBase *engine;
+ Value *savedStackTop;
+ CppStackFrame *parent;
+ Function *v4Function;
+ CallData *jsFrame;
+ const Value *originalArguments;
+ int originalArgumentsCount;
+ int instructionPointer;
+ const char *yield;
+ const char *unwindHandler;
+ const char *unwindLabel;
+ int unwindLevel;
+
+ void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc) {
+ this->engine = engine;
+
+ this->v4Function = v4Function;
+ originalArguments = argv;
+ originalArgumentsCount = argc;
+ instructionPointer = 0;
+ yield = nullptr;
+ unwindHandler = nullptr;
+ unwindLabel = nullptr;
+ unwindLevel = 0;
+ }
+
+ void push() {
+ parent = engine->currentStackFrame;
+ engine->currentStackFrame = this;
+ savedStackTop = engine->jsStackTop;
+ }
+
+ void pop() {
+ engine->currentStackFrame = parent;
+ engine->jsStackTop = savedStackTop;
+ }
+
+#ifndef V4_BOOTSTRAP
+ static uint requiredJSStackFrameSize(uint nRegisters) {
+ return CallData::HeaderSize() + nRegisters;
+ }
+ static uint requiredJSStackFrameSize(Function *v4Function) {
+ return CallData::HeaderSize() + v4Function->compiledFunction->nRegisters;
+ }
+ uint requiredJSStackFrameSize() const {
+ return requiredJSStackFrameSize(v4Function);
+ }
+ void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope,
+ const Value &thisObject, const Value &newTarget = Primitive::undefinedValue()) {
+ setupJSFrame(stackSpace, function, scope, thisObject, newTarget,
+ v4Function->nFormals, v4Function->compiledFunction->nRegisters);
+ }
+ void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope,
+ const Value &thisObject, const Value &newTarget, uint nFormals, uint nRegisters)
+ {
+ jsFrame = reinterpret_cast<CallData *>(stackSpace);
+ jsFrame->function = function;
+ jsFrame->context = scope->asReturnedValue();
+ jsFrame->accumulator = Encode::undefined();
+ jsFrame->thisObject = thisObject;
+ jsFrame->newTarget = newTarget;
+
+ uint argc = uint(originalArgumentsCount);
+ if (argc > nFormals)
+ argc = nFormals;
+ jsFrame->setArgc(argc);
+
+ memcpy(jsFrame->args, originalArguments, argc*sizeof(Value));
+ const Value *end = jsFrame->args + nRegisters;
+ for (Value *v = jsFrame->args + argc; v < end; ++v)
+ *v = Encode::undefined();
+ }
+#endif
+
+ QString source() const;
+ QString function() const;
+ inline QV4::ExecutionContext *context() const {
+ return static_cast<ExecutionContext *>(&jsFrame->context);
+ }
+ int lineNumber() const;
+
+ inline QV4::Heap::CallContext *callContext() const {
+ Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\
+ while (ctx->type != Heap::ExecutionContext::Type_CallContext)
+ ctx = ctx->outer;
+ return static_cast<Heap::CallContext *>(ctx);
+ }
+ ReturnedValue thisObject() const;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 447992ebec..911103c05d 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -52,8 +52,17 @@ using namespace QV4;
#ifndef V4_BOOTSTRAP
+void Heap::StringOrSymbol::markObjects(Heap::Base *that, MarkStack *markStack)
+{
+ StringOrSymbol *s = static_cast<StringOrSymbol *>(that);
+ Heap::StringOrSymbol *id = s->identifier.asStringOrSymbol();
+ if (id)
+ id->mark(markStack);
+}
+
void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
{
+ StringOrSymbol::markObjects(that, markStack);
String *s = static_cast<String *>(that);
if (s->subtype < StringType_Complex)
return;
@@ -68,15 +77,16 @@ void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
}
}
+DEFINE_MANAGED_VTABLE(StringOrSymbol);
DEFINE_MANAGED_VTABLE(String);
-bool String::isEqualTo(Managed *t, Managed *o)
+bool String::virtualIsEqualTo(Managed *t, Managed *o)
{
if (t == o)
return true;
- if (!o->d()->vtable()->isString)
+ if (!o->vtable()->isString)
return false;
return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
@@ -128,7 +138,8 @@ void Heap::ComplexString::init(Heap::String *ref, int from, int len)
this->len = len;
}
-void Heap::String::destroy() {
+void Heap::StringOrSymbol::destroy()
+{
if (text) {
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar));
if (!text->ref.deref())
@@ -155,12 +166,12 @@ uint String::toUInt(bool *ok) const
return UINT_MAX;
}
-void String::makeIdentifierImpl() const
+void String::createPropertyKeyImpl() const
{
if (!d()->text)
d()->simplifyString();
Q_ASSERT(d()->text);
- engine()->identifierTable->identifier(this);
+ engine()->identifierTable->asPropertyKey(this);
}
void Heap::String::simplifyString() const
@@ -174,7 +185,7 @@ void Heap::String::simplifyString() const
text = result.data_ptr();
text->ref.ref();
const ComplexString *cs = static_cast<const ComplexString *>(this);
- identifier = nullptr;
+ identifier = PropertyKey::invalid();
cs->left = cs->right = nullptr;
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar));
@@ -227,17 +238,26 @@ void Heap::String::append(const String *data, QChar *ch)
}
}
-void Heap::String::createHashValue() const
+void Heap::StringOrSymbol::createHashValue() const
{
- if (!text)
- simplifyString();
+ if (!text) {
+ Q_ASSERT(internalClass->vtable->isString);
+ static_cast<const Heap::String *>(this)->simplifyString();
+ }
Q_ASSERT(text);
const QChar *ch = reinterpret_cast<const QChar *>(text->data());
const QChar *end = ch + text->size;
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
}
-uint String::getLength(const Managed *m)
+PropertyKey StringOrSymbol::toPropertyKey() const {
+ if (d()->identifier.isValid())
+ return d()->identifier;
+ createPropertyKey();
+ return propertyKey();
+}
+
+qint64 String::virtualGetLength(const Managed *m)
{
return static_cast<const String *>(m)->d()->length();
}
@@ -248,4 +268,3 @@ uint String::toArrayIndex(const QString &str)
{
return QV4::String::toArrayIndex(str.constData(), str.constData() + str.length());
}
-
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 5466cc274d..8a4dc08693 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -60,13 +60,14 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct ExecutionEngine;
-struct Identifier;
+struct PropertyKey;
namespace Heap {
-struct Q_QML_PRIVATE_EXPORT String : Base {
- static void markObjects(Heap::Base *that, MarkStack *markStack);
+struct Q_QML_PRIVATE_EXPORT StringOrSymbol : Base
+{
enum StringType {
+ StringType_Symbol,
StringType_Regular,
StringType_ArrayIndex,
StringType_Unknown,
@@ -75,13 +76,20 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
StringType_Complex = StringType_AddedString
};
-#ifndef V4_BOOTSTRAP
- void init(const QString &text);
+ mutable QStringData *text;
+ mutable PropertyKey identifier;
+ mutable uint subtype;
+ mutable uint stringHash;
+
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
void destroy();
- void simplifyString() const;
- int length() const;
- std::size_t retainedTextSize() const {
- return subtype >= StringType_Complex ? 0 : (std::size_t(text->size) * sizeof(QChar));
+
+ inline QString toQString() const {
+ if (!text)
+ return QString();
+ QStringDataPtr ptr = { text };
+ text->ref.ref();
+ return QString(ptr);
}
void createHashValue() const;
inline unsigned hashValue() const {
@@ -91,6 +99,22 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
return stringHash;
}
+};
+
+struct Q_QML_PRIVATE_EXPORT String : StringOrSymbol {
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
+
+#ifndef V4_BOOTSTRAP
+ const VTable *vtable() const {
+ return internalClass->vtable;
+ }
+
+ void init(const QString &text);
+ void simplifyString() const;
+ int length() const;
+ std::size_t retainedTextSize() const {
+ return subtype >= StringType_Complex ? 0 : (std::size_t(text->size) * sizeof(QChar));
+ }
inline QString toQString() const {
if (subtype >= StringType_Complex)
simplifyString();
@@ -104,7 +128,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
if (hashValue() != other->hashValue())
return false;
Q_ASSERT(subtype < StringType_Complex);
- if (identifier && identifier == other->identifier)
+ if (identifier.isValid() && identifier == other->identifier)
return true;
if (subtype == Heap::String::StringType_ArrayIndex && other->subtype == Heap::String::StringType_ArrayIndex)
return true;
@@ -114,10 +138,6 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
bool startsWithUpper() const;
- mutable QStringData *text;
- mutable Identifier *identifier;
- mutable uint subtype;
- mutable uint stringHash;
private:
static void append(const String *data, QChar *ch);
#endif
@@ -146,9 +166,29 @@ int String::length() const {
}
-struct Q_QML_PRIVATE_EXPORT String : public Managed {
+struct Q_QML_PRIVATE_EXPORT StringOrSymbol : public Managed {
#ifndef V4_BOOTSTRAP
- V4_MANAGED(String, Managed)
+ V4_MANAGED(StringOrSymbol, Managed)
+ enum {
+ IsStringOrSymbol = true
+ };
+
+private:
+ inline void createPropertyKey() const;
+public:
+ PropertyKey propertyKey() const { Q_ASSERT(d()->identifier.isValid()); return d()->identifier; }
+ PropertyKey toPropertyKey() const;
+
+
+ inline QString toQString() const {
+ return d()->toQString();
+ }
+#endif
+};
+
+struct Q_QML_PRIVATE_EXPORT String : public StringOrSymbol {
+#ifndef V4_BOOTSTRAP
+ V4_MANAGED(String, StringOrSymbol)
Q_MANAGED_TYPE(String)
V4_INTERNALCLASS(String)
V4_NEEDS_DESTROY
@@ -177,24 +217,10 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
inline unsigned hashValue() const {
return d()->hashValue();
}
- uint asArrayIndex() const {
- if (subtype() >= Heap::String::StringType_Unknown)
- d()->createHashValue();
- Q_ASSERT(d()->subtype < Heap::String::StringType_Complex);
- if (subtype() == Heap::String::StringType_ArrayIndex)
- return d()->stringHash;
- return UINT_MAX;
- }
uint toUInt(bool *ok) const;
- void makeIdentifier() const {
- if (d()->identifier)
- return;
- makeIdentifierImpl();
- }
-
// slow path
- Q_NEVER_INLINE void makeIdentifierImpl() const;
+ Q_NEVER_INLINE void createPropertyKeyImpl() const;
static uint createHashValue(const QChar *ch, int length, uint *subtype)
{
@@ -210,11 +236,9 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
bool startsWithUpper() const { return d()->startsWithUpper(); }
- Identifier *identifier() const { return d()->identifier; }
-
protected:
- static bool isEqualTo(Managed *that, Managed *o);
- static uint getLength(const Managed *m);
+ static bool virtualIsEqualTo(Managed *that, Managed *o);
+ static qint64 virtualGetLength(const Managed *m);
#endif
public:
@@ -254,7 +278,7 @@ public:
uint h = toArrayIndex(ch, end);
if (h != UINT_MAX) {
if (subtype)
- *subtype = Heap::String::StringType_ArrayIndex;
+ *subtype = Heap::StringOrSymbol::StringType_ArrayIndex;
return h;
}
@@ -264,7 +288,7 @@ public:
}
if (subtype)
- *subtype = Heap::String::StringType_Regular;
+ *subtype = (toUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
return h;
}
};
@@ -280,9 +304,22 @@ struct ComplexString : String {
}
};
+inline
+void StringOrSymbol::createPropertyKey() const {
+ if (d()->identifier.isValid())
+ return;
+ Q_ASSERT(isString());
+ static_cast<const String *>(this)->createPropertyKeyImpl();
+}
+
+template<>
+inline const StringOrSymbol *Value::as() const {
+ return isManaged() && m()->internalClass->vtable->isStringOrSymbol ? static_cast<const String *>(this) : nullptr;
+}
+
template<>
inline const String *Value::as() const {
- return isManaged() && m()->vtable()->isString ? static_cast<const String *>(this) : nullptr;
+ return isManaged() && m()->internalClass->vtable->isString ? static_cast<const String *>(this) : nullptr;
}
template<>
diff --git a/src/qml/jsruntime/qv4stringiterator.cpp b/src/qml/jsruntime/qv4stringiterator.cpp
new file mode 100644
index 0000000000..810ed333e4
--- /dev/null
+++ b/src/qml/jsruntime/qv4stringiterator.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qv4iterator_p.h>
+#include <private/qv4stringiterator_p.h>
+#include <private/qv4symbol_p.h>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(StringIteratorObject);
+
+void StringIteratorPrototype::init(ExecutionEngine *e)
+{
+ defineDefaultProperty(QStringLiteral("next"), method_next, 0);
+
+ Scope scope(e);
+ ScopedString val(scope, e->newString(QLatin1String("String Iterator")));
+ defineReadonlyConfigurableProperty(e->symbol_toStringTag(), val);
+}
+
+ReturnedValue StringIteratorPrototype::method_next(const FunctionObject *b, const Value *that, const Value *, int)
+{
+ Scope scope(b);
+ const StringIteratorObject *thisObject = that->as<StringIteratorObject>();
+ if (!thisObject)
+ return scope.engine->throwTypeError(QLatin1String("Not an String Iterator instance"));
+
+ ScopedString s(scope, thisObject->d()->iteratedString);
+ if (!s) {
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+ }
+
+ quint32 index = thisObject->d()->nextIndex;
+
+ QString str = s->toQString();
+ quint32 len = str.length();
+
+ if (index >= len) {
+ thisObject->d()->iteratedString.set(scope.engine, nullptr);
+ QV4::Value undefined = Primitive::undefinedValue();
+ return IteratorPrototype::createIterResultObject(scope.engine, undefined, true);
+ }
+
+ QChar ch = str.at(index);
+ int num = 1;
+ if (ch.unicode() >= 0xd800 && ch.unicode() <= 0xdbff && index + 1 != len) {
+ ch = str.at(index + 1);
+ if (ch.unicode() >= 0xdc00 && ch.unicode() <= 0xdfff)
+ num = 2;
+ }
+
+ thisObject->d()->nextIndex += num;
+
+ ScopedString resultString(scope, scope.engine->newString(s->toQString().mid(index, num)));
+ return IteratorPrototype::createIterResultObject(scope.engine, resultString, false);
+}
+
diff --git a/src/qml/jsruntime/qv4stringiterator_p.h b/src/qml/jsruntime/qv4stringiterator_p.h
new file mode 100644
index 0000000000..672ccc9963
--- /dev/null
+++ b/src/qml/jsruntime/qv4stringiterator_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4STRINGITERATOR_P_H
+#define QV4STRINGITERATOR_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 "qv4object_p.h"
+#include "qv4string_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+namespace QV4 {
+
+namespace Heap {
+
+#define StringIteratorObjectMembers(class, Member) \
+ Member(class, Pointer, String *, iteratedString) \
+ Member(class, NoMark, quint32, nextIndex)
+
+DECLARE_HEAP_OBJECT(StringIteratorObject, Object) {
+ DECLARE_MARKOBJECTS(StringIteratorObject);
+ void init(String *str, QV4::ExecutionEngine *engine)
+ {
+ Object::init();
+ this->iteratedString.set(engine, str);
+ this->nextIndex = 0;
+ }
+};
+
+}
+
+struct StringIteratorPrototype : Object
+{
+ V4_PROTOTYPE(iteratorPrototype)
+ void init(ExecutionEngine *engine);
+
+ static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct StringIteratorObject : Object
+{
+ V4_OBJECT2(StringIteratorObject, Object)
+ Q_MANAGED_TYPE(StringIteratorObject)
+ V4_PROTOTYPE(stringIteratorPrototype)
+
+ void init(ExecutionEngine *engine);
+};
+
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4ARRAYITERATOR_P_H
+
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 61176b3706..f2d0d52013 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -44,8 +44,10 @@
#include "qv4objectproto_p.h"
#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
+#include "qv4symbol_p.h"
#include "qv4alloca_p.h"
#include "qv4jscall_p.h"
+#include "qv4stringiterator_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
@@ -95,19 +97,19 @@ uint Heap::StringObject::length() const
return string->length();
}
-bool StringObject::deleteIndexedProperty(Managed *m, uint index)
+bool StringObject::virtualDeleteProperty(Managed *m, PropertyKey id)
{
- ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine();
- Scope scope(v4);
- Scoped<StringObject> o(scope, m->as<StringObject>());
- Q_ASSERT(!!o);
-
- if (index < static_cast<uint>(o->d()->string->toQString().length()))
- return false;
- return true;
+ Q_ASSERT(m->as<StringObject>());
+ if (id.isArrayIndex()) {
+ StringObject *o = static_cast<StringObject *>(m);
+ uint index = id.asArrayIndex();
+ if (index < static_cast<uint>(o->d()->string->toQString().length()))
+ return false;
+ }
+ return Object::virtualDeleteProperty(m, id);
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
name->setM(nullptr);
StringObject *s = static_cast<StringObject *>(m);
@@ -116,9 +118,8 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name,
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
- PropertyAttributes a;
Property pd;
- s->getOwnProperty(*index, &a, &pd);
+ PropertyAttributes a = s->getOwnProperty(PropertyKey::fromArrayIndex(*index), &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
p->copy(&pd, a);
@@ -133,7 +134,27 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name,
}
}
- return Object::advanceIterator(m, it, name, index, p, attrs);
+ return Object::virtualAdvanceIterator(m, it, name, index, p, attrs);
+}
+
+PropertyAttributes StringObject::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
+{
+ PropertyAttributes attributes = Object::virtualGetOwnProperty(m, id, p);
+ if (attributes != Attr_Invalid)
+ return attributes;
+
+ Object *o = static_cast<Object *>(m);
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if (o->isStringObject()) {
+ if (index >= static_cast<const StringObject *>(m)->length())
+ return Attr_Invalid;
+ if (p)
+ p->value = static_cast<StringObject *>(o)->getIndex(index);
+ return Attr_NotConfigurable|Attr_NotWritable;
+ }
+ }
+ return Attr_Invalid;
}
DEFINE_OBJECT_VTABLE(StringCtor);
@@ -143,7 +164,7 @@ void Heap::StringCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("String"));
}
-ReturnedValue StringCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue StringCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
ExecutionEngine *v4 = static_cast<const Object *>(f)->engine();
Scope scope(v4);
@@ -152,16 +173,58 @@ ReturnedValue StringCtor::callAsConstructor(const FunctionObject *f, const Value
value = argv[0].toString(v4);
else
value = v4->newString();
+ CHECK_EXCEPTION();
return Encode(v4->newStringObject(value));
}
-ReturnedValue StringCtor::call(const FunctionObject *m, const Value *, const Value *argv, int argc)
+ReturnedValue StringCtor::virtualCall(const FunctionObject *m, const Value *, const Value *argv, int argc)
{
ExecutionEngine *v4 = m->engine();
- if (argc)
- return argv[0].toString(v4)->asReturnedValue();
- else
+ if (!argc)
return v4->newString()->asReturnedValue();
+ if (argv[0].isSymbol())
+ return v4->newString(argv[0].symbolValue()->descriptiveString())->asReturnedValue();
+ return argv[0].toString(v4)->asReturnedValue();
+}
+
+ReturnedValue StringCtor::method_fromCharCode(const FunctionObject *b, const Value *, const Value *argv, int argc)
+{
+ QString str(argc, Qt::Uninitialized);
+ QChar *ch = str.data();
+ for (int i = 0, ei = argc; i < ei; ++i) {
+ *ch = QChar(argv[i].toUInt16());
+ ++ch;
+ }
+ *ch = 0;
+ return Encode(b->engine()->newString(str));
+}
+
+
+
+ReturnedValue StringCtor::method_fromCodePoint(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ ExecutionEngine *e = f->engine();
+ QString result(argc*2, Qt::Uninitialized); // assume worst case
+ QChar *ch = result.data();
+ for (int i = 0; i < argc; ++i) {
+ double num = argv[i].toNumber();
+ if (e->hasException)
+ return Encode::undefined();
+ int cp = static_cast<int>(num);
+ if (cp != num || cp < 0 || cp > 0x10ffff)
+ return e->throwRangeError(QStringLiteral("String.fromCodePoint: argument out of range."));
+ if (cp > 0xffff) {
+ *ch = QChar::highSurrogate(cp);
+ ++ch;
+ *ch = QChar::lowSurrogate(cp);
+ } else {
+ *ch = cp;
+ }
+ ++ch;
+ }
+ *ch = 0;
+ result.truncate(ch - result.constData());
+ return e->newString(result)->asReturnedValue();
}
void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
@@ -169,15 +232,23 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
+ // need to set this once again, as these were not fully defined when creating the string proto
+ Heap::InternalClass *ic = scope.engine->classes[ExecutionEngine::Class_StringObject]->changePrototype(scope.engine->objectPrototype()->d());
+ d()->internalClass.set(scope.engine, ic);
+ d()->string.set(scope.engine, scope.engine->id_empty()->d());
+ setProperty(scope.engine, Heap::StringObject::LengthPropertyIndex, Primitive::fromInt32(0));
+
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
- ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), method_fromCharCode, 1);
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), StringCtor::method_fromCharCode, 1);
+ ctor->defineDefaultProperty(QStringLiteral("fromCodePoint"), StringCtor::method_fromCodePoint, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString);
defineDefaultProperty(engine->id_valueOf(), method_toString); // valueOf and toString are identical
defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1);
defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1);
+ defineDefaultProperty(QStringLiteral("codePointAt"), method_codePointAt, 1);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
defineDefaultProperty(QStringLiteral("endsWith"), method_endsWith, 1);
defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1);
@@ -185,6 +256,9 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1);
defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare, 1);
defineDefaultProperty(QStringLiteral("match"), method_match, 1);
+ defineDefaultProperty(QStringLiteral("normalize"), method_normalize, 0);
+ defineDefaultProperty(QStringLiteral("padEnd"), method_padEnd, 1);
+ defineDefaultProperty(QStringLiteral("padStart"), method_padStart, 1);
defineDefaultProperty(QStringLiteral("repeat"), method_repeat, 1);
defineDefaultProperty(QStringLiteral("replace"), method_replace, 2);
defineDefaultProperty(QStringLiteral("search"), method_search, 1);
@@ -198,6 +272,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("toUpperCase"), method_toUpperCase);
defineDefaultProperty(QStringLiteral("toLocaleUpperCase"), method_toLocaleUpperCase);
defineDefaultProperty(QStringLiteral("trim"), method_trim);
+ defineDefaultProperty(engine->symbol_iterator(), method_iterator);
}
static Heap::String *thisAsString(ExecutionEngine *v4, const QV4::Value *thisObject)
@@ -270,6 +345,29 @@ ReturnedValue StringPrototype::method_charCodeAt(const FunctionObject *b, const
return Encode(qt_qnan());
}
+ReturnedValue StringPrototype::method_codePointAt(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *v4 = f->engine();
+ QString value = getThisString(v4, thisObject);
+ if (v4->hasException)
+ return QV4::Encode::undefined();
+
+ int index = argc ? argv[0].toInteger() : 0;
+ if (v4->hasException)
+ return QV4::Encode::undefined();
+
+ if (index < 0 || index >= value.size())
+ return Encode::undefined();
+
+ uint first = value.at(index).unicode();
+ if (QChar::isHighSurrogate(first) && index + 1 < value.size()) {
+ uint second = value.at(index + 1).unicode();
+ if (QChar::isLowSurrogate(second))
+ return Encode(QChar::surrogateToUcs4(first, second));
+ }
+ return Encode(first);
+}
+
ReturnedValue StringPrototype::method_concat(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
ExecutionEngine *v4 = b->engine();
@@ -298,12 +396,11 @@ ReturnedValue StringPrototype::method_endsWith(const FunctionObject *b, const Va
if (v4->hasException)
return QV4::Encode::undefined();
- QString searchString;
- if (argc) {
- if (argv[0].as<RegExpObject>())
- return v4->throwTypeError();
- searchString = argv[0].toQString();
- }
+ if (argc && argv[0].as<RegExpObject>())
+ return v4->throwTypeError();
+ QString searchString = (argc ? argv[0] : Primitive::undefinedValue()).toQString();
+ if (v4->hasException)
+ return Encode::undefined();
int pos = value.length();
if (argc > 1)
@@ -323,9 +420,9 @@ ReturnedValue StringPrototype::method_indexOf(const FunctionObject *b, const Val
if (v4->hasException)
return QV4::Encode::undefined();
- QString searchString;
- if (argc)
- searchString = argv[0].toQString();
+ QString searchString = (argc ? argv[0] : Primitive::undefinedValue()).toQString();
+ if (v4->hasException)
+ return Encode::undefined();
int pos = 0;
if (argc > 1)
@@ -345,12 +442,11 @@ ReturnedValue StringPrototype::method_includes(const FunctionObject *b, const Va
if (v4->hasException)
return QV4::Encode::undefined();
- QString searchString;
- if (argc) {
- if (argv[0].as<RegExpObject>())
- return v4->throwTypeError();
- searchString = argv[0].toQString();
- }
+ if (argc && argv[0].as<RegExpObject>())
+ return v4->throwTypeError();
+ QString searchString = (argc ? argv[0] : Primitive::undefinedValue()).toQString();
+ if (v4->hasException)
+ return Encode::undefined();
int pos = 0;
if (argc > 1) {
@@ -374,9 +470,9 @@ ReturnedValue StringPrototype::method_lastIndexOf(const FunctionObject *b, const
if (v4->hasException)
return QV4::Encode::undefined();
- QString searchString;
- if (argc)
- searchString = argv[0].toQString();
+ QString searchString = (argc ? argv[0] : Primitive::undefinedValue()).toQString();
+ if (v4->hasException)
+ return Encode::undefined();
double position = argc > 1 ? RuntimeHelpers::toNumber(argv[1]) : +qInf();
if (std::isnan(position))
@@ -418,7 +514,7 @@ ReturnedValue StringPrototype::method_match(const FunctionObject *b, const Value
Scoped<RegExpObject> that(scope, argc ? argv[0] : Primitive::undefinedValue());
if (!that) {
// convert args[0] to a regexp
- that = RegExpCtor::callAsConstructor(b, argv, argc);
+ that = RegExpCtor::virtualCallAsConstructor(b, argv, argc, b);
if (v4->hasException)
return Encode::undefined();
}
@@ -455,6 +551,115 @@ ReturnedValue StringPrototype::method_match(const FunctionObject *b, const Value
return a.asReturnedValue();
}
+ReturnedValue StringPrototype::method_normalize(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *v4 = f->engine();
+ const QString value = getThisString(v4, thisObject);
+ if (v4->hasException)
+ return Encode::undefined();
+
+ QString::NormalizationForm form = QString::NormalizationForm_C;
+ if (argc >= 1 && !argv[0].isUndefined()) {
+ QString f = argv[0].toQString();
+ if (v4->hasException)
+ return Encode::undefined();
+ if (f == QLatin1String("NFC"))
+ form = QString::NormalizationForm_C;
+ else if (f == QLatin1String("NFD"))
+ form = QString::NormalizationForm_D;
+ else if (f == QLatin1String("NFKC"))
+ form = QString::NormalizationForm_KC;
+ else if (f == QLatin1String("NFKD"))
+ form = QString::NormalizationForm_KD;
+ else
+ return v4->throwRangeError(QLatin1String("String.prototype.normalize: Invalid normalization form."));
+ }
+ QString normalized = value.normalized(form);
+ return v4->newString(normalized)->asReturnedValue();
+}
+
+ReturnedValue StringPrototype::method_padEnd(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *v4 = f->engine();
+ if (thisObject->isNullOrUndefined())
+ return v4->throwTypeError();
+
+ Scope scope(v4);
+ ScopedString s(scope, thisAsString(v4, thisObject));
+ if (v4->hasException)
+ return Encode::undefined();
+ if (!argc)
+ return s->asReturnedValue();
+
+ int maxLen = argv[0].toInteger();
+ if (maxLen <= s->d()->length())
+ return s->asReturnedValue();
+ QString fillString = (argc > 1 && !argv[1].isUndefined()) ? argv[1].toQString() : QString::fromLatin1(" ");
+ if (v4->hasException)
+ return Encode::undefined();
+
+ if (fillString.isEmpty())
+ return s->asReturnedValue();
+
+ QString padded = s->toQString();
+ int oldLength = padded.length();
+ int toFill = maxLen - oldLength;
+ padded.resize(maxLen);
+ QChar *ch = padded.data() + oldLength;
+ while (toFill) {
+ int copy = qMin(fillString.length(), toFill);
+ memcpy(ch, fillString.constData(), copy*sizeof(QChar));
+ toFill -= copy;
+ ch += copy;
+ }
+ *ch = 0;
+
+ return v4->newString(padded)->asReturnedValue();
+}
+
+ReturnedValue StringPrototype::method_padStart(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ ExecutionEngine *v4 = f->engine();
+ if (thisObject->isNullOrUndefined())
+ return v4->throwTypeError();
+
+ Scope scope(v4);
+ ScopedString s(scope, thisAsString(v4, thisObject));
+ if (v4->hasException)
+ return Encode::undefined();
+ if (!argc)
+ return s->asReturnedValue();
+
+ int maxLen = argv[0].toInteger();
+ if (maxLen <= s->d()->length())
+ return s->asReturnedValue();
+ QString fillString = (argc > 1 && !argv[1].isUndefined()) ? argv[1].toQString() : QString::fromLatin1(" ");
+ if (v4->hasException)
+ return Encode::undefined();
+
+ if (fillString.isEmpty())
+ return s->asReturnedValue();
+
+ QString original = s->toQString();
+ int oldLength = original.length();
+ int toFill = maxLen - oldLength;
+ QString padded;
+ padded.resize(maxLen);
+ QChar *ch = padded.data();
+ while (toFill) {
+ int copy = qMin(fillString.length(), toFill);
+ memcpy(ch, fillString.constData(), copy*sizeof(QChar));
+ toFill -= copy;
+ ch += copy;
+ }
+ memcpy(ch, original.constData(), oldLength*sizeof(QChar));
+ ch += oldLength;
+ *ch = 0;
+
+ return v4->newString(padded)->asReturnedValue();
+}
+
+
ReturnedValue StringPrototype::method_repeat(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
ExecutionEngine *v4 = b->engine();
@@ -777,12 +982,11 @@ ReturnedValue StringPrototype::method_startsWith(const FunctionObject *b, const
if (v4->hasException)
return QV4::Encode::undefined();
- QString searchString;
- if (argc) {
- if (argv[0].as<RegExpObject>())
- return v4->throwTypeError();
- searchString = argv[0].toQString();
- }
+ if (argc && argv[0].as<RegExpObject>())
+ return v4->throwTypeError();
+ QString searchString = (argc ? argv[0] : Primitive::undefinedValue()).toQString();
+ if (v4->hasException)
+ return Encode::undefined();
int pos = 0;
if (argc > 1)
@@ -892,17 +1096,6 @@ ReturnedValue StringPrototype::method_toLocaleUpperCase(const FunctionObject *b,
return method_toUpperCase(b, thisObject, argv, argc);
}
-ReturnedValue StringPrototype::method_fromCharCode(const FunctionObject *b, const Value *, const Value *argv, int argc)
-{
- QString str(argc, Qt::Uninitialized);
- QChar *ch = str.data();
- for (int i = 0, ei = argc; i < ei; ++i) {
- *ch = QChar(argv[i].toUInt16());
- ++ch;
- }
- return Encode(b->engine()->newString(str));
-}
-
ReturnedValue StringPrototype::method_trim(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
@@ -923,3 +1116,16 @@ ReturnedValue StringPrototype::method_trim(const FunctionObject *b, const Value
return Encode(v4->newString(QString(chars + start, end - start + 1)));
}
+
+
+
+ReturnedValue StringPrototype::method_iterator(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ ScopedString s(scope, thisObject->toString(scope.engine));
+ if (!s || thisObject->isNullOrUndefined())
+ return scope.engine->throwTypeError();
+
+ Scoped<StringIteratorObject> si(scope, scope.engine->memoryManager->allocate<StringIteratorObject>(s->d(), scope.engine));
+ return si->asReturnedValue();
+}
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 7d25678b61..2d37e36b34 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -70,6 +70,8 @@ DECLARE_HEAP_OBJECT(StringObject, Object) {
LengthPropertyIndex = 0
};
+ void init(bool /*don't init*/)
+ { Object::init(); }
void init();
void init(const QV4::String *string);
@@ -96,18 +98,22 @@ struct StringObject: Object {
return d()->length();
}
- static bool deleteIndexedProperty(Managed *m, uint index);
-
+ using Object::getOwnProperty;
protected:
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
+ static bool virtualDeleteProperty(Managed *m, PropertyKey id);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
};
struct StringCtor: FunctionObject
{
V4_OBJECT2(StringCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_fromCharCode(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_fromCodePoint(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
struct StringPrototype: StringObject
@@ -118,6 +124,7 @@ struct StringPrototype: StringObject
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_charAt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_charCodeAt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_codePointAt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_concat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_endsWith(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_indexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
@@ -125,6 +132,9 @@ struct StringPrototype: StringObject
static ReturnedValue method_lastIndexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_localeCompare(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_match(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_normalize(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_padEnd(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_padStart(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_repeat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_replace(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_search(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
@@ -137,8 +147,8 @@ struct StringPrototype: StringObject
static ReturnedValue method_toLocaleLowerCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toUpperCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_toLocaleUpperCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_fromCharCode(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_trim(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_iterator(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
}
diff --git a/src/qml/jsruntime/qv4symbol.cpp b/src/qml/jsruntime/qv4symbol.cpp
new file mode 100644
index 0000000000..bdefe1eb9e
--- /dev/null
+++ b/src/qml/jsruntime/qv4symbol.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qv4symbol_p.h>
+#include <qv4functionobject_p.h>
+#include <qv4identifiertable_p.h>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(SymbolCtor);
+DEFINE_MANAGED_VTABLE(Symbol);
+DEFINE_OBJECT_VTABLE(SymbolObject);
+
+void Heap::Symbol::init(const QString &s)
+{
+ Q_ASSERT(s.at(0) == QLatin1Char('@'));
+ identifier = PropertyKey::fromStringOrSymbol(this);
+ QString desc(s);
+ text = desc.data_ptr();
+ text->ref.ref();
+}
+
+void Heap::SymbolCtor::init(QV4::ExecutionContext *scope)
+{
+ Heap::FunctionObject::init(scope, QStringLiteral("Symbol"));
+}
+
+void Heap::SymbolObject::init(const QV4::Symbol *s)
+{
+ Object::init();
+ symbol.set(internalClass->engine, s->d());
+}
+
+ReturnedValue QV4::SymbolCtor::virtualCall(const QV4::FunctionObject *f, const QV4::Value *, const QV4::Value *argv, int argc)
+{
+ Scope scope(f);
+ QString desc = QChar::fromLatin1('@');
+ if (argc && !argv[0].isUndefined()) {
+ ScopedString s(scope, argv[0].toString(scope.engine));
+ if (scope.hasException())
+ return Encode::undefined();
+ desc += s->toQString();
+ }
+ return Symbol::create(scope.engine, desc)->asReturnedValue();
+}
+
+ReturnedValue SymbolCtor::method_for(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ Scope scope(f);
+ ScopedValue k(scope, argc ? argv[0]: Primitive::undefinedValue());
+ ScopedString key(scope, k->toString(scope.engine));
+ if (scope.hasException())
+ return Encode::undefined();
+ QString desc = QLatin1Char('@') + key->toQString();
+ return scope.engine->identifierTable->insertSymbol(desc)->asReturnedValue();
+}
+
+ReturnedValue SymbolCtor::method_keyFor(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ ExecutionEngine *e = f->engine();
+ if (!argc || !argv[0].isSymbol())
+ return e->throwTypeError(QLatin1String("Symbol.keyFor: Argument is not a symbol."));
+ const Symbol &arg = static_cast<const Symbol &>(argv[0]);
+ Heap::Symbol *s = e->identifierTable->symbolForId(arg.propertyKey());
+ Q_ASSERT(!s || s == arg.d());
+ if (s)
+ return e->newString(arg.toQString().mid((1)))->asReturnedValue();
+ return Encode::undefined();
+}
+
+void SymbolPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Scope scope(engine);
+ ScopedValue v(scope);
+ ctor->defineReadonlyProperty(engine->id_prototype(), (v = this));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
+
+ ctor->defineDefaultProperty(QStringLiteral("for"), SymbolCtor::method_for, 1);
+ ctor->defineDefaultProperty(QStringLiteral("keyFor"), SymbolCtor::method_keyFor, 1);
+ ctor->defineReadonlyProperty(QStringLiteral("hasInstance"), *engine->symbol_hasInstance());
+ ctor->defineReadonlyProperty(QStringLiteral("isConcatSpreadable"), *engine->symbol_isConcatSpreadable());
+ ctor->defineReadonlyProperty(QStringLiteral("iterator"), *engine->symbol_iterator());
+ ctor->defineReadonlyProperty(QStringLiteral("match"), *engine->symbol_match());
+ ctor->defineReadonlyProperty(QStringLiteral("replace"), *engine->symbol_replace());
+ ctor->defineReadonlyProperty(QStringLiteral("search"), *engine->symbol_search());
+ ctor->defineReadonlyProperty(QStringLiteral("species"), *engine->symbol_species());
+ ctor->defineReadonlyProperty(QStringLiteral("split"), *engine->symbol_split());
+ ctor->defineReadonlyProperty(QStringLiteral("toPrimitive"), *engine->symbol_toPrimitive());
+ ctor->defineReadonlyProperty(QStringLiteral("toStringTag"), *engine->symbol_toStringTag());
+ ctor->defineReadonlyProperty(QStringLiteral("unscopables"), *engine->symbol_unscopables());
+
+ defineDefaultProperty(QStringLiteral("constructor"), (v = ctor));
+ defineDefaultProperty(QStringLiteral("toString"), method_toString);
+ defineDefaultProperty(QStringLiteral("valueOf"), method_valueOf);
+ defineDefaultProperty(engine->symbol_toPrimitive(), method_symbolToPrimitive, 1, Attr_ReadOnly_ButConfigurable);
+
+ v = engine->newString(QStringLiteral("Symbol"));
+ defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), v);
+
+}
+
+ReturnedValue SymbolPrototype::method_toString(const FunctionObject *f, const Value *thisObject, const Value *, int)
+{
+ Scope scope(f);
+ Scoped<Symbol> s(scope, thisObject->as<Symbol>());
+ if (!s) {
+ if (const SymbolObject *o = thisObject->as<SymbolObject>())
+ s = o->d()->symbol;
+ else
+ return scope.engine->throwTypeError();
+ }
+ return scope.engine->newString(s->descriptiveString())->asReturnedValue();
+}
+
+ReturnedValue SymbolPrototype::method_valueOf(const FunctionObject *f, const Value *thisObject, const Value *, int)
+{
+ Scope scope(f);
+ Scoped<Symbol> s(scope, thisObject->as<Symbol>());
+ if (!s) {
+ if (const SymbolObject *o = thisObject->as<SymbolObject>())
+ s = o->d()->symbol;
+ else
+ return scope.engine->throwTypeError();
+ }
+ return s->asReturnedValue();
+}
+
+ReturnedValue SymbolPrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int)
+{
+ if (thisObject->isSymbol())
+ return thisObject->asReturnedValue();
+ if (const SymbolObject *o = thisObject->as<SymbolObject>())
+ return o->d()->symbol->asReturnedValue();
+ return f->engine()->throwTypeError();
+}
+
+Heap::Symbol *Symbol::create(ExecutionEngine *e, const QString &s)
+{
+ Q_ASSERT(s.at(0) == QLatin1Char('@'));
+ return e->memoryManager->alloc<Symbol>(s);
+}
+
+QString Symbol::descriptiveString() const
+{
+ return QLatin1String("Symbol(") + toQString().midRef(1) + QLatin1String(")");
+}
diff --git a/src/qml/jsruntime/qv4symbol_p.h b/src/qml/jsruntime/qv4symbol_p.h
new file mode 100644
index 0000000000..46fa2979f8
--- /dev/null
+++ b/src/qml/jsruntime/qv4symbol_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4_SYMBOL_H
+#define QV4_SYMBOL_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 "qv4string_p.h"
+#include "qv4functionobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+namespace QV4 {
+
+namespace Heap {
+
+struct SymbolCtor : FunctionObject {
+ void init(QV4::ExecutionContext *scope);
+};
+
+struct Symbol : StringOrSymbol {
+ void init(const QString &s);
+};
+
+#define SymbolObjectMembers(class, Member) \
+ Member(class, Pointer, Symbol *, symbol)
+
+DECLARE_HEAP_OBJECT(SymbolObject, Object) {
+ DECLARE_MARKOBJECTS(SymbolObject);
+ void init(const QV4::Symbol *s);
+};
+
+}
+
+struct SymbolCtor : FunctionObject
+{
+ V4_OBJECT2(SymbolCtor, FunctionObject)
+
+ static ReturnedValue virtualCall(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_for(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_keyFor(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct SymbolPrototype : Object
+{
+ V4_PROTOTYPE(objectPrototype)
+ void init(ExecutionEngine *engine, Object *ctor);
+
+ static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_symbolToPrimitive(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+};
+
+struct Symbol : StringOrSymbol
+{
+ V4_MANAGED(Symbol, StringOrSymbol)
+ Q_MANAGED_TYPE(Symbol)
+ V4_INTERNALCLASS(Symbol)
+ V4_NEEDS_DESTROY
+
+ static Heap::Symbol *create(ExecutionEngine *e, const QString &s);
+
+ QString descriptiveString() const;
+};
+
+struct SymbolObject : Object
+{
+ V4_OBJECT2(SymbolObject, Object)
+ Q_MANAGED_TYPE(SymbolObject)
+ V4_INTERNALCLASS(SymbolObject)
+ V4_PROTOTYPE(symbolPrototype)
+
+ static bool virtualPut(Managed *, PropertyKey, const Value &, Value *) { return false; }
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index ea1532b8ce..cb9cdd8df5 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -36,15 +36,20 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#include "qv4typedarray_p.h"
+#include "qv4arrayiterator_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4string_p.h"
#include "qv4jscall_p.h"
+#include "qv4symbol_p.h"
#include <cmath>
using namespace QV4;
+DEFINE_OBJECT_VTABLE(IntrinsicTypedArrayCtor);
+DEFINE_OBJECT_VTABLE(IntrinsicTypedArrayPrototype);
DEFINE_OBJECT_VTABLE(TypedArrayCtor);
DEFINE_OBJECT_VTABLE(TypedArrayPrototype);
DEFINE_OBJECT_VTABLE(TypedArray);
@@ -209,16 +214,19 @@ void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t
type = t;
}
-ReturnedValue TypedArrayCtor::callAsConstructor(const FunctionObject *f, const Value *argv, int argc)
+ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
{
Scope scope(f->engine());
const TypedArrayCtor *that = static_cast<const TypedArrayCtor *>(f);
if (!argc || !argv[0].isObject()) {
// ECMA 6 22.2.1.1
- double l = argc ? argv[0].toNumber() : 0;
+ qint64 l = argc ? argv[0].toIndex() : 0;
if (scope.engine->hasException)
return Encode::undefined();
+ // ### lift UINT_MAX restriction
+ if (l < 0 || l > UINT_MAX)
+ return scope.engine->throwRangeError(QLatin1String("Index out of range."));
uint len = (uint)l;
if (l != len)
scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array."));
@@ -312,7 +320,10 @@ ReturnedValue TypedArrayCtor::callAsConstructor(const FunctionObject *f, const V
return scope.engine->throwTypeError();
uint elementSize = operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(l * elementSize));
+ size_t bufferSize;
+ if (mul_overflow(size_t(l), size_t(elementSize), &bufferSize))
+ return scope.engine->throwRangeError(QLatin1String("new TypedArray: invalid length"));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(bufferSize));
if (scope.engine->hasException)
return Encode::undefined();
@@ -325,7 +336,7 @@ ReturnedValue TypedArrayCtor::callAsConstructor(const FunctionObject *f, const V
char *b = newBuffer->d()->data->data();
ScopedValue val(scope);
while (idx < l) {
- val = o->getIndexed(idx);
+ val = o->get(idx);
array->d()->type->write(scope.engine, b, 0, val);
if (scope.engine->hasException)
return Encode::undefined();
@@ -337,9 +348,9 @@ ReturnedValue TypedArrayCtor::callAsConstructor(const FunctionObject *f, const V
return array.asReturnedValue();
}
-ReturnedValue TypedArrayCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
+ReturnedValue TypedArrayCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
{
- return callAsConstructor(f, argv, argc);
+ return f->engine()->throwTypeError(QStringLiteral("calling a TypedArray constructor without new is invalid"));
}
void Heap::TypedArray::init(Type t)
@@ -351,13 +362,17 @@ void Heap::TypedArray::init(Type t)
Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
{
- QV4::InternalClass *ic = e->internalClasses[EngineBase::Class_Empty]->changeVTable(staticVTable());
- ic = ic->changePrototype(e->typedArrayPrototype[t].d());
- return e->memoryManager->allocObject<TypedArray>(ic, e->typedArrayPrototype + t, t);
+ Scope scope(e);
+ Scoped<InternalClass> ic(scope, e->newInternalClass(staticVTable(), e->typedArrayPrototype + t));
+ return e->memoryManager->allocObject<TypedArray>(ic->d(), t);
}
-ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty)
+ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
+ if (!id.isArrayIndex())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
+ uint index = id.asArrayIndex();
Scope scope(static_cast<const Object *>(m)->engine());
Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
@@ -373,8 +388,12 @@ ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProp
return a->d()->type->read(a->d()->buffer->data->data(), byteOffset);
}
-bool TypedArray::putIndexed(Managed *m, uint index, const Value &value)
+bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
+ if (!id.isArrayIndex())
+ return Object::virtualPut(m, id, value, receiver);
+
+ uint index = id.asArrayIndex();
ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
if (v4->hasException)
return false;
@@ -395,21 +414,18 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), *this);
ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
+ ctor->setPrototypeOf(engine->intrinsicTypedArrayCtor());
+
+ setPrototypeOf(engine->intrinsicTypedArrayPrototype());
defineDefaultProperty(engine->id_constructor(), (o = ctor));
- defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, nullptr);
- defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
- defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, nullptr);
- defineAccessorProperty(QStringLiteral("length"), method_get_length, nullptr);
defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
-
- defineDefaultProperty(QStringLiteral("set"), method_set, 1);
- defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0);
}
-ReturnedValue TypedArrayPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int)
+ReturnedValue IntrinsicTypedArrayPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
const TypedArray *v = thisObject->as<TypedArray>();
@@ -419,7 +435,7 @@ ReturnedValue TypedArrayPrototype::method_get_buffer(const FunctionObject *b, co
return v->d()->buffer->asReturnedValue();
}
-ReturnedValue TypedArrayPrototype::method_get_byteLength(const FunctionObject *b, const Value *thisObject, const Value *, int)
+ReturnedValue IntrinsicTypedArrayPrototype::method_get_byteLength(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
const TypedArray *v = thisObject->as<TypedArray>();
@@ -429,7 +445,7 @@ ReturnedValue TypedArrayPrototype::method_get_byteLength(const FunctionObject *b
return Encode(v->d()->byteLength);
}
-ReturnedValue TypedArrayPrototype::method_get_byteOffset(const FunctionObject *b, const Value *thisObject, const Value *, int)
+ReturnedValue IntrinsicTypedArrayPrototype::method_get_byteOffset(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
const TypedArray *v = thisObject->as<TypedArray>();
@@ -439,7 +455,7 @@ ReturnedValue TypedArrayPrototype::method_get_byteOffset(const FunctionObject *b
return Encode(v->d()->byteOffset);
}
-ReturnedValue TypedArrayPrototype::method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
+ReturnedValue IntrinsicTypedArrayPrototype::method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
const TypedArray *v = thisObject->as<TypedArray>();
@@ -449,7 +465,43 @@ ReturnedValue TypedArrayPrototype::method_get_length(const FunctionObject *b, co
return Encode(v->d()->byteLength/v->d()->type->bytesPerElement);
}
-ReturnedValue TypedArrayPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue IntrinsicTypedArrayPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<TypedArray> O(scope, thisObject);
+ if (!O)
+ THROW_TYPE_ERROR();
+
+ Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
+ ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue IntrinsicTypedArrayPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<TypedArray> O(scope, thisObject);
+ if (!O)
+ THROW_TYPE_ERROR();
+
+ Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
+ ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue IntrinsicTypedArrayPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
+{
+ Scope scope(b);
+ Scoped<TypedArray> O(scope, thisObject);
+ if (!O)
+ THROW_TYPE_ERROR();
+
+ Scoped<ArrayIteratorObject> ao(scope, scope.engine->newArrayIteratorObject(O));
+ ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
+ return ao->asReturnedValue();
+}
+
+ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
Scoped<TypedArray> a(scope, *thisObject);
@@ -487,7 +539,7 @@ ReturnedValue TypedArrayPrototype::method_set(const FunctionObject *b, const Val
char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
ScopedValue val(scope);
while (idx < l) {
- val = o->getIndexed(idx);
+ val = o->get(idx);
a->d()->type->write(scope.engine, b, 0, val);
if (scope.engine->hasException)
RETURN_UNDEFINED();
@@ -538,7 +590,7 @@ ReturnedValue TypedArrayPrototype::method_set(const FunctionObject *b, const Val
RETURN_UNDEFINED();
}
-ReturnedValue TypedArrayPrototype::method_subarray(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue IntrinsicTypedArrayPrototype::method_subarray(const FunctionObject *builtin, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(builtin);
Scoped<TypedArray> a(scope, *thisObject);
@@ -578,3 +630,47 @@ ReturnedValue TypedArrayPrototype::method_subarray(const FunctionObject *builtin
arguments[2] = Encode(newLen);
return constructor->callAsConstructor(arguments, 3);
}
+
+ReturnedValue IntrinsicTypedArrayPrototype::method_get_toStringTag(const FunctionObject *, const Value *thisObject, const Value *, int)
+{
+ const TypedArray *a = thisObject->as<TypedArray>();
+ if (!a)
+ return Encode::undefined();
+
+ return a->engine()->newString(QString::fromLatin1(a->d()->type->name))->asReturnedValue();
+}
+
+ReturnedValue IntrinsicTypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
+{
+ return f->engine()->throwTypeError();
+}
+
+ReturnedValue IntrinsicTypedArrayCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
+{
+ return f->engine()->throwTypeError();
+}
+
+void IntrinsicTypedArrayPrototype::init(ExecutionEngine *engine, IntrinsicTypedArrayCtor *ctor)
+{
+ ctor->defineReadonlyProperty(engine->id_prototype(), *this);
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
+ ctor->addSymbolSpecies();
+
+ defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, nullptr);
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
+ defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, nullptr);
+ defineAccessorProperty(QStringLiteral("length"), method_get_length, nullptr);
+
+ defineDefaultProperty(QStringLiteral("entries"), method_entries, 0);
+ defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
+ defineDefaultProperty(QStringLiteral("set"), method_set, 1);
+ defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0);
+
+ Scope scope(engine);
+ ScopedString valuesString(scope, engine->newIdentifier(QStringLiteral("values")));
+ ScopedObject values(scope, FunctionObject::createBuiltinFunction(engine, valuesString, method_values, 0));
+ defineDefaultProperty(QStringLiteral("values"), values);
+ defineDefaultProperty(engine->symbol_iterator(), values);
+
+ defineAccessorProperty(engine->symbol_toStringTag(), method_get_toStringTag, nullptr);
+}
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 129c662c97..967d3235b2 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -97,12 +97,18 @@ DECLARE_HEAP_OBJECT(TypedArray, Object) {
void init(Type t);
};
+struct IntrinsicTypedArrayCtor : FunctionObject {
+};
+
struct TypedArrayCtor : FunctionObject {
void init(QV4::ExecutionContext *scope, TypedArray::Type t);
TypedArray::Type type;
};
+struct IntrinsicTypedArrayPrototype : Object {
+};
+
struct TypedArrayPrototype : Object {
inline void init(TypedArray::Type t);
TypedArray::Type type;
@@ -132,34 +138,56 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
Heap::TypedArray::Type arrayType() const {
return static_cast<Heap::TypedArray::Type>(d()->arrayType);
}
+ using Object::get;
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool putIndexed(Managed *m, uint index, const Value &value);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+};
+
+struct IntrinsicTypedArrayCtor: FunctionObject
+{
+ V4_OBJECT2(IntrinsicTypedArrayCtor, FunctionObject)
+
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
struct TypedArrayCtor: FunctionObject
{
V4_OBJECT2(TypedArrayCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
+ static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
-
-struct TypedArrayPrototype : Object
+struct IntrinsicTypedArrayPrototype : Object
{
- V4_OBJECT2(TypedArrayPrototype, Object)
+ V4_OBJECT2(IntrinsicTypedArrayPrototype, Object)
V4_PROTOTYPE(objectPrototype)
- void init(ExecutionEngine *engine, TypedArrayCtor *ctor);
+ void init(ExecutionEngine *engine, IntrinsicTypedArrayCtor *ctor);
static ReturnedValue method_get_buffer(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_byteLength(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_byteOffset(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_length(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_entries(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_keys(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_values(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_set(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_subarray(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_get_toStringTag(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+};
+
+struct TypedArrayPrototype : Object
+{
+ V4_OBJECT2(TypedArrayPrototype, Object)
+ V4_PROTOTYPE(objectPrototype)
+
+ void init(ExecutionEngine *engine, TypedArrayCtor *ctor);
};
inline void
diff --git a/src/qml/jsruntime/qv4util_p.h b/src/qml/jsruntime/qv4util_p.h
index 2669a3e4bf..073832937d 100644
--- a/src/qml/jsruntime/qv4util_p.h
+++ b/src/qml/jsruntime/qv4util_p.h
@@ -59,26 +59,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-template <typename T>
-struct TemporaryAssignment
-{
- TemporaryAssignment(T &var, const T& temporaryValue)
- : variable(var)
- , savedValue(var)
- {
- variable = temporaryValue;
- }
- ~TemporaryAssignment()
- {
- variable = savedValue;
- }
- T &variable;
- T savedValue;
-private:
- TemporaryAssignment(const TemporaryAssignment<T>&);
- TemporaryAssignment operator=(const TemporaryAssignment<T>&);
-};
-
#if !defined(BROKEN_STD_VECTOR_BOOL_OR_BROKEN_STD_FIND)
// Sanity:
class BitVector
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 0d4711df3c..cbc153bb86 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -39,7 +39,9 @@
#include <qv4engine_p.h>
#include <qv4runtime_p.h>
#include <qv4string_p.h>
+#include <qv4propertykey_p.h>
#ifndef V4_BOOTSTRAP
+#include <qv4symbol_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <private/qv4mm_p.h>
@@ -84,7 +86,7 @@ bool Value::toBooleanImpl(Value val)
#ifdef V4_BOOTSTRAP
Q_UNIMPLEMENTED();
#else
- if (b->vtable()->isString)
+ if (b->internalClass->vtable->isString)
return static_cast<Heap::String *>(b)->length() > 0;
#endif
return true;
@@ -107,6 +109,11 @@ double Value::toNumberImpl(Value val)
#else
if (String *s = val.stringValue())
return RuntimeHelpers::stringToNumber(s->toQString());
+ if (val.isSymbol()) {
+ Managed &m = static_cast<Managed &>(val);
+ m.engine()->throwTypeError();
+ return 0;
+ }
{
Q_ASSERT(val.isObject());
Scope scope(val.objectValue()->engine());
@@ -145,6 +152,8 @@ QString Value::toQStringNoThrow() const
case Value::Managed_Type:
if (String *s = stringValue())
return s->toQString();
+ if (Symbol *s = symbolValue())
+ return s->descriptiveString();
{
Q_ASSERT(isObject());
Scope scope(objectValue()->engine());
@@ -197,9 +206,12 @@ QString Value::toQString() const
else
return QStringLiteral("false");
case Value::Managed_Type:
- if (String *s = stringValue())
+ if (String *s = stringValue()) {
return s->toQString();
- {
+ } else if (isSymbol()) {
+ static_cast<const Managed *>(this)->engine()->throwTypeError();
+ return QString();
+ } else {
Q_ASSERT(isObject());
Scope scope(objectValue()->engine());
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, STRING_HINT));
@@ -217,6 +229,25 @@ QString Value::toQString() const
}
} // switch
}
+
+QV4::PropertyKey Value::toPropertyKey(ExecutionEngine *e) const
+{
+ if (isInteger() && int_32() >= 0)
+ return PropertyKey::fromArrayIndex(static_cast<uint>(int_32()));
+ if (isStringOrSymbol()) {
+ Scope scope(e);
+ ScopedStringOrSymbol s(scope, this);
+ return s->toPropertyKey();
+ }
+ Scope scope(e);
+ ScopedValue v(scope, RuntimeHelpers::toPrimitive(*this, STRING_HINT));
+ if (!v->isStringOrSymbol())
+ v = v->toString(e);
+ if (e->hasException)
+ return PropertyKey::invalid();
+ ScopedStringOrSymbol s(scope, v);
+ return s->toPropertyKey();
+}
#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
@@ -235,6 +266,25 @@ bool Value::sameValue(Value other) const {
return false;
}
+bool Value::sameValueZero(Value other) const {
+ if (_val == other._val)
+ return true;
+ String *s = stringValue();
+ String *os = other.stringValue();
+ if (s && os)
+ return s->isEqualTo(os);
+ if (isInteger() && other.isDouble())
+ return double(int_32()) == other.doubleValue();
+ if (isDouble() && other.isInteger())
+ return other.int_32() == doubleValue();
+ if (isDouble() && other.isDouble()) {
+ if (doubleValue() == 0 && other.doubleValue() == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
#ifndef V4_BOOTSTRAP
Heap::String *Value::toString(ExecutionEngine *e, Value val)
{
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index a5ee6b5373..6a6df3eb6d 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -56,6 +56,7 @@
#include <QtCore/QString>
#include "qv4global_p.h"
#include <private/qv4heap_p.h>
+#include <private/qv4internalclass_p.h>
#include <private/qnumeric_p.h>
@@ -184,23 +185,7 @@ public:
QML_NEARLY_ALWAYS_INLINE void setEmpty()
{
- setTagValue(quint32(ValueTypeInternal::Empty), value());
- }
-
- QML_NEARLY_ALWAYS_INLINE void setEmpty(int i)
- {
- setTagValue(quint32(ValueTypeInternal::Empty), quint32(i));
- }
-
- QML_NEARLY_ALWAYS_INLINE void setEmpty(quint32 i)
- {
- setTagValue(quint32(ValueTypeInternal::Empty), i);
- }
-
- QML_NEARLY_ALWAYS_INLINE quint32 emptyValue()
- {
- Q_ASSERT(isEmpty());
- return quint32(value());
+ setTagValue(quint32(ValueTypeInternal::Empty), 0);
}
// ### Fix for 32 bit (easiest solution is to set highest bit to 1 for mananged/undefined/integercompatible
@@ -248,7 +233,8 @@ public:
IsManagedOrUndefined_Shift = 64-15,
IsIntegerConvertible_Shift = 64-15,
IsIntegerOrBool_Shift = 64-16,
- QuickType_Shift = 64 - 17
+ QuickType_Shift = 64 - 17,
+ IsPositiveIntShift = 31
};
static const quint64 Immediate_Mask_64 = 0x00020000u; // bit 49
@@ -315,6 +301,14 @@ public:
}
inline bool isNaN() const { return (tag() & 0x7ffc0000 ) == 0x00040000; }
+ inline bool isPositiveInt() const {
+#if QT_POINTER_SIZE == 4
+ return isInteger() && int_32() >= 0;
+#else
+ return (_val >> IsPositiveIntShift) == (quint64(ValueTypeInternal::Integer) << 1);
+#endif
+ }
+
QML_NEARLY_ALWAYS_INLINE double doubleValue() const {
Q_ASSERT(isDouble());
double d;
@@ -331,6 +325,8 @@ public:
Q_ASSERT(isDouble());
}
inline bool isString() const;
+ inline bool isStringOrSymbol() const;
+ inline bool isSymbol() const;
inline bool isObject() const;
inline bool isFunctionObject() const;
inline bool isInt32() {
@@ -338,14 +334,17 @@ public:
return true;
if (isDouble()) {
double d = doubleValue();
- int i = (int)d;
- if (i == d && !(d == 0 && std::signbit(d))) {
- setInt_32(i);
+ if (isInt32(d)) {
+ setInt_32(int(d));
return true;
}
}
return false;
}
+ QML_NEARLY_ALWAYS_INLINE static bool isInt32(double d) {
+ int i = int(d);
+ return (i == d && !(d == 0 && std::signbit(d)));
+ }
double asDouble() const {
if (tag() == quint32(ValueTypeInternal::Integer))
return int_32();
@@ -362,7 +361,17 @@ public:
QML_NEARLY_ALWAYS_INLINE String *stringValue() const {
if (!isString())
return nullptr;
- return reinterpret_cast<String*>(const_cast<Value *>(this));
+ return reinterpret_cast<String *>(const_cast<Value *>(this));
+ }
+ QML_NEARLY_ALWAYS_INLINE StringOrSymbol *stringOrSymbolValue() const {
+ if (!isStringOrSymbol())
+ return nullptr;
+ return reinterpret_cast<StringOrSymbol *>(const_cast<Value *>(this));
+ }
+ QML_NEARLY_ALWAYS_INLINE Symbol *symbolValue() const {
+ if (!isSymbol())
+ return nullptr;
+ return reinterpret_cast<Symbol *>(const_cast<Value *>(this));
}
QML_NEARLY_ALWAYS_INLINE Object *objectValue() const {
if (!isObject())
@@ -388,6 +397,8 @@ public:
int toUInt16() const;
inline int toInt32() const;
inline unsigned int toUInt32() const;
+ qint64 toLength() const;
+ inline qint64 toIndex() const;
bool toBoolean() const {
if (integerCompatible())
@@ -407,6 +418,8 @@ public:
return reinterpret_cast<Heap::String *>(m());
return toString(e, *this);
}
+ QV4::PropertyKey toPropertyKey(ExecutionEngine *e) const;
+
static Heap::String *toString(ExecutionEngine *e, Value val);
Heap::Object *toObject(ExecutionEngine *e) const {
if (isObject())
@@ -428,11 +441,11 @@ public:
if (!isManaged())
return nullptr;
- Q_ASSERT(m()->vtable());
+ Q_ASSERT(m()->internalClass->vtable);
#if !defined(QT_NO_QOBJECT_CHECK)
static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
#endif
- const VTable *vt = m()->vtable();
+ const VTable *vt = m()->internalClass->vtable;
while (vt) {
if (vt == T::staticVTable())
return static_cast<const T *>(this);
@@ -455,8 +468,6 @@ public:
return static_cast<const T *>(managed());
}
- inline uint asArrayIndex() const;
- inline bool asArrayIndex(uint &idx) const;
#ifndef V4_BOOTSTRAP
uint asArrayLength(bool *ok) const;
#endif
@@ -465,8 +476,9 @@ public:
ReturnedValue asReturnedValue() const { return _val; }
static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
- // Section 9.12
+ // As per ES specs
bool sameValue(Value other) const;
+ bool sameValueZero(Value other) const;
inline void mark(MarkStack *markStack);
@@ -500,18 +512,32 @@ inline void Value::mark(MarkStack *markStack)
inline bool Value::isString() const
{
Heap::Base *b = heapObject();
- return b && b->vtable()->isString;
+ return b && b->internalClass->vtable->isString;
+}
+
+bool Value::isStringOrSymbol() const
+{
+ Heap::Base *b = heapObject();
+ return b && b->internalClass->vtable->isStringOrSymbol;
+}
+
+bool Value::isSymbol() const
+{
+ Heap::Base *b = heapObject();
+ return b && b->internalClass->vtable->isStringOrSymbol && !b->internalClass->vtable->isString;
}
+
inline bool Value::isObject() const
+
{
Heap::Base *b = heapObject();
- return b && b->vtable()->isObject;
+ return b && b->internalClass->vtable->isObject;
}
inline bool Value::isFunctionObject() const
{
Heap::Base *b = heapObject();
- return b && b->vtable()->isFunctionObject;
+ return b && b->internalClass->vtable->isFunctionObject;
}
inline bool Value::isPrimitive() const
@@ -528,43 +554,6 @@ inline double Value::toNumber() const
return toNumberImpl();
}
-
-#ifndef V4_BOOTSTRAP
-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 bool Value::asArrayIndex(uint &idx) const
-{
- if (Q_LIKELY(!isDouble())) {
- if (Q_LIKELY(isInteger() && int_32() >= 0)) {
- idx = (uint)int_32();
- return true;
- }
- return false;
- }
- double d = doubleValue();
- idx = (uint)d;
- return (idx == d && idx != UINT_MAX);
-}
-#endif
-
inline
ReturnedValue Heap::Base::asReturnedValue() const
{
@@ -576,7 +565,6 @@ ReturnedValue Heap::Base::asReturnedValue() const
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
inline static Primitive emptyValue();
- inline static Primitive emptyValue(uint v);
static inline Primitive fromBoolean(bool b);
static inline Primitive fromInt32(int i);
inline static Primitive undefinedValue();
@@ -602,14 +590,7 @@ inline Primitive Primitive::undefinedValue()
inline Primitive Primitive::emptyValue()
{
Primitive v;
- v.setEmpty(0);
- return v;
-}
-
-inline Primitive Primitive::emptyValue(uint e)
-{
- Primitive v;
- v.setEmpty(e);
+ v.setEmpty();
return v;
}
@@ -755,7 +736,7 @@ struct Encode {
}
static ReturnedValue smallestNumber(double d) {
- if (static_cast<int>(d) == d && !(d == 0. && std::signbit(d)))
+ if (Value::isInt32(d))
return Encode(static_cast<int>(d));
else
return Encode(d);
@@ -788,6 +769,31 @@ inline unsigned int Value::toUInt32() const
return static_cast<unsigned int>(toInt32());
}
+inline qint64 Value::toLength() const
+{
+ if (Q_LIKELY(integerCompatible()))
+ return int_32() < 0 ? 0 : int_32();
+ double i = Primitive::toInteger(isDouble() ? doubleValue() : toNumberImpl());
+ if (i <= 0)
+ return 0;
+ if (i > (static_cast<qint64>(1) << 53) - 1)
+ return (static_cast<qint64>(1) << 53) - 1;
+ return static_cast<qint64>(i);
+}
+
+inline qint64 Value::toIndex() const
+{
+ qint64 idx;
+ if (Q_LIKELY(integerCompatible())) {
+ idx = int_32();
+ } else {
+ idx = static_cast<qint64>(Primitive::toInteger(isDouble() ? doubleValue() : toNumberImpl()));
+ }
+ if (idx > (static_cast<qint64>(1) << 53) - 1)
+ idx = -1;
+ return idx;
+}
+
inline double Value::toInteger() const
{
if (integerCompatible())
@@ -831,7 +837,7 @@ struct ValueArray {
WriteBarrier::write(e, base(), values[index].data_ptr(), v.asReturnedValue());
}
void set(EngineBase *e, uint index, Heap::Base *b) {
- WriteBarrier::write(e, base(), values[index].data_ptr(), b->asReturnedValue());
+ WriteBarrier::write(e, base(), values[index].data_ptr(), Value::fromHeapObject(b).asReturnedValue());
}
inline const Value &operator[] (uint index) const {
Q_ASSERT(index < alloc);
@@ -884,7 +890,6 @@ struct ValueArray {
// have wrong offsets between host and target.
Q_STATIC_ASSERT(offsetof(ValueArray<0>, values) == 8);
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index bee17e0390..ef0877dbd0 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -70,7 +70,7 @@ bool VariantObject::Data::isScarce() const
return t == QVariant::Pixmap || t == QVariant::Image;
}
-bool VariantObject::isEqualTo(Managed *m, Managed *other)
+bool VariantObject::virtualIsEqualTo(Managed *m, Managed *other)
{
Q_ASSERT(m->as<QV4::VariantObject>());
QV4::VariantObject *lv = static_cast<QV4::VariantObject *>(m);
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 62fa7ff9a8..78e0a5373a 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -99,7 +99,8 @@ struct VariantObject : Object
void addVmePropertyReference() const;
void removeVmePropertyReference() const;
- static bool isEqualTo(Managed *m, Managed *other);
+protected:
+ static bool virtualIsEqualTo(Managed *m, Managed *other);
};
struct VariantPrototype : VariantObject
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index a1f5b01fa9..53e5632eff 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -55,12 +55,13 @@
#include <private/qv4string_p.h>
#include <private/qv4profiling_p.h>
#include <private/qv4jscall_p.h>
+#include <private/qv4generatorobject_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <iostream>
#include "qv4alloca_p.h"
-#include <private/qv4jit_p.h>
+#include <private/qv4baselinejit_p.h>
#undef COUNT_INSTRUCTIONS
@@ -327,7 +328,7 @@ static struct InstrCount {
#ifdef MOTH_COMPUTED_GOTO
#define MOTH_END_INSTR(instr) \
- MOTH_DISPATCH() \
+ MOTH_DISPATCH_SINGLE() \
}
#else // !MOTH_COMPUTED_GOTO
#define MOTH_END_INSTR(instr) \
@@ -343,7 +344,7 @@ static struct InstrCount {
#endif
#define CHECK_EXCEPTION \
if (engine->hasException) \
- goto catchException
+ goto handleUnwind
static inline Heap::CallContext *getScope(QV4::Value *stack, int level)
{
@@ -361,95 +362,6 @@ static inline const QV4::Value &constant(Function *function, int index)
return function->compilationUnit->constants[index];
}
-
-static bool compareEqual(QV4::Value lhs, QV4::Value rhs)
-{
- redo:
- if (lhs.asReturnedValue() == rhs.asReturnedValue())
- return !lhs.isNaN();
-
- int lt = lhs.quickType();
- int rt = rhs.quickType();
- if (rt < lt) {
- qSwap(lhs, rhs);
- qSwap(lt, rt);
- }
-
- switch (lt) {
- case QV4::Value::QT_ManagedOrUndefined:
- if (lhs.isUndefined())
- return rhs.isNullOrUndefined();
- Q_FALLTHROUGH();
- case QV4::Value::QT_ManagedOrUndefined1:
- case QV4::Value::QT_ManagedOrUndefined2:
- case QV4::Value::QT_ManagedOrUndefined3:
- // LHS: Managed
- switch (rt) {
- case QV4::Value::QT_ManagedOrUndefined:
- if (rhs.isUndefined())
- return false;
- Q_FALLTHROUGH();
- case QV4::Value::QT_ManagedOrUndefined1:
- case QV4::Value::QT_ManagedOrUndefined2:
- case QV4::Value::QT_ManagedOrUndefined3: {
- // RHS: Managed
- Heap::Base *l = lhs.m();
- Heap::Base *r = rhs.m();
- Q_ASSERT(l);
- Q_ASSERT(r);
- if (l->vtable()->isString == r->vtable()->isString)
- return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs));
- if (l->vtable()->isString) {
- rhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT));
- break;
- } else {
- Q_ASSERT(r->vtable()->isString);
- lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT));
- break;
- }
- return false;
- }
- case QV4::Value::QT_Empty:
- Q_UNREACHABLE();
- case QV4::Value::QT_Null:
- return false;
- case QV4::Value::QT_Bool:
- case QV4::Value::QT_Int:
- rhs = Primitive::fromDouble(rhs.int_32());
- // fall through
- default: // double
- if (lhs.m()->vtable()->isString)
- return RuntimeHelpers::toNumber(lhs) == rhs.doubleValue();
- else
- lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT));
- }
- goto redo;
- case QV4::Value::QT_Empty:
- Q_UNREACHABLE();
- case QV4::Value::QT_Null:
- return rhs.isNull();
- case QV4::Value::QT_Bool:
- case QV4::Value::QT_Int:
- switch (rt) {
- case QV4::Value::QT_ManagedOrUndefined:
- case QV4::Value::QT_ManagedOrUndefined1:
- case QV4::Value::QT_ManagedOrUndefined2:
- case QV4::Value::QT_ManagedOrUndefined3:
- case QV4::Value::QT_Empty:
- case QV4::Value::QT_Null:
- Q_UNREACHABLE();
- case QV4::Value::QT_Bool:
- case QV4::Value::QT_Int:
- return lhs.int_32() == rhs.int_32();
- default: // double
- return lhs.int_32() == rhs.doubleValue();
- }
- default: // double
- Q_ASSERT(rhs.isDouble());
- return lhs.doubleValue() == rhs.doubleValue();
- }
-}
-
static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
{
redo:
@@ -462,7 +374,7 @@ static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
case QV4::Value::QT_ManagedOrUndefined2:
case QV4::Value::QT_ManagedOrUndefined3:
// LHS: Managed
- if (lhs.m()->vtable()->isString)
+ if (lhs.m()->internalClass->vtable->isString)
return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs;
accumulator = lhs;
lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT));
@@ -479,7 +391,7 @@ static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
}
}
-#define STORE_IP() frame.instructionPointer = int(code - codeStart);
+#define STORE_IP() frame->instructionPointer = int(code - function->codeData);
#define STORE_ACC() accumulator = acc;
#define ACC Primitive::fromReturnedValue(acc)
#define VALUE_TO_INT(i, val) \
@@ -500,82 +412,46 @@ static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
} \
} while (false)
-QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
+ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
{
qt_v4ResolvePendingBreakpointsHook();
- ExecutionEngine *engine;
- QV4::Value *stack;
- CppStackFrame frame;
- frame.originalArguments = argv;
- frame.originalArgumentsCount = argc;
- Function *function;
-
- {
- Heap::ExecutionContext *scope;
-
- quintptr d = reinterpret_cast<quintptr>(fo);
- if (d & 0x1) {
- // we don't have a FunctionObject, but a ExecData
- ExecData *data = reinterpret_cast<ExecData *>(d - 1);
- function = data->function;
- scope = data->scope->d();
- fo = nullptr;
- } else {
- function = fo->function();
- scope = fo->scope();
- }
-
- engine = function->internalClass->engine;
-
- stack = engine->jsStackTop;
- CallData *callData = reinterpret_cast<CallData *>(stack);
- callData->function = fo ? fo->asReturnedValue() : Encode::undefined();
- callData->context = scope;
- callData->accumulator = Encode::undefined();
- callData->thisObject = thisObject ? *thisObject : Primitive::undefinedValue();
- if (argc > int(function->nFormals))
- argc = int(function->nFormals);
- callData->setArgc(argc);
-
- int jsStackFrameSize = offsetof(CallData, args)/sizeof(Value) + function->compiledFunction->nRegisters;
- engine->jsStackTop += jsStackFrameSize;
- memcpy(callData->args, argv, argc*sizeof(Value));
- for (Value *v = callData->args + argc; v < engine->jsStackTop; ++v)
- *v = Encode::undefined();
-
- frame.parent = engine->currentStackFrame;
- frame.v4Function = function;
- frame.instructionPointer = 0;
- frame.jsFrame = callData;
- engine->currentStackFrame = &frame;
- }
CHECK_STACK_LIMITS(engine);
+ Function *function = frame->v4Function;
Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
QV4::Debugging::Debugger *debugger = engine->debugger();
- const uchar *exceptionHandler = nullptr;
-
- QV4::Value &accumulator = frame.jsFrame->accumulator;
- QV4::ReturnedValue acc = Encode::undefined();
#ifdef V4_ENABLE_JIT
- if (function->jittedCode == nullptr && debugger == nullptr) {
- if (engine->canJIT(function))
- QV4::JIT::BaselineJIT(function).generate();
- else
- ++function->interpreterCallCount;
+ if (debugger == nullptr) {
+ if (function->jittedCode == nullptr) {
+ if (engine->canJIT(function))
+ QV4::JIT::BaselineJIT(function).generate();
+ else
+ ++function->interpreterCallCount;
+ }
+ if (function->jittedCode != nullptr)
+ return function->jittedCode(frame, engine);
}
#endif // V4_ENABLE_JIT
+ // interpreter
if (debugger)
debugger->enteringFunction();
- if (function->jittedCode != nullptr && debugger == nullptr) {
- acc = function->jittedCode(&frame, engine);
- } else {
- // interpreter
- const uchar *code = function->codeData;
- const uchar *codeStart = code;
+ ReturnedValue result = interpret(frame, engine, function->codeData);
+
+ if (debugger)
+ debugger->leavingFunction(result);
+
+ return result;
+}
+
+QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, const char *code)
+{
+ QV4::Function *function = frame->v4Function;
+ QV4::Value &accumulator = frame->jsFrame->accumulator;
+ QV4::ReturnedValue acc = accumulator.asReturnedValue();
+ Value *stack = reinterpret_cast<Value *>(frame->jsFrame);
MOTH_JUMP_TABLE;
@@ -629,12 +505,14 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
MOTH_BEGIN_INSTR(LoadLocal)
auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
+ Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
acc = cc->locals[index].asReturnedValue();
MOTH_END_INSTR(LoadLocal)
MOTH_BEGIN_INSTR(StoreLocal)
CHECK_EXCEPTION;
auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
+ Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
MOTH_END_INSTR(StoreLocal)
@@ -689,58 +567,37 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
MOTH_BEGIN_INSTR(LoadElement)
STORE_IP();
- acc = Runtime::method_loadElement(engine, STACK_VALUE(base), STACK_VALUE(index));
- CHECK_EXCEPTION;
- MOTH_END_INSTR(LoadElement)
-
- MOTH_BEGIN_INSTR(LoadElementA)
- STORE_IP();
STORE_ACC();
acc = Runtime::method_loadElement(engine, STACK_VALUE(base), accumulator);
CHECK_EXCEPTION;
- MOTH_END_INSTR(LoadElementA)
+ MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
STORE_IP();
STORE_ACC();
- if (!Runtime::method_storeElement(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator) && function->isStrict())
- engine->throwTypeError();
+ Runtime::method_storeElement(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
STORE_IP();
- acc = Runtime::method_loadProperty(engine, STACK_VALUE(base), name);
- CHECK_EXCEPTION;
- MOTH_END_INSTR(LoadProperty)
-
- MOTH_BEGIN_INSTR(LoadPropertyA)
- STORE_IP();
STORE_ACC();
acc = Runtime::method_loadProperty(engine, accumulator, name);
CHECK_EXCEPTION;
- MOTH_END_INSTR(LoadPropertyA)
+ MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
STORE_IP();
- QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
- acc = l->getter(l, engine, STACK_VALUE(base));
- CHECK_EXCEPTION;
- MOTH_END_INSTR(GetLookup)
-
- MOTH_BEGIN_INSTR(GetLookupA)
- STORE_IP();
STORE_ACC();
QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
acc = l->getter(l, engine, accumulator);
CHECK_EXCEPTION;
- MOTH_END_INSTR(GetLookupA)
+ MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
STORE_IP();
STORE_ACC();
- if (!Runtime::method_storeProperty(engine, STACK_VALUE(base), name, accumulator) && function->isStrict())
- engine->throwTypeError();
+ Runtime::method_storeProperty(engine, STACK_VALUE(base), name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
@@ -753,6 +610,20 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
CHECK_EXCEPTION;
MOTH_END_INSTR(SetLookup)
+ MOTH_BEGIN_INSTR(LoadSuperProperty)
+ STORE_IP();
+ STORE_ACC();
+ acc = Runtime::method_loadSuperProperty(engine, STACK_VALUE(property));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(LoadSuperProperty)
+
+ MOTH_BEGIN_INSTR(StoreSuperProperty)
+ STORE_IP();
+ STORE_ACC();
+ Runtime::method_storeSuperProperty(engine, STACK_VALUE(property), accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreSuperProperty)
+
MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
STORE_ACC();
Runtime::method_storeQmlScopeObjectProperty(engine, STACK_VALUE(base), propertyIndex, accumulator);
@@ -784,14 +655,33 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadIdObject)
+ MOTH_BEGIN_INSTR(Yield)
+ frame->yield = code;
+ return acc;
+ MOTH_END_INSTR(Yield)
+
+ MOTH_BEGIN_INSTR(Resume)
+ // check exception, in case the generator was called with throw() or return()
+ if (engine->hasException) {
+ // an empty value indicates that the generator was called with return()
+ if (engine->exceptionValue->asReturnedValue() != Primitive::emptyValue().asReturnedValue())
+ goto handleUnwind;
+ engine->hasException = false;
+ *engine->exceptionValue = Primitive::undefinedValue();
+ } else {
+ code += offset;
+ }
+ MOTH_END_INSTR(Resume)
+
MOTH_BEGIN_INSTR(CallValue)
STORE_IP();
Value func = STACK_VALUE(name);
if (Q_UNLIKELY(!func.isFunctionObject())) {
acc = engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
- goto catchException;
+ goto handleUnwind;
}
- acc = static_cast<const FunctionObject &>(func).call(nullptr, stack + argv, argc);
+ Value undef = Primitive::undefinedValue();
+ acc = static_cast<const FunctionObject &>(func).call(&undef, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(CallValue)
@@ -809,7 +699,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
if (Q_UNLIKELY(!f.isFunctionObject())) {
acc = engine->throwTypeError();
- goto catchException;
+ goto handleUnwind;
}
acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
@@ -852,15 +742,49 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
CHECK_EXCEPTION;
MOTH_END_INSTR(CallContextObjectProperty)
- MOTH_BEGIN_INSTR(SetExceptionHandler)
- exceptionHandler = offset ? code + offset : nullptr;
- MOTH_END_INSTR(SetExceptionHandler)
+ MOTH_BEGIN_INSTR(CallWithSpread)
+ STORE_IP();
+ acc = Runtime::method_callWithSpread(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CallWithSpread)
+
+ MOTH_BEGIN_INSTR(Construct)
+ STORE_IP();
+ acc = Runtime::method_construct(engine, STACK_VALUE(func), ACC, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(Construct)
+
+ MOTH_BEGIN_INSTR(ConstructWithSpread)
+ STORE_IP();
+ acc = Runtime::method_constructWithSpread(engine, STACK_VALUE(func), ACC, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(ConstructWithSpread)
+
+ MOTH_BEGIN_INSTR(SetUnwindHandler)
+ frame->unwindHandler = offset ? code + offset : nullptr;
+ MOTH_END_INSTR(SetUnwindHandler)
+
+ MOTH_BEGIN_INSTR(UnwindDispatch)
+ CHECK_EXCEPTION;
+ if (frame->unwindLevel) {
+ --frame->unwindLevel;
+ if (frame->unwindLevel)
+ goto handleUnwind;
+ code = frame->unwindLabel;
+ }
+ MOTH_END_INSTR(UnwindDispatch)
+
+ MOTH_BEGIN_INSTR(UnwindToLabel)
+ frame->unwindLevel = level;
+ frame->unwindLabel = code + offset;
+ goto handleUnwind;
+ MOTH_END_INSTR(UnwindToLabel)
MOTH_BEGIN_INSTR(ThrowException)
STORE_IP();
STORE_ACC();
Runtime::method_throwException(engine, accumulator);
- goto catchException;
+ goto handleUnwind;
MOTH_END_INSTR(ThrowException)
MOTH_BEGIN_INSTR(GetException)
@@ -870,71 +794,90 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
MOTH_END_INSTR(HasException)
MOTH_BEGIN_INSTR(SetException)
- *engine->exceptionValue = acc;
- engine->hasException = true;
+ if (acc != Primitive::emptyValue().asReturnedValue()) {
+ *engine->exceptionValue = acc;
+ engine->hasException = true;
+ }
MOTH_END_INSTR(SetException)
MOTH_BEGIN_INSTR(PushCatchContext)
- STACK_VALUE(reg) = STACK_VALUE(CallData::Context);
ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, name);
+ STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, index, name);
MOTH_END_INSTR(PushCatchContext)
MOTH_BEGIN_INSTR(CreateCallContext)
- stack[CallData::Context] = ExecutionContext::newCallContext(&frame);
+ stack[CallData::Context] = ExecutionContext::newCallContext(frame);
MOTH_END_INSTR(CreateCallContext)
MOTH_BEGIN_INSTR(PushWithContext)
STORE_IP();
STORE_ACC();
- accumulator = accumulator.toObject(engine);
+ auto ctx = Runtime::method_createWithContext(engine, stack);
CHECK_EXCEPTION;
- STACK_VALUE(reg) = STACK_VALUE(CallData::Context);
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_createWithContext(c, accumulator);
+ STACK_VALUE(CallData::Context) = ctx;
MOTH_END_INSTR(PushWithContext)
+ MOTH_BEGIN_INSTR(PushBlockContext)
+ STORE_ACC();
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ STACK_VALUE(CallData::Context) = Runtime::method_createBlockContext(c, index);
+ MOTH_END_INSTR(PushBlockContext)
+
+ MOTH_BEGIN_INSTR(CloneBlockContext)
+ STORE_ACC();
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ STACK_VALUE(CallData::Context) = Runtime::method_cloneBlockContext(c);
+ MOTH_END_INSTR(CloneBlockContext)
+
+ MOTH_BEGIN_INSTR(PushScriptContext)
+ STACK_VALUE(CallData::Context) = Runtime::method_createScriptContext(engine, index);
+ MOTH_END_INSTR(PushScriptContext)
+
+ MOTH_BEGIN_INSTR(PopScriptContext)
+ STACK_VALUE(CallData::Context) = Runtime::method_popScriptContext(engine);
+ MOTH_END_INSTR(PopScriptContext)
+
MOTH_BEGIN_INSTR(PopContext)
- STACK_VALUE(CallData::Context) = STACK_VALUE(reg);
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ STACK_VALUE(CallData::Context) = c->d()->outer;
MOTH_END_INSTR(PopContext)
- MOTH_BEGIN_INSTR(ForeachIteratorObject)
+ MOTH_BEGIN_INSTR(GetIterator)
STORE_ACC();
- acc = Runtime::method_foreachIterator(engine, accumulator);
+ acc = Runtime::method_getIterator(engine, accumulator, iterator);
CHECK_EXCEPTION;
- MOTH_END_INSTR(ForeachIteratorObject)
+ MOTH_END_INSTR(GetIterator)
- MOTH_BEGIN_INSTR(ForeachNextPropertyName)
+ MOTH_BEGIN_INSTR(IteratorNext)
STORE_ACC();
- acc = Runtime::method_foreachNextPropertyName(accumulator);
+ acc = Runtime::method_iteratorNext(engine, accumulator, &STACK_VALUE(value));
CHECK_EXCEPTION;
- MOTH_END_INSTR(ForeachNextPropertyName)
+ MOTH_END_INSTR(IteratorNext)
- MOTH_BEGIN_INSTR(DeleteMember)
- if (!Runtime::method_deleteMember(engine, STACK_VALUE(base), member)) {
- if (function->isStrict()) {
- STORE_IP();
- engine->throwTypeError();
- goto catchException;
- }
- acc = Encode(false);
- } else {
- acc = Encode(true);
- }
- MOTH_END_INSTR(DeleteMember)
+ MOTH_BEGIN_INSTR(IteratorClose)
+ STORE_ACC();
+ acc = Runtime::method_iteratorClose(engine, accumulator, STACK_VALUE(done));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(IteratorClose)
+
+ MOTH_BEGIN_INSTR(DestructureRestElement)
+ STORE_ACC();
+ acc = Runtime::method_destructureRestElement(engine, ACC);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(DestructureRestElement)
- MOTH_BEGIN_INSTR(DeleteSubscript)
- if (!Runtime::method_deleteElement(engine, STACK_VALUE(base), STACK_VALUE(index))) {
+ MOTH_BEGIN_INSTR(DeleteProperty)
+ if (!Runtime::method_deleteProperty(engine, STACK_VALUE(base), STACK_VALUE(index))) {
if (function->isStrict()) {
STORE_IP();
engine->throwTypeError();
- goto catchException;
+ goto handleUnwind;
}
acc = Encode(false);
} else {
acc = Encode(true);
}
- MOTH_END_INSTR(DeleteSubscript)
+ MOTH_END_INSTR(DeleteProperty)
MOTH_BEGIN_INSTR(DeleteName)
if (!Runtime::method_deleteName(engine, name)) {
@@ -942,7 +885,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
STORE_IP();
QString n = function->compilationUnit->runtimeStrings[name]->toQString();
engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(n));
- goto catchException;
+ goto handleUnwind;
}
acc = Encode(false);
} else {
@@ -970,9 +913,13 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
MOTH_BEGIN_INSTR(DefineObjectLiteral)
QV4::Value *arguments = stack + args;
- acc = Runtime::method_objectLiteral(engine, arguments, internalClassId, arrayValueCount, arrayGetterSetterCountAndFlags);
+ acc = Runtime::method_objectLiteral(engine, internalClassId, argc, arguments);
MOTH_END_INSTR(DefineObjectLiteral)
+ MOTH_BEGIN_INSTR(CreateClass)
+ acc = Runtime::method_createClass(engine, classIndex, STACK_VALUE(heritage), stack + computedNames);
+ MOTH_END_INSTR(CreateClass)
+
MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
acc = Runtime::method_createMappedArgumentsObject(engine);
MOTH_END_INSTR(CreateMappedArgumentsObject)
@@ -981,6 +928,10 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
acc = Runtime::method_createUnmappedArgumentsObject(engine);
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
+ MOTH_BEGIN_INSTR(CreateRestParameter)
+ acc = Runtime::method_createRestParameter(engine, argIndex);
+ MOTH_END_INSTR(CreateRestParameter)
+
MOTH_BEGIN_INSTR(ConvertThisToObject)
Value *t = &stack[CallData::This];
if (!t->isObject()) {
@@ -993,11 +944,20 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
}
MOTH_END_INSTR(ConvertThisToObject)
- MOTH_BEGIN_INSTR(Construct)
- STORE_IP();
- acc = Runtime::method_construct(engine, STACK_VALUE(func), stack + argv, argc);
+ MOTH_BEGIN_INSTR(LoadSuperConstructor)
+ const Value *f = &stack[CallData::Function];
+ if (!f->isFunctionObject()) {
+ engine->throwTypeError();
+ } else {
+ acc = static_cast<const Object *>(f)->getPrototypeOf()->asReturnedValue();
+ }
CHECK_EXCEPTION;
- MOTH_END_INSTR(Construct)
+ MOTH_END_INSTR(LoadSuperConstructor)
+
+ MOTH_BEGIN_INSTR(ToObject)
+ acc = ACC.toObject(engine)->asReturnedValue();
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(ToObject)
MOTH_BEGIN_INSTR(Jump)
code += offset;
@@ -1023,6 +983,16 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
}
MOTH_END_INSTR(JumpFalse)
+ MOTH_BEGIN_INSTR(JumpNoException)
+ if (!engine->hasException)
+ code += offset;
+ MOTH_END_INSTR(JumpNoException)
+
+ MOTH_BEGIN_INSTR(JumpNotUndefined)
+ if (Q_LIKELY(acc != QV4::Encode::undefined()))
+ code += offset;
+ MOTH_END_INSTR(JumpNotUndefined)
+
MOTH_BEGIN_INSTR(CmpEqNull)
acc = Encode(ACC.isNullOrUndefined());
MOTH_END_INSTR(CmpEqNull)
@@ -1059,7 +1029,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
acc = Encode(left.int_32() == ACC.int_32());
} else {
STORE_ACC();
- acc = Encode(compareEqual(left, accumulator));
+ acc = Encode(bool(Runtime::method_compareEqual(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpEq)
@@ -1070,7 +1040,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
acc = Encode(bool(left.int_32() != ACC.int_32()));
} else {
STORE_ACC();
- acc = Encode(!compareEqual(left, accumulator));
+ acc = Encode(bool(!Runtime::method_compareEqual(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpNe)
@@ -1154,27 +1124,11 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
MOTH_END_INSTR(CmpIn)
MOTH_BEGIN_INSTR(CmpInstanceOf)
- // 11.8.6, 5: rval must be an Object
- if (Q_UNLIKELY(!Primitive::fromReturnedValue(acc).isObject())) {
- acc = engine->throwTypeError();
- goto catchException;
- }
-
- // 11.8.6, 7: call "HasInstance", which we term instanceOf, and return the result.
- acc = Primitive::fromReturnedValue(acc).objectValue()->instanceOf(STACK_VALUE(lhs));
+ STORE_ACC();
+ acc = Runtime::method_instanceof(engine, STACK_VALUE(lhs), ACC);
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpInstanceOf)
- MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
- if (STACK_VALUE(lhs).int_32() != rhs || STACK_VALUE(lhs).isUndefined())
- code += offset;
- MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
-
- MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
- if (STACK_VALUE(lhs).int_32() == rhs && !STACK_VALUE(lhs).isUndefined())
- code += offset;
- MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
-
MOTH_BEGIN_INSTR(UNot)
if (ACC.integerCompatible()) {
acc = Encode(!static_cast<bool>(ACC.int_32()));
@@ -1259,6 +1213,16 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
}
MOTH_END_INSTR(Sub)
+ MOTH_BEGIN_INSTR(Exp)
+ const Value left = STACK_VALUE(lhs);
+ double base = left.toNumber();
+ double exp = ACC.toNumber();
+ if (qIsInf(exp) && (base == 1 || base == -1))
+ acc = Encode(qSNaN());
+ else
+ acc = Encode(pow(base,exp));
+ MOTH_END_INSTR(Exp)
+
MOTH_BEGIN_INSTR(Mul)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
@@ -1351,7 +1315,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
MOTH_END_INSTR(ShlConst)
MOTH_BEGIN_INSTR(Ret)
- goto functionExit;
+ return acc;
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
@@ -1369,21 +1333,12 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj
STACK_VALUE(result) = Runtime::method_loadQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
- catchException:
- Q_ASSERT(engine->hasException);
- if (!exceptionHandler) {
+ handleUnwind:
+ Q_ASSERT(engine->hasException || frame->unwindLevel);
+ if (!frame->unwindHandler) {
acc = Encode::undefined();
- goto functionExit;
+ return acc;
}
- code = exceptionHandler;
- }
+ code = frame->unwindHandler;
}
-
-functionExit:
- if (QV4::Debugging::Debugger *debugger = engine->debugger())
- debugger->leavingFunction(ACC.asReturnedValue());
- engine->currentStackFrame = frame.parent;
- engine->jsStackTop = stack;
-
- return acc;
}
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 3b7723ca7e..8a76e60f20 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -65,13 +65,8 @@ public:
QV4::Function *function;
const QV4::ExecutionContext *scope;
};
- static inline
- QV4::ReturnedValue exec(Function *v4Function, const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
- ExecData data{v4Function, context};
- quintptr d = reinterpret_cast<quintptr>(&data) | 0x1;
- return exec(reinterpret_cast<const FunctionObject *>(d), thisObject, argv, argc);
- }
- static QV4::ReturnedValue exec(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc);
+ static QV4::ReturnedValue exec(CppStackFrame *frame, ExecutionEngine *engine);
+ static QV4::ReturnedValue interpret(CppStackFrame *frame, ExecutionEngine *engine, const char *codeEntry);
};
} // namespace Moth
diff --git a/src/qml/jsruntime/qv4vtable_p.h b/src/qml/jsruntime/qv4vtable_p.h
new file mode 100644
index 0000000000..b4e868d45d
--- /dev/null
+++ b/src/qml/jsruntime/qv4vtable_p.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4VTABLE_P_H
+#define QV4VTABLE_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 "qv4global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct VTable
+{
+ typedef void (*Destroy)(Heap::Base *);
+ typedef void (*MarkObjects)(Heap::Base *, MarkStack *markStack);
+ typedef bool (*IsEqualTo)(Managed *m, Managed *other);
+
+ typedef ReturnedValue (*Get)(const Managed *, PropertyKey id, const Value *receiver, bool *hasProperty);
+ typedef bool (*Put)(Managed *, PropertyKey id, const Value &value, Value *receiver);
+ typedef bool (*DeleteProperty)(Managed *m, PropertyKey id);
+ typedef bool (*HasProperty)(const Managed *m, PropertyKey id);
+ typedef PropertyAttributes (*GetOwnProperty)(Managed *m, PropertyKey id, Property *p);
+ typedef bool (*DefineOwnProperty)(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs);
+ typedef bool (*IsExtensible)(const Managed *);
+ typedef bool (*PreventExtensions)(Managed *);
+ typedef Heap::Object *(*GetPrototypeOf)(const Managed *);
+ typedef bool (*SetPrototypeOf)(Managed *, const Object *);
+ typedef qint64 (*GetLength)(const Managed *m);
+ typedef void (*AdvanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ typedef ReturnedValue (*InstanceOf)(const Object *typeObject, const Value &var);
+
+ typedef ReturnedValue (*Call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ typedef ReturnedValue (*CallAsConstructor)(const FunctionObject *, const Value *argv, int argc, const Value *newTarget);
+
+ const VTable * const parent;
+ quint32 inlinePropertyOffset : 16;
+ quint32 nInlineProperties : 16;
+ quint8 isExecutionContext;
+ quint8 isString;
+ quint8 isObject;
+ quint8 isFunctionObject;
+ quint8 isErrorObject;
+ quint8 isArrayData;
+ quint8 isStringOrSymbol;
+ quint8 type;
+ quint8 unused[4];
+ const char *className;
+
+ Destroy destroy;
+ MarkObjects markObjects;
+ IsEqualTo isEqualTo;
+
+ Get get;
+ Put put;
+ DeleteProperty deleteProperty;
+ HasProperty hasProperty;
+ GetOwnProperty getOwnProperty;
+ DefineOwnProperty defineOwnProperty;
+ IsExtensible isExtensible;
+ PreventExtensions preventExtensions;
+ GetPrototypeOf getPrototypeOf;
+ SetPrototypeOf setPrototypeOf;
+ GetLength getLength;
+ AdvanceIterator advanceIterator;
+ InstanceOf instanceOf;
+
+ Call call;
+ CallAsConstructor callAsConstructor;
+};
+
+
+struct VTableBase {
+protected:
+ static constexpr VTable::Destroy virtualDestroy = nullptr;
+ static constexpr VTable::IsEqualTo virtualIsEqualTo = nullptr;
+
+ static constexpr VTable::Get virtualGet = nullptr;
+ static constexpr VTable::Put virtualPut = nullptr;
+ static constexpr VTable::DeleteProperty virtualDeleteProperty = nullptr;
+ static constexpr VTable::HasProperty virtualHasProperty = nullptr;
+ static constexpr VTable::GetOwnProperty virtualGetOwnProperty = nullptr;
+ static constexpr VTable::DefineOwnProperty virtualDefineOwnProperty = nullptr;
+ static constexpr VTable::IsExtensible virtualIsExtensible = nullptr;
+ static constexpr VTable::PreventExtensions virtualPreventExtensions = nullptr;
+ static constexpr VTable::GetPrototypeOf virtualGetPrototypeOf = nullptr;
+ static constexpr VTable::SetPrototypeOf virtualSetPrototypeOf = nullptr;
+ static constexpr VTable::GetLength virtualGetLength = nullptr;
+ static constexpr VTable::AdvanceIterator virtualAdvanceIterator = nullptr;
+ static constexpr VTable::InstanceOf virtualInstanceOf = nullptr;
+
+ static constexpr VTable::Call virtualCall = nullptr;
+ static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr;
+};
+
+#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
+{ \
+ parentVTable, \
+ (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
+ (sizeof(classname::Data) + (classname::NInlineProperties*sizeof(QV4::Value)) + QV4::Chunk::SlotSize - 1)/QV4::Chunk::SlotSize*QV4::Chunk::SlotSize/sizeof(QV4::Value) \
+ - (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
+ classname::IsExecutionContext, \
+ classname::IsString, \
+ classname::IsObject, \
+ classname::IsFunctionObject, \
+ classname::IsErrorObject, \
+ classname::IsArrayData, \
+ classname::IsStringOrSymbol, \
+ classname::MyType, \
+ { 0, 0, 0, 0 }, \
+ #classname, \
+ \
+ classname::virtualDestroy, \
+ classname::Data::markObjects, \
+ classname::virtualIsEqualTo, \
+ \
+ classname::virtualGet, \
+ classname::virtualPut, \
+ classname::virtualDeleteProperty, \
+ classname::virtualHasProperty, \
+ classname::virtualGetOwnProperty, \
+ classname::virtualDefineOwnProperty, \
+ classname::virtualIsExtensible, \
+ classname::virtualPreventExtensions, \
+ classname::virtualGetPrototypeOf, \
+ classname::virtualSetPrototypeOf, \
+ classname::virtualGetLength, \
+ classname::virtualAdvanceIterator, \
+ classname::virtualInstanceOf, \
+ \
+ classname::virtualCall, \
+ classname::virtualCallAsConstructor, \
+}
+
+#define DEFINE_MANAGED_VTABLE(classname) \
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+
+#define V4_OBJECT2(DataClass, superClass) \
+ private: \
+ DataClass() Q_DECL_EQ_DELETE; \
+ Q_DISABLE_COPY(DataClass) \
+ public: \
+ Q_MANAGED_CHECK \
+ typedef QV4::Heap::DataClass Data; \
+ typedef superClass SuperClass; \
+ static const QV4::VTable static_vtbl; \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
+ V4_MANAGED_SIZE_TEST \
+ QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
+ QV4::Heap::DataClass *d() const { \
+ QV4::Heap::DataClass *dptr = d_unchecked(); \
+ dptr->_checkIsInitialized(); \
+ return dptr; \
+ } \
+ Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
+
+#define V4_PROTOTYPE(p) \
+ static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
+ { return e->p(); }
+
+
+#define DEFINE_OBJECT_VTABLE_BASE(classname) \
+ const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, (std::is_same<classname::SuperClass, Object>::value) ? nullptr : &classname::SuperClass::static_vtbl)
+
+#define DEFINE_OBJECT_VTABLE(classname) \
+DEFINE_OBJECT_VTABLE_BASE(classname)
+
+#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \
+template<> DEFINE_OBJECT_VTABLE_BASE(classname)
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index 53933cd090..07af5a6f7a 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -54,7 +54,7 @@
#include <private/qv4global_p.h>
#include <private/qv4mmdefs_p.h>
#include <private/qv4writebarrier_p.h>
-#include <private/qv4internalclass_p.h>
+#include <private/qv4vtable_p.h>
#include <QSharedPointer>
// To check if Heap::Base::init is called (meaning, all subclasses did their init and called their
@@ -65,40 +65,43 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct InternalClass;
+namespace Heap {
-struct VTable
-{
- const VTable * const parent;
- uint inlinePropertyOffset : 16;
- uint nInlineProperties : 16;
- uint isExecutionContext : 1;
- uint isString : 1;
- uint isObject : 1;
- uint isFunctionObject : 1;
- uint isErrorObject : 1;
- uint isArrayData : 1;
- uint unused : 18;
- uint type : 8;
- const char *className;
- void (*destroy)(Heap::Base *);
- void (*markObjects)(Heap::Base *, MarkStack *markStack);
- bool (*isEqualTo)(Managed *m, Managed *other);
-};
+template <typename T, size_t o>
+struct Pointer {
+ static Q_CONSTEXPR size_t offset = o;
+ T operator->() const { return get(); }
+ operator T () const { return get(); }
-namespace Heap {
+ Base *base();
+
+ void set(EngineBase *e, T newVal) {
+ WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Base *>(newVal));
+ }
+
+ T get() const { return reinterpret_cast<T>(ptr); }
+
+ template <typename Type>
+ Type *cast() { return static_cast<Type *>(ptr); }
+
+ Base *heapObject() const { return ptr; }
+
+private:
+ Base *ptr;
+};
+typedef Pointer<char *, 0> V4PointerCheck;
+Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value);
struct Q_QML_EXPORT Base {
void *operator new(size_t) = delete;
- static void markObjects(Heap::Base *, MarkStack *) {}
+ static void markObjects(Base *, MarkStack *);
- InternalClass *internalClass;
+ Pointer<InternalClass *, 0> internalClass;
inline ReturnedValue asReturnedValue() const;
inline void mark(QV4::MarkStack *markStack);
- const VTable *vtable() const { return internalClass->vtable; }
inline bool isMarked() const {
const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
Chunk *c = h->chunk();
@@ -125,13 +128,9 @@ struct Q_QML_EXPORT Base {
return Chunk::testBit(c->objectBitmap, h - c->realBase());
}
- inline void markChildren(MarkStack *markStack) {
- vtable()->markObjects(this, markStack);
- }
-
void *operator new(size_t, Managed *m) { return m; }
- void *operator new(size_t, Heap::Base *m) { return m; }
- void operator delete(void *, Heap::Base *) {}
+ void *operator new(size_t, Base *m) { return m; }
+ void operator delete(void *, Base *) {}
void init() { _setInitialized(); }
void destroy() { _setDestroyed(); }
@@ -178,10 +177,8 @@ Q_STATIC_ASSERT(std::is_standard_layout<Base>::value);
Q_STATIC_ASSERT(offsetof(Base, internalClass) == 0);
Q_STATIC_ASSERT(sizeof(Base) == QT_POINTER_SIZE);
-}
-
inline
-void Heap::Base::mark(QV4::MarkStack *markStack)
+void Base::mark(QV4::MarkStack *markStack)
{
Q_ASSERT(inUse());
const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
@@ -196,36 +193,12 @@ void Heap::Base::mark(QV4::MarkStack *markStack)
}
}
-namespace Heap {
-
-template <typename T, size_t o>
-struct Pointer {
- static Q_CONSTEXPR size_t offset = o;
- T operator->() const { return get(); }
- operator T () const { return get(); }
-
- Heap::Base *base() {
- Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
- Q_ASSERT(base->inUse());
- return base;
- }
-
- void set(EngineBase *e, T newVal) {
- WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal));
- }
-
- T get() const { return reinterpret_cast<T>(ptr); }
-
- template <typename Type>
- Type *cast() { return static_cast<Type *>(ptr); }
-
- Heap::Base *heapObject() const { return ptr; }
-
-private:
- Heap::Base *ptr;
-};
-typedef Pointer<char *, 0> V4PointerCheck;
-Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value);
+template<typename T, size_t o>
+Base *Pointer<T, o>::base() {
+ Base *base = reinterpret_cast<Base *>(this) - (offset/sizeof(Base *));
+ Q_ASSERT(base->inUse());
+ return base;
+}
}
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 4e83abebdf..d9772e608e 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -42,6 +42,7 @@
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
#include "qv4qobjectwrapper_p.h"
+#include "qv4identifiertable_p.h"
#include <QtCore/qalgorithms.h>
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/qloggingcategory.h>
@@ -335,7 +336,7 @@ bool Chunk::sweep(ExecutionEngine *engine)
HeapItem *itemToFree = o + index;
Heap::Base *b = *itemToFree;
- const VTable *v = b->vtable();
+ const VTable *v = b->internalClass->vtable;
// if (Q_UNLIKELY(classCountPtr))
// classCountPtr(v->className);
if (v->destroy) {
@@ -389,8 +390,8 @@ void Chunk::freeAll(ExecutionEngine *engine)
HeapItem *itemToFree = o + index;
Heap::Base *b = *itemToFree;
- if (b->vtable()->destroy) {
- b->vtable()->destroy(b);
+ if (b->internalClass->vtable->destroy) {
+ b->internalClass->vtable->destroy(b);
b->_checkIsDestroyed();
}
#ifdef V4_USE_HEAPTRACK
@@ -412,10 +413,6 @@ void Chunk::resetBlackBits()
memset(blackBitmap, 0, sizeof(blackBitmap));
}
-#ifdef MM_STATS
-static uint nGrayItems = 0;
-#endif
-
void Chunk::collectGrayItems(MarkStack *markStack)
{
// DEBUG << "sweeping chunk" << this << (*freeList);
@@ -438,10 +435,6 @@ void Chunk::collectGrayItems(MarkStack *markStack)
Heap::Base *b = *itemToFree;
Q_ASSERT(b->inUse());
markStack->push(b);
-#ifdef MM_STATS
- ++nGrayItems;
-// qDebug() << "adding gray item" << b << "to mark stack";
-#endif
}
grayBitmap[i] = 0;
o += Chunk::Bits;
@@ -459,7 +452,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
#else
const int start = 1;
#endif
-#ifdef MM_STATS
+#ifndef QT_NO_DEBUG
uint freeSlots = 0;
uint allocatedSlots = 0;
#endif
@@ -469,7 +462,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
if (!i)
usedSlots |= (static_cast<quintptr>(1) << (HeaderSize/SlotSize)) - 1;
#endif
-#ifdef MM_STATS
+#ifndef QT_NO_DEBUG
allocatedSlots += qPopulationCount(usedSlots);
// qDebug() << hex << " i=" << i << "used=" << usedSlots;
#endif
@@ -486,7 +479,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
break;
}
usedSlots = (objectBitmap[i]|extendsBitmap[i]);
-#ifdef MM_STATS
+#ifndef QT_NO_DEBUG
allocatedSlots += qPopulationCount(usedSlots);
// qDebug() << hex << " i=" << i << "used=" << usedSlots;
#endif
@@ -497,7 +490,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
usedSlots |= (quintptr(1) << index) - 1;
uint freeEnd = i*Bits + index;
uint nSlots = freeEnd - freeStart;
-#ifdef MM_STATS
+#ifndef QT_NO_DEBUG
// qDebug() << hex << " got free slots from" << freeStart << "to" << freeEnd << "n=" << nSlots << "usedSlots=" << usedSlots;
freeSlots += nSlots;
#endif
@@ -508,7 +501,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
bins[bin] = freeItem;
}
}
-#ifdef MM_STATS
+#ifndef QT_NO_DEBUG
Q_ASSERT(freeSlots + allocatedSlots == (EntriesInBitmap - start) * 8 * sizeof(quintptr));
#endif
}
@@ -643,8 +636,9 @@ void BlockAllocator::sweep()
void BlockAllocator::freeAll()
{
- for (auto c : chunks) {
+ for (auto c : chunks)
c->freeAll(engine);
+ for (auto c : chunks) {
Q_V4_PROFILE_DEALLOC(engine, Chunk::DataSize, Profiling::HeapPage);
chunkAllocator->free(c);
}
@@ -691,7 +685,7 @@ static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocato
{
HeapItem *itemToFree = c.chunk->first();
Heap::Base *b = *itemToFree;
- const VTable *v = b->vtable();
+ const VTable *v = b->internalClass->vtable;
if (Q_UNLIKELY(classCountPtr))
classCountPtr(v->className);
@@ -758,6 +752,7 @@ MemoryManager::MemoryManager(ExecutionEngine *engine)
: engine(engine)
, chunkAllocator(new ChunkAllocator)
, blockAllocator(chunkAllocator, engine)
+ , icAllocator(chunkAllocator, engine)
, hugeItemAllocator(chunkAllocator, engine)
, m_persistentValues(new PersistentValueStorage(engine))
, m_weakValues(new PersistentValueStorage(engine))
@@ -774,11 +769,6 @@ MemoryManager::MemoryManager(ExecutionEngine *engine)
blockAllocator.allocationStats = statistics.allocations;
}
-#ifdef MM_STATS
-static int allocationCount = 0;
-static size_t lastAllocRequestedSlots = 0;
-#endif
-
Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize)
{
const size_t stringSize = align(sizeof(Heap::String));
@@ -884,7 +874,7 @@ Heap::Object *MemoryManager::allocObjectWithMemberData(const QV4::VTable *vtable
Chunk::clearBit(c->extendsBitmap, index);
}
o->memberData.set(engine, m);
- m->internalClass = engine->internalClasses[EngineBase::Class_MemberData];
+ m->internalClass.set(engine, engine->internalClasses(EngineBase::Class_MemberData));
Q_ASSERT(o->memberData->internalClass);
m->values.alloc = static_cast<uint>((memberSize - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
m->values.size = o->memberData->values.alloc;
@@ -911,7 +901,7 @@ void MarkStack::drain()
Heap::Base *h = pop();
++markStackSize;
Q_ASSERT(h); // at this point we should only have Heap::Base objects in this area on the stack. If not, weird things might happen.
- h->markChildren(this);
+ h->internalClass->vtable->markObjects(h, this);
}
}
@@ -1017,8 +1007,13 @@ void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPt
}
}
- blockAllocator.sweep();
- hugeItemAllocator.sweep(classCountPtr);
+
+ if (!lastSweep) {
+ engine->identifierTable->sweep();
+ blockAllocator.sweep(/*classCountPtr*/);
+ hugeItemAllocator.sweep(classCountPtr);
+ icAllocator.sweep(/*classCountPtr*/);
+ }
}
bool MemoryManager::shouldRunGC() const
@@ -1096,10 +1091,6 @@ void MemoryManager::runGC()
qDebug(stats) << "Fragmented memory before GC" << (totalMem - usedBefore);
dumpBins(&blockAllocator);
-#ifdef MM_STATS
- nGrayItems = 0;
-#endif
-
QElapsedTimer t;
t.start();
mark();
@@ -1159,7 +1150,8 @@ void MemoryManager::runGC()
if (aggressiveGC) {
// ensure we don't 'loose' any memory
- Q_ASSERT(blockAllocator.allocatedMem() == getUsedMem() + dumpBins(&blockAllocator, false));
+ Q_ASSERT(blockAllocator.allocatedMem()
+ == blockAllocator.usedMem() + dumpBins(&blockAllocator, false));
}
usedSlotsAfterLastFullSweep = blockAllocator.usedSlotsAfterLastSweep;
@@ -1167,16 +1159,17 @@ void MemoryManager::runGC()
// reset all black bits
blockAllocator.resetBlackBits();
hugeItemAllocator.resetBlackBits();
+ icAllocator.resetBlackBits();
}
size_t MemoryManager::getUsedMem() const
{
- return blockAllocator.usedMem();
+ return blockAllocator.usedMem() + icAllocator.usedMem();
}
size_t MemoryManager::getAllocatedMem() const
{
- return blockAllocator.allocatedMem() + hugeItemAllocator.usedMem();
+ return blockAllocator.allocatedMem() + icAllocator.allocatedMem() + hugeItemAllocator.usedMem();
}
size_t MemoryManager::getLargeItemsMem() const
@@ -1193,6 +1186,7 @@ MemoryManager::~MemoryManager()
sweep(/*lastSweep*/true);
blockAllocator.freeAll();
hugeItemAllocator.freeAll();
+ icAllocator.freeAll();
delete m_weakValues;
#ifdef V4_USE_VALGRIND
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 40670bcdc7..e3a011caf9 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -160,224 +160,98 @@ public:
{ return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); }
template<typename ManagedType>
- inline typename ManagedType::Data *allocManaged(std::size_t size)
+ inline typename ManagedType::Data *allocManaged(std::size_t size, Heap::InternalClass *ic)
{
Q_STATIC_ASSERT(std::is_trivial< typename ManagedType::Data >::value);
size = align(size);
- Heap::Base *o = allocData(size);
- InternalClass *ic = ManagedType::defaultInternalClass(engine);
- ic = ic->changeVTable(ManagedType::staticVTable());
- o->internalClass = ic;
- Q_ASSERT(o->internalClass && o->internalClass->vtable);
- return static_cast<typename ManagedType::Data *>(o);
+ typename ManagedType::Data *d = static_cast<typename ManagedType::Data *>(allocData(size));
+ d->internalClass.set(engine, ic);
+ Q_ASSERT(d->internalClass && d->internalClass->vtable);
+ Q_ASSERT(ic->vtable == ManagedType::staticVTable());
+ return d;
}
template<typename ManagedType>
inline typename ManagedType::Data *allocManaged(std::size_t size, InternalClass *ic)
{
- Q_STATIC_ASSERT(std::is_trivial< typename ManagedType::Data >::value);
- size = align(size);
- Heap::Base *o = allocData(size);
- o->internalClass = ic;
- Q_ASSERT(o->internalClass && o->internalClass->vtable);
- Q_ASSERT(ic->vtable == ManagedType::staticVTable());
- return static_cast<typename ManagedType::Data *>(o);
+ return allocManaged<ManagedType>(size, ic->d());
+ }
+
+ template<typename ManagedType>
+ inline typename ManagedType::Data *allocManaged(std::size_t size)
+ {
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope, ManagedType::defaultInternalClass(engine));
+ return allocManaged<ManagedType>(size, ic);
}
template <typename ObjectType>
- typename ObjectType::Data *allocateObject(InternalClass *ic)
+ typename ObjectType::Data *allocateObject(Heap::InternalClass *ic)
{
Heap::Object *o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->size);
- o->internalClass = ic;
- Q_ASSERT(o->internalClass && o->internalClass->vtable);
- Q_ASSERT(ic->vtable == ObjectType::staticVTable());
+ o->internalClass.set(engine, ic);
+ Q_ASSERT(o->internalClass.get() && o->vtable());
+ Q_ASSERT(o->vtable() == ObjectType::staticVTable());
return static_cast<typename ObjectType::Data *>(o);
}
template <typename ObjectType>
+ typename ObjectType::Data *allocateObject(InternalClass *ic)
+ {
+ return allocateObject<ObjectType>(ic->d());
+ }
+
+ template <typename ObjectType>
typename ObjectType::Data *allocateObject()
{
- InternalClass *ic = ObjectType::defaultInternalClass(engine);
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope, ObjectType::defaultInternalClass(engine));
ic = ic->changeVTable(ObjectType::staticVTable());
ic = ic->changePrototype(ObjectType::defaultPrototype(engine)->d());
- Heap::Object *o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->size);
- o->internalClass = ic;
- Q_ASSERT(o->internalClass && o->internalClass->vtable);
- Q_ASSERT(o->internalClass->prototype == ObjectType::defaultPrototype(engine)->d());
- return static_cast<typename ObjectType::Data *>(o);
+ return allocateObject<ObjectType>(ic);
}
template <typename ManagedType, typename Arg1>
typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
{
typename ManagedType::Data *o = reinterpret_cast<typename ManagedType::Data *>(allocString(unmanagedSize));
- o->internalClass = ManagedType::defaultInternalClass(engine);
+ o->internalClass.set(engine, ManagedType::defaultInternalClass(engine));
Q_ASSERT(o->internalClass && o->internalClass->vtable);
o->init(arg1);
return o;
}
- template <typename ObjectType>
- typename ObjectType::Data *allocObject(InternalClass *ic)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- t->d_unchecked()->init();
- return t->d();
- }
-
- template <typename ObjectType>
- typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr));
- Q_UNUSED(prototype);
- t->d_unchecked()->init();
- return t->d();
- }
-
- template <typename ObjectType, typename Arg1>
- typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr));
- Q_UNUSED(prototype);
- t->d_unchecked()->init(arg1);
- return t->d();
- }
-
- template <typename ObjectType, typename Arg1, typename Arg2>
- typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr));
- Q_UNUSED(prototype);
- t->d_unchecked()->init(arg1, arg2);
- return t->d();
- }
-
- template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
- typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr));
- Q_UNUSED(prototype);
- t->d_unchecked()->init(arg1, arg2, arg3);
- return t->d();
- }
-
- template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
- typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr));
- Q_UNUSED(prototype);
- t->d_unchecked()->init(arg1, arg2, arg3, arg4);
- return t->d();
- }
-
- template <typename ObjectType>
- typename ObjectType::Data *allocObject()
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- t->d_unchecked()->init();
- return t->d();
- }
-
- template <typename ObjectType, typename Arg1>
- typename ObjectType::Data *allocObject(Arg1 arg1)
+ template <typename ObjectType, typename... Args>
+ typename ObjectType::Data *allocObject(Heap::InternalClass *ic, Args... args)
{
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- t->d_unchecked()->init(arg1);
- return t->d();
- }
-
- template <typename ObjectType, typename Arg1, typename Arg2>
- typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2)
- {
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- t->d_unchecked()->init(arg1, arg2);
- return t->d();
+ typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
+ d->init(args...);
+ return d;
}
- template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
- typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ template <typename ObjectType, typename... Args>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Args... args)
{
- Scope scope(engine);
- Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- t->d_unchecked()->init(arg1, arg2, arg3);
- return t->d();
+ typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
+ d->init(args...);
+ return d;
}
- template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
- typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ template <typename ObjectType, typename... Args>
+ typename ObjectType::Data *allocate(Args... args)
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- t->d_unchecked()->init(arg1, arg2, arg3, arg4);
- return t->d();
- }
-
-
- template <typename ManagedType>
- typename ManagedType::Data *alloc()
- {
- Scope scope(engine);
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init();
- return t->d();
- }
-
- template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *alloc(Arg1 arg1)
- {
- Scope scope(engine);
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init(arg1);
- return t->d();
- }
-
- template <typename ManagedType, typename Arg1, typename Arg2>
- typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
- {
- Scope scope(engine);
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init(arg1, arg2);
- return t->d();
- }
-
- template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
- typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
- {
- Scope scope(engine);
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init(arg1, arg2, arg3);
- return t->d();
- }
-
- template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
- typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
- {
- Scope scope(engine);
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init(arg1, arg2, arg3, arg4);
+ t->d_unchecked()->init(args...);
return t->d();
}
- template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
- typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+ template <typename ManagedType, typename... Args>
+ typename ManagedType::Data *alloc(Args... args)
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5);
+ t->d_unchecked()->init(args...);
return t->d();
}
@@ -392,6 +266,14 @@ public:
// called when a JS object grows itself. Specifically: Heap::String::append
void changeUnmanagedHeapSizeUsage(qptrdiff delta) { unmanagedHeapSize += delta; }
+ template<typename ManagedType>
+ typename ManagedType::Data *allocIC()
+ {
+ size_t size = align(sizeof(typename ManagedType::Data));
+ Heap::Base *b = *icAllocator.allocate(size, true);
+ return static_cast<typename ManagedType::Data *>(b);
+ }
+
protected:
/// expects size to be aligned
Heap::Base *allocString(std::size_t unmanagedSize);
@@ -409,6 +291,7 @@ public:
QV4::ExecutionEngine *engine;
ChunkAllocator *chunkAllocator;
BlockAllocator blockAllocator;
+ BlockAllocator icAllocator;
HugeItemAllocator hugeItemAllocator;
PersistentValueStorage *m_persistentValues;
PersistentValueStorage *m_weakValues;
@@ -423,6 +306,9 @@ public:
bool gcStats = false;
bool gcCollectorStats = false;
+ int allocationCount = 0;
+ size_t lastAllocRequestedSlots = 0;
+
struct {
size_t maxReservedMem = 0;
size_t maxAllocatedMem = 0;
diff --git a/src/qml/parser/parser.pri b/src/qml/parser/parser.pri
index e5b8ae2749..adab4ef9a2 100644
--- a/src/qml/parser/parser.pri
+++ b/src/qml/parser/parser.pri
@@ -3,20 +3,24 @@ HEADERS += \
$$PWD/qqmljsastfwd_p.h \
$$PWD/qqmljsastvisitor_p.h \
$$PWD/qqmljsengine_p.h \
- $$PWD/qqmljsgrammar_p.h \
$$PWD/qqmljslexer_p.h \
$$PWD/qqmljsmemorypool_p.h \
- $$PWD/qqmljsparser_p.h \
$$PWD/qqmljsglobal_p.h \
$$PWD/qqmljskeywords_p.h \
+ $$PWD/qqmljsengine_p.h \
+ $$PWD/qqmljsglobal_p.h
SOURCES += \
$$PWD/qqmljsast.cpp \
$$PWD/qqmljsastvisitor.cpp \
$$PWD/qqmljsengine_p.cpp \
- $$PWD/qqmljsgrammar.cpp \
$$PWD/qqmljslexer.cpp \
- $$PWD/qqmljsparser.cpp \
-OTHER_FILES += \
- $$PWD/qqmljs.g
+CONFIG += qlalr
+QLALRSOURCES = $$PWD/qqmljs.g
+QMAKE_QLALRFLAGS = --no-debug --qt
+
+OTHER_FILES += $$QLALRSOURCES
+
+# make sure we install the headers generated by qlalr
+private_headers.CONFIG += no_check_exist
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index d2d947e55c..cd40a77299 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -40,8 +40,7 @@
%parser QQmlJSGrammar
%decl qqmljsparser_p.h
%impl qqmljsparser.cpp
-%expect 5
-%expect-rr 2
+%expect 1
%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
@@ -64,7 +63,8 @@
%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
-%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
+%token T_STAR_STAR "**" T_STAR_STAR_EQ "**=" T_STAR_EQ "*="
+%token T_STRING_LITERAL "string literal"
%token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly"
%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
@@ -77,14 +77,29 @@
%token T_MULTILINE_STRING_LITERAL "multiline string literal"
%token T_COMMENT "comment"
%token T_COMPATIBILITY_SEMICOLON
+%token T_ARROW "=>"
%token T_ENUM "enum"
+%token T_ELLIPSIS "..."
+%token T_YIELD "yield"
+%token T_SUPER "super"
+%token T_CLASS "class"
+%token T_EXTENDS "extends"
+%token T_STATIC "static"
+%token T_EXPORT "export"
+%token T_FROM "from"
+
+--- template strings
+%token T_NO_SUBSTITUTION_TEMPLATE"(no subst template)"
+%token T_TEMPLATE_HEAD "(template head)"
+%token T_TEMPLATE_MIDDLE "(template middle)"
+%token T_TEMPLATE_TAIL "(template tail)"
--- context keywords.
%token T_PUBLIC "public"
%token T_IMPORT "import"
%token T_PRAGMA "pragma"
%token T_AS "as"
-%token T_ON "on"
+%token T_OF "of"
%token T_GET "get"
%token T_SET "set"
@@ -95,11 +110,16 @@
%token T_FEED_UI_OBJECT_MEMBER
%token T_FEED_JS_STATEMENT
%token T_FEED_JS_EXPRESSION
-%token T_FEED_JS_SOURCE_ELEMENT
-%token T_FEED_JS_PROGRAM
+%token T_FEED_JS_SCRIPT
+%token T_FEED_JS_MODULE
-%nonassoc SHIFT_THERE
-%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET
+--- Lookahead handling
+%token T_FORCE_DECLARATION "(force decl)"
+%token T_FORCE_BLOCK "(force block)"
+%token T_FOR_LOOKAHEAD_OK "(for lookahead ok)"
+
+--%left T_PLUS T_MINUS
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_OF T_STATIC T_FROM
%nonassoc REDUCE_HERE
%start TopLevel
@@ -143,10 +163,10 @@
**
****************************************************************************/
-#include "qqmljsengine_p.h"
-#include "qqmljslexer_p.h"
-#include "qqmljsast_p.h"
-#include "qqmljsmemorypool_p.h"
+#include <private/qqmljsengine_p.h>
+#include <private/qqmljslexer_p.h>
+#include <private/qqmljsast_p.h>
+#include <private/qqmljsmemorypool_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>
@@ -221,10 +241,10 @@
#ifndef QQMLJSPARSER_P_H
#define QQMLJSPARSER_P_H
-#include "qqmljsglobal_p.h"
-#include "qqmljsgrammar_p.h"
-#include "qqmljsast_p.h"
-#include "qqmljsengine_p.h"
+#include <private/qqmljsglobal_p.h>
+#include <private/qqmljsgrammar_p.h>
+#include <private/qqmljsast_p.h>
+#include <private/qqmljsengine_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qstring.h>
@@ -241,30 +261,32 @@ public:
union Value {
int ival;
double dval;
+ AST::VariableScope scope;
+ AST::ForEachType forEachType;
AST::ArgumentList *ArgumentList;
AST::CaseBlock *CaseBlock;
AST::CaseClause *CaseClause;
AST::CaseClauses *CaseClauses;
AST::Catch *Catch;
AST::DefaultClause *DefaultClause;
- AST::ElementList *ElementList;
AST::Elision *Elision;
AST::ExpressionNode *Expression;
+ AST::TemplateLiteral *Template;
AST::Finally *Finally;
AST::FormalParameterList *FormalParameterList;
- AST::FunctionBody *FunctionBody;
AST::FunctionDeclaration *FunctionDeclaration;
AST::Node *Node;
AST::PropertyName *PropertyName;
- AST::PropertyAssignment *PropertyAssignment;
- AST::PropertyAssignmentList *PropertyAssignmentList;
- AST::SourceElement *SourceElement;
- AST::SourceElements *SourceElements;
AST::Statement *Statement;
AST::StatementList *StatementList;
AST::Block *Block;
- AST::VariableDeclaration *VariableDeclaration;
AST::VariableDeclarationList *VariableDeclarationList;
+ AST::Pattern *Pattern;
+ AST::PatternElement *PatternElement;
+ AST::PatternElementList *PatternElementList;
+ AST::PatternProperty *PatternProperty;
+ AST::PatternPropertyList *PatternPropertyList;
+ AST::ClassElementList *ClassElementList;
AST::UiProgram *UiProgram;
AST::UiHeaderItemList *UiHeaderItemList;
@@ -290,12 +312,13 @@ public:
~Parser();
// parse a UI program
- bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parse() { ++functionNestingLevel; bool r = parse(T_FEED_UI_PROGRAM); --functionNestingLevel; return r; }
bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
- bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); }
- bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
- bool parseProgram() { return parse(T_FEED_JS_PROGRAM); }
+ bool parseUiObjectMember() { ++functionNestingLevel; bool r = parse(T_FEED_UI_OBJECT_MEMBER); --functionNestingLevel; return r; }
+ bool parseProgram() { return parse(T_FEED_JS_SCRIPT); }
+ bool parseScript() { return parse(T_FEED_JS_SCRIPT); }
+ bool parseModule() { return parse(T_FEED_JS_MODULE); }
AST::UiProgram *ast() const
{ return AST::cast<AST::UiProgram *>(program); }
@@ -366,20 +389,30 @@ protected:
AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
AST::UiQualifiedPragmaId *reparseAsQualifiedPragmaId(AST::ExpressionNode *expr);
+ void pushToken(int token);
+ int lookaheadToken(Lexer *lexer);
+
+ void syntaxError(const AST::SourceLocation &location, const char *message) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, QLatin1String(message)));
+ }
+ void syntaxError(const AST::SourceLocation &location, const QString &message) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, message));
+ }
+
protected:
Engine *driver;
MemoryPool *pool;
- int tos;
- int stack_size;
- Value *sym_stack;
- int *state_stack;
- AST::SourceLocation *location_stack;
- QStringRef *string_stack;
+ int tos = 0;
+ int stack_size = 0;
+ Value *sym_stack = nullptr;
+ int *state_stack = nullptr;
+ AST::SourceLocation *location_stack = nullptr;
+ QVector<QStringRef> string_stack;
- AST::Node *program;
+ AST::Node *program = nullptr;
- // error recovery
- enum { TOKEN_BUFFER_SIZE = 3 };
+ // error recovery and lookahead handling
+ enum { TOKEN_BUFFER_SIZE = 5 };
struct SavedToken {
int token;
@@ -388,14 +421,25 @@ protected:
QStringRef spell;
};
- double yylval;
+ int yytoken = -1;
+ double yylval = 0.;
QStringRef yytokenspell;
AST::SourceLocation yylloc;
AST::SourceLocation yyprevlloc;
SavedToken token_buffer[TOKEN_BUFFER_SIZE];
- SavedToken *first_token;
- SavedToken *last_token;
+ SavedToken *first_token = nullptr;
+ SavedToken *last_token = nullptr;
+
+ int functionNestingLevel = 0;
+
+ enum CoverExpressionType {
+ CE_Invalid,
+ CE_ParenthesizedExpression,
+ CE_FormalParameterList
+ };
+ AST::SourceLocation coverExpressionErrorLocation;
+ CoverExpressionType coverExpressionType = CE_Invalid;
QList<DiagnosticMessage> diagnostic_messages;
};
@@ -424,6 +468,8 @@ protected:
// qlalr --no-debug --no-lines --qt qqmljs.g
//
+#define UNIMPLEMENTED syntaxError(loc(1), "Unimplemented"); return false
+
using namespace QQmlJS;
QT_QML_BEGIN_NAMESPACE
@@ -438,22 +484,12 @@ void Parser::reallocateStack()
sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value)));
state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int)));
location_stack = reinterpret_cast<AST::SourceLocation*> (realloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
- string_stack = reinterpret_cast<QStringRef*> (realloc(string_stack, stack_size * sizeof(QStringRef)));
+ string_stack.resize(stack_size);
}
Parser::Parser(Engine *engine):
driver(engine),
- pool(engine->pool()),
- tos(0),
- stack_size(0),
- sym_stack(0),
- state_stack(0),
- location_stack(0),
- string_stack(0),
- program(0),
- yylval(0),
- first_token(0),
- last_token(0)
+ pool(engine->pool())
{
}
@@ -463,7 +499,6 @@ Parser::~Parser()
free(sym_stack);
free(state_stack);
free(location_stack);
- free(string_stack);
}
}
@@ -517,17 +552,39 @@ AST::UiQualifiedPragmaId *Parser::reparseAsQualifiedPragmaId(AST::ExpressionNode
return 0;
}
+void Parser::pushToken(int token)
+{
+ last_token->token = yytoken;
+ last_token->dval = yylval;
+ last_token->spell = yytokenspell;
+ last_token->loc = yylloc;
+ ++last_token;
+ yytoken = token;
+}
+
+int Parser::lookaheadToken(Lexer *lexer)
+{
+ if (yytoken < 0) {
+ yytoken = lexer->lex();
+ yylval = lexer->tokenValue();
+ yytokenspell = lexer->tokenSpell();
+ yylloc = location(lexer);
+ }
+ return yytoken;
+}
+
+//#define PARSER_DEBUG
bool Parser::parse(int startToken)
{
Lexer *lexer = driver->lexer();
bool hadErrors = false;
- int yytoken = -1;
+ yytoken = -1;
int action = 0;
token_buffer[0].token = startToken;
first_token = &token_buffer[0];
- if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) {
+ if (startToken == T_FEED_JS_SCRIPT && !lexer->qmlMode()) {
Directives ignoreDirectives;
Directives *directives = driver->directives();
if (!directives)
@@ -570,10 +627,19 @@ bool Parser::parse(int startToken)
yytokenspell = first_token->spell;
yylloc = first_token->loc;
++first_token;
+ if (first_token == last_token)
+ first_token = last_token = &token_buffer[0];
}
}
+#ifdef PARSER_DEBUG
+ qDebug() << " in state" << action;
+#endif
+
action = t_action(action, yytoken);
+#ifdef PARSER_DEBUG
+ qDebug() << " current token" << yytoken << (yytoken >= 0 ? spell[yytoken] : "(null)") << "new state" << action;
+#endif
if (action > 0) {
if (action != ACCEPT_STATE) {
yytoken = -1;
@@ -588,6 +654,10 @@ bool Parser::parse(int startToken)
const int r = -action - 1;
tos -= rhs[r];
+#ifdef PARSER_DEBUG
+ qDebug() << " reducing through rule " << -action;
+#endif
+
switch (r) {
./
@@ -595,2582 +665,3463 @@ bool Parser::parse(int startToken)
-- Declarative UI
--------------------------------------------------------------------------------------------------------
-TopLevel: T_FEED_UI_PROGRAM UiProgram ;
+TopLevel: T_FEED_UI_PROGRAM UiProgram;
/.
-case $rule_number: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+ } break;
./
-TopLevel: T_FEED_JS_STATEMENT Statement ;
+TopLevel: T_FEED_JS_STATEMENT Statement;
/.
-case $rule_number: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+ } break;
./
-TopLevel: T_FEED_JS_EXPRESSION Expression ;
+TopLevel: T_FEED_JS_EXPRESSION Expression;
/.
-case $rule_number: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+ } break;
./
-TopLevel: T_FEED_JS_SOURCE_ELEMENT SourceElement ;
+TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember;
/.
-case $rule_number: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+ } break;
./
-TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ;
+TopLevel: T_FEED_JS_SCRIPT Script;
/.
-case $rule_number: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+ } break;
./
-TopLevel: T_FEED_JS_PROGRAM Program ;
+TopLevel: T_FEED_JS_MODULE Module;
/.
-case $rule_number: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+ } break;
./
+
UiProgram: UiHeaderItemListOpt UiRootMember;
/.
-case $rule_number: {
- sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiHeaderItemList,
- sym(2).UiObjectMemberList->finish());
-} break;
+ case $rule_number: {
+ sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiHeaderItemList, sym(2).UiObjectMemberList->finish());
+ } break;
./
-UiHeaderItemListOpt: Empty ;
-UiHeaderItemListOpt: UiHeaderItemList ;
+UiHeaderItemListOpt: Empty;
+UiHeaderItemListOpt: UiHeaderItemList;
/.
-case $rule_number: {
- sym(1).Node = sym(1).UiHeaderItemList->finish();
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(1).UiHeaderItemList->finish();
+ } break;
./
-UiHeaderItemList: UiPragma ;
+UiHeaderItemList: UiPragma;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiPragma);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiPragma);
+ } break;
./
-UiHeaderItemList: UiImport ;
+UiHeaderItemList: UiImport;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiImport);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiImport);
+ } break;
./
-UiHeaderItemList: UiHeaderItemList UiPragma ;
+UiHeaderItemList: UiHeaderItemList UiPragma;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiPragma);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiPragma);
+ } break;
./
-UiHeaderItemList: UiHeaderItemList UiImport ;
+UiHeaderItemList: UiHeaderItemList UiImport;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiImport);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiImport);
+ } break;
./
-PragmaId: MemberExpression ;
+PragmaId: MemberExpression;
-ImportId: MemberExpression ;
+ImportId: MemberExpression;
-UiPragma: UiPragmaHead T_AUTOMATIC_SEMICOLON ;
-UiPragma: UiPragmaHead T_SEMICOLON ;
+UiPragma: UiPragmaHead T_AUTOMATIC_SEMICOLON;
+UiPragma: UiPragmaHead T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).UiPragma->semicolonToken = loc(2);
-} break;
+ case $rule_number: {
+ sym(1).UiPragma->semicolonToken = loc(2);
+ } break;
./
-UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ;
-UiImport: UiImportHead T_SEMICOLON ;
+UiImport: UiImportHead T_AUTOMATIC_SEMICOLON;
+UiImport: UiImportHead T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).UiImport->semicolonToken = loc(2);
-} break;
+ case $rule_number: {
+ sym(1).UiImport->semicolonToken = loc(2);
+ } break;
./
-UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ;
-UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).UiImport->versionToken = loc(2);
- sym(1).UiImport->semicolonToken = loc(3);
-} break;
+ case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+ } break;
./
-UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
-UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS QmlIdentifier T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).UiImport->versionToken = loc(2);
- sym(1).UiImport->asToken = loc(3);
- sym(1).UiImport->importIdToken = loc(4);
- sym(1).UiImport->importId = stringRef(4);
- sym(1).UiImport->semicolonToken = loc(5);
-} break;
+ case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = stringRef(4);
+ sym(1).UiImport->semicolonToken = loc(5);
+ } break;
./
-UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
-UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ;
+UiImport: UiImportHead T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiImport: UiImportHead T_AS QmlIdentifier T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).UiImport->asToken = loc(2);
- sym(1).UiImport->importIdToken = loc(3);
- sym(1).UiImport->importId = stringRef(3);
- sym(1).UiImport->semicolonToken = loc(4);
-} break;
+ case $rule_number: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = stringRef(3);
+ sym(1).UiImport->semicolonToken = loc(4);
+ } break;
./
-UiPragmaHead: T_PRAGMA PragmaId ;
+UiPragmaHead: T_PRAGMA PragmaId;
/.
-case $rule_number: {
- AST::UiPragma *node = 0;
+ case $rule_number: {
+ AST::UiPragma *node = 0;
- if (AST::UiQualifiedPragmaId *qualifiedId = reparseAsQualifiedPragmaId(sym(2).Expression)) {
- node = new (pool) AST::UiPragma(qualifiedId);
- }
+ if (AST::UiQualifiedPragmaId *qualifiedId = reparseAsQualifiedPragmaId(sym(2).Expression))
+ node = new (pool) AST::UiPragma(qualifiedId);
- sym(1).Node = node;
+ sym(1).Node = node;
- if (node) {
- node->pragmaToken = loc(1);
- } else {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
- QLatin1String("Expected a qualified name id")));
+ if (node) {
+ node->pragmaToken = loc(1);
+ } else {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
- return false; // ### remove me
- }
-} break;
+ return false; // ### remove me
+ }
+ } break;
./
-UiImportHead: T_IMPORT ImportId ;
+UiImportHead: T_IMPORT ImportId;
/.
-case $rule_number: {
- AST::UiImport *node = 0;
-
- if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
- node = new (pool) AST::UiImport(importIdLiteral->value);
- node->fileNameToken = loc(2);
- } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
- node = new (pool) AST::UiImport(qualifiedId);
- node->fileNameToken = loc(2);
- }
+ case $rule_number: {
+ AST::UiImport *node = 0;
- sym(1).Node = node;
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = new (pool) AST::UiImport(importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ node = new (pool) AST::UiImport(qualifiedId);
+ node->fileNameToken = loc(2);
+ }
- if (node) {
- node->importToken = loc(1);
- } else {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
- QLatin1String("Expected a qualified name id or a string literal")));
+ sym(1).Node = node;
- return false; // ### remove me
- }
-} break;
+ if (node) {
+ node->importToken = loc(1);
+ } else {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+ } break;
./
Empty: ;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-UiRootMember: UiObjectDefinition ;
+UiRootMember: UiObjectDefinition;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
+ } break;
./
-UiObjectMemberList: UiObjectMember ;
+UiObjectMemberList: UiObjectMember;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
+ } break;
./
-UiObjectMemberList: UiObjectMemberList UiObjectMember ;
+UiObjectMemberList: UiObjectMemberList UiObjectMember;
/.
-case $rule_number: {
- AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList(
- sym(1).UiObjectMemberList, sym(2).UiObjectMember);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList(sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+ } break;
./
-UiArrayMemberList: UiObjectDefinition ;
+UiArrayMemberList: UiObjectDefinition;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember);
+ } break;
./
-UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ;
+UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition;
/.
-case $rule_number: {
- AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList(
- sym(1).UiArrayMemberList, sym(3).UiObjectMember);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList(sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-UiObjectInitializer: T_LBRACE T_RBRACE ;
+UiObjectInitializer: T_LBRACE T_RBRACE;
/.
-case $rule_number: {
- AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ;
+UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE;
/.
-case $rule_number: {
- AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish());
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-UiObjectDefinition: UiQualifiedId UiObjectInitializer ;
+UiObjectDefinition: UiQualifiedId UiObjectInitializer;
/.
-case $rule_number: {
- AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId,
- sym(2).UiObjectInitializer);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: UiObjectDefinition ;
+UiObjectMember: UiObjectDefinition;
-UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+UiObjectMember: UiQualifiedId T_COLON ExpressionStatementLookahead T_LBRACKET UiArrayMemberList T_RBRACKET;
/.
-case $rule_number: {
- AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding(
- sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
- node->colonToken = loc(2);
- node->lbracketToken = loc(3);
- node->rbracketToken = loc(5);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding(sym(1).UiQualifiedId, sym(5).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(4);
+ node->rbracketToken = loc(6);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+UiObjectMember: UiQualifiedId T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer;
/.
-case $rule_number: {
- AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding(
- sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding(
+ sym(1).UiQualifiedId, sym(4).UiQualifiedId, sym(5).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer ;
+UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer;
/.
-case $rule_number: {
- AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding(
- sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer);
- node->colonToken = loc(2);
- node->hasOnToken = true;
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding(
+ sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ node->hasOnToken = true;
+ sym(1).Node = node;
+ } break;
./
-UiScriptStatement: Block ;
-UiScriptStatement: EmptyStatement ;
-UiScriptStatement: ExpressionStatement ;
-UiScriptStatement: IfStatement ;
-UiScriptStatement: WithStatement ;
-UiScriptStatement: SwitchStatement ;
-UiScriptStatement: TryStatement ;
-UiObjectMember: UiQualifiedId T_COLON UiScriptStatement ;
+UiObjectLiteral: T_LBRACE ExpressionStatementLookahead UiPropertyDefinitionList T_RBRACE;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiObjectLiteral: T_LBRACE ExpressionStatementLookahead UiPropertyDefinitionList T_COMMA T_RBRACE;
/.
-case $rule_number:
-{
- AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding(
- sym(1).UiQualifiedId, sym(3).Statement);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ObjectPattern *l = new (pool) AST::ObjectPattern(sym(3).PatternPropertyList->finish());
+ l->lbraceToken = loc(1);
+ l->rbraceToken = loc(4);
+ AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(l);
+ sym(1).Node = node;
+ } break;
./
-UiPropertyType: T_VAR ;
-/.
-case $rule_number: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-./
-UiPropertyType: T_RESERVED_WORD ;
+UiScriptStatement: ExpressionStatementLookahead T_FORCE_DECLARATION ExpressionStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead T_FORCE_BLOCK Block;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead T_FORCE_BLOCK UiObjectLiteral;
/.
-case $rule_number: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(3).Node;
+ } break;
./
-UiPropertyType: T_IDENTIFIER ;
-/.
-case $rule_number: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-./
-UiPropertyType: UiPropertyType T_DOT T_IDENTIFIER ;
+UiScriptStatement: ExpressionStatementLookahead EmptyStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead ExpressionStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead IfStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead WithStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead SwitchStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+UiScriptStatement: ExpressionStatementLookahead TryStatement;
/.
-case $rule_number: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(sym(1).UiQualifiedId, stringRef(3));
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ } break;
./
-UiParameterListOpt: ;
+UiObjectMember: UiQualifiedId T_COLON UiScriptStatement;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+case $rule_number:
+{
+ AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding(sym(1).UiQualifiedId, sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-UiParameterListOpt: UiParameterList ;
+UiPropertyType: T_VAR;
/.
-case $rule_number: {
- sym(1).Node = sym(1).UiParameterList->finish ();
-} break;
+ case $rule_number: {
+ AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UiParameterList: UiPropertyType JsIdentifier ;
+UiPropertyType: T_RESERVED_WORD;
/.
-case $rule_number: {
- AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiQualifiedId->finish(), stringRef(2));
- node->propertyTypeToken = loc(1);
- node->identifierToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ;
+UiPropertyType: T_IDENTIFIER;
/.
-case $rule_number: {
- AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(3).UiQualifiedId->finish(), stringRef(4));
- node->propertyTypeToken = loc(3);
- node->commaToken = loc(2);
- node->identifierToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ;
-UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ;
+UiPropertyType: UiPropertyType T_DOT T_IDENTIFIER;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2));
- node->type = AST::UiPublicMember::Signal;
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(2);
- node->parameters = sym(4).UiParameterList;
- node->semicolonToken = loc(6);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(sym(1).UiQualifiedId, stringRef(3));
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
-UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ;
+UiParameterListOpt: ;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2));
- node->type = AST::UiPublicMember::Signal;
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(2);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_AUTOMATIC_SEMICOLON ;
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ;
+UiParameterListOpt: UiParameterList;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
- node->typeModifier = stringRef(2);
- node->propertyToken = loc(1);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(6);
- node->semicolonToken = loc(7);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(1).UiParameterList->finish();
+ } break;
./
-UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ;
-UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ;
+UiParameterList: UiPropertyType QmlIdentifier;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(3);
- node->semicolonToken = loc(4);
- sym(1).Node = node;
-} break;
-./
+ case $rule_number: {
+ AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiQualifiedId->finish(), stringRef(2));
+ node->propertyTypeToken = loc(1);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ;
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ;
+UiParameterList: UiParameterList T_COMMA UiPropertyType QmlIdentifier;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
- node->isDefaultMember = true;
- node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5);
- sym(1).Node = node;
-} break;
-./
-
-UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_AUTOMATIC_SEMICOLON ;
-UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ;
+ case $rule_number: {
+ AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(3).UiQualifiedId->finish(), stringRef(4));
+ node->propertyTypeToken = loc(3);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
- node->isDefaultMember = true;
- node->defaultToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8);
- sym(1).Node = node;
-} break;
-./
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2));
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2));
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
+ node->typeModifier = stringRef(2);
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+ } break;
+./
-UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ;
-/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3),
- sym(5).Statement);
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(3);
- node->colonToken = loc(4);
- sym(1).Node = node;
-} break;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON;
+UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->typeModifier = stringRef(3);
+ node->propertyToken = loc(2);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(7);
+ node->semicolonToken = loc(8);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3), sym(5).Statement);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement;
+/.
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement);
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4),
- sym(6).Statement);
- node->isReadonlyMember = true;
- node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ;
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4),
- sym(6).Statement);
- node->isDefaultMember = true;
- node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
- sym(1).Node = node;
-} break;
-./
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
+ node->typeModifier = stringRef(2);
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7); // insert a fake ';' before ':'
-UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
-/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
- node->typeModifier = stringRef(2);
- node->propertyToken = loc(1);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(6);
- node->semicolonToken = loc(7); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6));
- propertyName->identifierToken = loc(6);
- propertyName->next = 0;
-
- AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(
- propertyName, sym(9).UiArrayMemberList->finish());
- binding->colonToken = loc(7);
- binding->lbracketToken = loc(8);
- binding->rbracketToken = loc(10);
-
- node->binding = binding;
+ AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6));
+ propertyName->identifierToken = loc(6);
+ propertyName->next = 0;
- sym(1).Node = node;
-} break;
+ AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(propertyName, sym(9).UiArrayMemberList->finish());
+ binding->colonToken = loc(7);
+ binding->lbracketToken = loc(8);
+ binding->rbracketToken = loc(10);
+
+ node->binding = binding;
+
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ;
+UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(3);
- node->semicolonToken = loc(4); // insert a fake ';' before ':'
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4); // insert a fake ';' before ':'
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3));
- propertyName->identifierToken = loc(3);
- propertyName->next = 0;
+ AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3));
+ propertyName->identifierToken = loc(3);
+ propertyName->next = 0;
- AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
- propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer);
- binding->colonToken = loc(4);
+ AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
+ propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer);
+ binding->colonToken = loc(4);
- node->binding = binding;
+ node->binding = binding;
- sym(1).Node = node;
-} break;
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ;
+UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer;
/.
-case $rule_number: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
- node->isReadonlyMember = true;
- node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5); // insert a fake ';' before ':'
+ case $rule_number: {
+ AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5); // insert a fake ';' before ':'
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4));
- propertyName->identifierToken = loc(4);
- propertyName->next = 0;
+ AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4));
+ propertyName->identifierToken = loc(4);
+ propertyName->next = 0;
- AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
- propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer);
- binding->colonToken = loc(5);
+ AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
+ propertyName, sym(7).UiQualifiedId, sym(8).UiObjectInitializer);
+ binding->colonToken = loc(5);
- node->binding = binding;
+ node->binding = binding;
- sym(1).Node = node;
-} break;
+ sym(1).Node = node;
+ } break;
./
-UiObjectMember: FunctionDeclaration ;
+UiObjectMember: FunctionDeclaration;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
+ } break;
./
-UiObjectMember: VariableStatement ;
+UiObjectMember: VariableStatement;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
+ } break;
+./
+
+UiQualifiedId: MemberExpression;
+/.
+ case $rule_number: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+ } break;
./
UiObjectMember: T_ENUM T_IDENTIFIER T_LBRACE EnumMemberList T_RBRACE;
/.
-case $rule_number: {
- AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish());
- enumDeclaration->enumToken = loc(1);
- enumDeclaration->rbraceToken = loc(5);
- sym(1).Node = enumDeclaration;
- break;
-}
+ case $rule_number: {
+ AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish());
+ enumDeclaration->enumToken = loc(1);
+ enumDeclaration->rbraceToken = loc(5);
+ sym(1).Node = enumDeclaration;
+ break;
+ }
./
EnumMemberList: T_IDENTIFIER;
/.
-case $rule_number: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1));
- node->memberToken = loc(1);
- sym(1).Node = node;
- break;
-}
+ case $rule_number: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1));
+ node->memberToken = loc(1);
+ sym(1).Node = node;
+ break;
+ }
./
EnumMemberList: T_IDENTIFIER T_EQ T_NUMERIC_LITERAL;
/.
-case $rule_number: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1), sym(3).dval);
- node->memberToken = loc(1);
- node->valueToken = loc(3);
- sym(1).Node = node;
- break;
-}
+ case $rule_number: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1), sym(3).dval);
+ node->memberToken = loc(1);
+ node->valueToken = loc(3);
+ sym(1).Node = node;
+ break;
+ }
./
EnumMemberList: EnumMemberList T_COMMA T_IDENTIFIER;
/.
-case $rule_number: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3));
- node->memberToken = loc(3);
- sym(1).Node = node;
- break;
-}
+ case $rule_number: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3));
+ node->memberToken = loc(3);
+ sym(1).Node = node;
+ break;
+ }
./
EnumMemberList: EnumMemberList T_COMMA T_IDENTIFIER T_EQ T_NUMERIC_LITERAL;
/.
-case $rule_number: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3), sym(5).dval);
- node->memberToken = loc(3);
- node->valueToken = loc(5);
- sym(1).Node = node;
- break;
-}
+ case $rule_number: {
+ AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3), sym(5).dval);
+ node->memberToken = loc(3);
+ node->valueToken = loc(5);
+ sym(1).Node = node;
+ break;
+ }
./
-JsIdentifier: T_IDENTIFIER;
+QmlIdentifier: T_IDENTIFIER;
+QmlIdentifier: T_PROPERTY;
+QmlIdentifier: T_SIGNAL;
+QmlIdentifier: T_READONLY;
+QmlIdentifier: T_ON;
+QmlIdentifier: T_GET;
+QmlIdentifier: T_SET;
+QmlIdentifier: T_FROM;
+QmlIdentifier: T_OF;
-JsIdentifier: T_PROPERTY ;
-JsIdentifier: T_SIGNAL ;
-JsIdentifier: T_READONLY ;
-JsIdentifier: T_ON ;
-JsIdentifier: T_GET ;
-JsIdentifier: T_SET ;
+JsIdentifier: T_IDENTIFIER;
+JsIdentifier: T_PROPERTY;
+JsIdentifier: T_SIGNAL;
+JsIdentifier: T_READONLY;
+JsIdentifier: T_ON;
+JsIdentifier: T_GET;
+JsIdentifier: T_SET;
+JsIdentifier: T_FROM;
+JsIdentifier: T_STATIC;
+JsIdentifier: T_OF;
+
+IdentifierReference: JsIdentifier;
+BindingIdentifier: IdentifierReference;
--------------------------------------------------------------------------------------------------------
-- Expressions
--------------------------------------------------------------------------------------------------------
-PrimaryExpression: T_THIS ;
+PrimaryExpression: T_THIS;
/.
-case $rule_number: {
- AST::ThisExpression *node = new (pool) AST::ThisExpression();
- node->thisToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ThisExpression *node = new (pool) AST::ThisExpression();
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PrimaryExpression: JsIdentifier ;
+PrimaryExpression: IdentifierReference;
/.
-case $rule_number: {
- AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PrimaryExpression: T_NULL ;
+PrimaryExpression: Literal;
+PrimaryExpression: ArrayLiteral;
+PrimaryExpression: ObjectLiteral;
+PrimaryExpression: FunctionExpression;
+PrimaryExpression: ClassExpression;
+PrimaryExpression: GeneratorExpression;
+PrimaryExpression: RegularExpressionLiteral;
+PrimaryExpression: TemplateLiteral;
+
+PrimaryExpression: CoverParenthesizedExpressionAndArrowParameterList;
/.
-case $rule_number: {
- AST::NullExpression *node = new (pool) AST::NullExpression();
- node->nullToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ if (coverExpressionType != CE_ParenthesizedExpression) {
+ syntaxError(coverExpressionErrorLocation, "Expected token ')'.");
+ return false;
+ }
+ } break;
./
-PrimaryExpression: T_TRUE ;
+-- Parsing of the CoverParenthesizedExpressionAndArrowParameterList is restricted to the one rule below when this is parsed as a primary expression
+CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN Expression_In T_RPAREN;
/.
-case $rule_number: {
- AST::TrueLiteral *node = new (pool) AST::TrueLiteral();
- node->trueToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+ coverExpressionType = CE_ParenthesizedExpression;
+ } break;
./
-PrimaryExpression: T_FALSE ;
+CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN T_RPAREN;
/.
-case $rule_number: {
- AST::FalseLiteral *node = new (pool) AST::FalseLiteral();
- node->falseToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ coverExpressionErrorLocation = loc(2);
+ coverExpressionType = CE_FormalParameterList;
+ } break;
./
-PrimaryExpression: T_NUMERIC_LITERAL ;
+CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN BindingRestElement T_RPAREN;
/.
-case $rule_number: {
- AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval);
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FormalParameterList *node = (new (pool) AST::FormalParameterList(nullptr, sym(2).PatternElement))->finish(pool);
+ sym(1).Node = node;
+ coverExpressionErrorLocation = loc(2);
+ coverExpressionType = CE_FormalParameterList;
+ } break;
./
-PrimaryExpression: T_MULTILINE_STRING_LITERAL ;
-/.case $rule_number:./
+CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN Expression_In T_COMMA BindingRestElementOpt T_RPAREN;
+/.
+ case $rule_number: {
+ AST::FormalParameterList *list = sym(2).Expression->reparseAsFormalParameterList(pool);
+ if (!list) {
+ syntaxError(loc(1), "Invalid Arrow parameter list.");
+ return false;
+ }
+ if (sym(4).Node) {
+ list = new (pool) AST::FormalParameterList(list, sym(4).PatternElement);
+ }
+ coverExpressionErrorLocation = loc(4);
+ coverExpressionType = CE_FormalParameterList;
+ sym(1).Node = list->finish(pool);
+ } break;
+./
-PrimaryExpression: T_STRING_LITERAL ;
+Literal: T_NULL;
/.
-case $rule_number: {
- AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1));
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::NullExpression *node = new (pool) AST::NullExpression();
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
+
+Literal: T_TRUE;
+/.
+ case $rule_number: {
+ AST::TrueLiteral *node = new (pool) AST::TrueLiteral();
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
+
+Literal: T_FALSE;
+/.
+ case $rule_number: {
+ AST::FalseLiteral *node = new (pool) AST::FalseLiteral();
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
+
+Literal: T_NUMERIC_LITERAL;
+/.
+ case $rule_number: {
+ AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PrimaryExpression: T_DIVIDE_ ;
+Literal: T_MULTILINE_STRING_LITERAL;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+
+Literal: T_STRING_LITERAL;
+/.
+ case $rule_number: {
+ AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1));
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
+
+RegularExpressionLiteral: T_DIVIDE_;
/:
#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
:/
/.
-case $rule_number: {
- bool rx = lexer->scanRegExp(Lexer::NoPrefix);
- if (!rx) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
- return false; // ### remove me
- }
-
- loc(1).length = lexer->tokenLength();
- yylloc = loc(1); // adjust the location of the current token
-
- AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral(
- driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
+{
+ Lexer::RegExpBodyPrefix prefix;
+ case $rule_number:
+ prefix = Lexer::NoPrefix;
+ goto scan_regexp;
./
-PrimaryExpression: T_DIVIDE_EQ ;
+RegularExpressionLiteral: T_DIVIDE_EQ;
/:
#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
:/
/.
-case $rule_number: {
- bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
- if (!rx) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
- return false;
- }
+ case $rule_number:
+ prefix = Lexer::EqualPrefix;
+ goto scan_regexp;
+
+ scan_regexp: {
+ bool rx = lexer->scanRegExp(prefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
- loc(1).length = lexer->tokenLength();
- yylloc = loc(1); // adjust the location of the current token
+ loc(1).length = lexer->tokenLength();
+ yylloc = loc(1); // adjust the location of the current token
- AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral(
- driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
+ AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral(driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+ } break;
+}
./
-PrimaryExpression: T_LBRACKET T_RBRACKET ;
+
+ArrayLiteral: T_LBRACKET ElisionOpt T_RBRACKET;
/.
-case $rule_number: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0);
- node->lbracketToken = loc(1);
- node->rbracketToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElementList *list = nullptr;
+ if (sym(2).Elision)
+ list = (new (pool) AST::PatternElementList(sym(2).Elision, nullptr))->finish();
+ AST::ArrayPattern *node = new (pool) AST::ArrayPattern(list);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-PrimaryExpression: T_LBRACKET Elision T_RBRACKET ;
+ArrayLiteral: T_LBRACKET ElementList T_RBRACKET;
/.
-case $rule_number: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish());
- node->lbracketToken = loc(1);
- node->rbracketToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ArrayPattern *node = new (pool) AST::ArrayPattern(sym(2).PatternElementList->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
+ArrayLiteral: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET;
/.
-case $rule_number: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ());
- node->lbracketToken = loc(1);
- node->rbracketToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ auto *list = sym(2).PatternElementList;
+ if (sym(4).Elision) {
+ AST::PatternElementList *l = new (pool) AST::PatternElementList(sym(4).Elision, nullptr);
+ list = list->append(l);
+ }
+ AST::ArrayPattern *node = new (pool) AST::ArrayPattern(list->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+ Q_ASSERT(node->isValidArrayLiteral());
+ } break;
./
-PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ;
+ElementList: AssignmentExpression_In;
/.
-case $rule_number: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
- (AST::Elision *) 0);
- node->lbracketToken = loc(1);
- node->commaToken = loc(3);
- node->rbracketToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElement *e = new (pool) AST::PatternElement(sym(1).Expression);
+ sym(1).Node = new (pool) AST::PatternElementList(nullptr, e);
+ } break;
./
-PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ;
+ElementList: Elision AssignmentExpression_In;
/.
-case $rule_number: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
- sym(4).Elision->finish());
- node->lbracketToken = loc(1);
- node->commaToken = loc(3);
- node->rbracketToken = loc(5);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElement *e = new (pool) AST::PatternElement(sym(2).Expression);
+ sym(1).Node = new (pool) AST::PatternElementList(sym(1).Elision->finish(), e);
+ } break;
./
--- PrimaryExpression: T_LBRACE T_RBRACE ;
--- /.
--- case $rule_number: {
--- sym(1).Node = new (pool) AST::ObjectLiteral();
--- } break;
--- ./
+ElementList: ElisionOpt SpreadElement;
+/.
+ case $rule_number: {
+ AST::PatternElementList *node = new (pool) AST::PatternElementList(sym(1).Elision, sym(2).PatternElement);
+ sym(1).Node = node;
+ } break;
+./
-PrimaryExpression: T_LBRACE PropertyAssignmentListOpt T_RBRACE ;
+ElementList: ElementList T_COMMA ElisionOpt AssignmentExpression_In;
/.
-case $rule_number: {
- AST::ObjectLiteral *node = 0;
- if (sym(2).Node)
- node = new (pool) AST::ObjectLiteral(
- sym(2).PropertyAssignmentList->finish ());
- else
- node = new (pool) AST::ObjectLiteral();
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElement *e = new (pool) AST::PatternElement(sym(4).Expression);
+ AST::PatternElementList *node = new (pool) AST::PatternElementList(sym(3).Elision, e);
+ sym(1).Node = sym(1).PatternElementList->append(node);
+ } break;
./
-PrimaryExpression: T_LBRACE PropertyAssignmentList T_COMMA T_RBRACE ;
+ElementList: ElementList T_COMMA ElisionOpt SpreadElement;
/.
-case $rule_number: {
- AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral(
- sym(2).PropertyAssignmentList->finish ());
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElementList *node = new (pool) AST::PatternElementList(sym(3).Elision, sym(4).PatternElement);
+ sym(1).Node = sym(1).PatternElementList->append(node);
+ } break;
./
-PrimaryExpression: T_LPAREN Expression T_RPAREN ;
+Elision: T_COMMA;
/.
-case $rule_number: {
- AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression);
- node->lparenToken = loc(1);
- node->rparenToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::Elision *node = new (pool) AST::Elision();
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
+Elision: Elision T_COMMA;
+/.
+ case $rule_number: {
+ AST::Elision *node = new (pool) AST::Elision(sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
-UiQualifiedId: MemberExpression ;
+ElisionOpt: ;
/.
-case $rule_number: {
- if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
- QLatin1String("Ignored annotation")));
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
+./
- sym(1).Expression = mem->base;
- }
+ElisionOpt: Elision;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(1).Elision->finish();
+ } break;
+./
- if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
- sym(1).UiQualifiedId = qualifiedId;
- } else {
- sym(1).UiQualifiedId = 0;
+SpreadElement: T_ELLIPSIS AssignmentExpression;
+/.
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(sym(2).Expression, AST::PatternElement::SpreadElement);
+ sym(1).Node = node;
+ } break;
+./
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
- QLatin1String("Expected a qualified name id")));
+ObjectLiteral: T_LBRACE T_RBRACE;
+/.
+ case $rule_number: {
+ AST::ObjectPattern *node = new (pool) AST::ObjectPattern();
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
- return false; // ### recover
- }
-} break;
+ObjectLiteral: T_LBRACE PropertyDefinitionList T_RBRACE;
+/.
+ case $rule_number: {
+ AST::ObjectPattern *node = new (pool) AST::ObjectPattern(sym(2).PatternPropertyList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-ElementList: AssignmentExpression ;
+ObjectLiteral: T_LBRACE PropertyDefinitionList T_COMMA T_RBRACE;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression);
-} break;
+ case $rule_number: {
+ AST::ObjectPattern *node = new (pool) AST::ObjectPattern(sym(2).PatternPropertyList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-ElementList: Elision AssignmentExpression ;
+
+UiPropertyDefinitionList: UiPropertyDefinition;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+PropertyDefinitionList: PropertyDefinition;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::PatternPropertyList(sym(1).PatternProperty);
+ } break;
./
-ElementList: ElementList T_COMMA AssignmentExpression ;
+UiPropertyDefinitionList: UiPropertyDefinitionList T_COMMA UiPropertyDefinition;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+PropertyDefinitionList: PropertyDefinitionList T_COMMA PropertyDefinition;
/.
-case $rule_number: {
- AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList,
- (AST::Elision *) 0, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternPropertyList *node = new (pool) AST::PatternPropertyList(sym(1).PatternPropertyList, sym(3).PatternProperty);
+ sym(1).Node = node;
+ } break;
./
-ElementList: ElementList T_COMMA Elision AssignmentExpression ;
+PropertyDefinition: IdentifierReference;
/.
-case $rule_number: {
- AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(),
- sym(4).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::IdentifierPropertyName *name = new (pool) AST::IdentifierPropertyName(stringRef(1));
+ name->propertyNameToken = loc(1);
+ AST::IdentifierExpression *expr = new (pool) AST::IdentifierExpression(stringRef(1));
+ expr->identifierToken = loc(1);
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(name, expr);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-Elision: T_COMMA ;
+-- Using this production should result in a syntax error when used in an ObjectLiteral
+PropertyDefinition: CoverInitializedName;
+
+CoverInitializedName: IdentifierReference Initializer_In;
/.
-case $rule_number: {
- AST::Elision *node = new (pool) AST::Elision();
- node->commaToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::IdentifierPropertyName *name = new (pool) AST::IdentifierPropertyName(stringRef(1));
+ name->propertyNameToken = loc(1);
+ AST::IdentifierExpression *left = new (pool) AST::IdentifierExpression(stringRef(1));
+ left->identifierToken = loc(1);
+ // if initializer is an anonymous function expression, we need to assign identifierref as it's name
+ if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
+ f->name = stringRef(1);
+ if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
+ c->name = stringRef(1);
+ AST::BinaryExpression *assignment = new (pool) AST::BinaryExpression(left, QSOperator::Assign, sym(2).Expression);
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(name, assignment);
+ node->colonToken = loc(1);
+ sym(1).Node = node;
+
+ } break;
./
-Elision: Elision T_COMMA ;
+UiPropertyDefinition: UiPropertyName T_COLON AssignmentExpression_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+PropertyDefinition: PropertyName T_COLON AssignmentExpression_In;
/.
-case $rule_number: {
- AST::Elision *node = new (pool) AST::Elision(sym(1).Elision);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, sym(3).Expression);
+ if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression)) {
+ if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName))
+ f->name = driver->newStringRef(sym(1).PropertyName->asString());
+ }
+ if (auto *c = asAnonymousClassDefinition(sym(3).Expression)) {
+ if (!AST::cast<AST::ComputedPropertyName *>(sym(1).PropertyName))
+ c->name = driver->newStringRef(sym(1).PropertyName->asString());
+ }
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+PropertyDefinition: MethodDefinition;
+
+PropertyName: LiteralPropertyName;
+PropertyName: ComputedPropertyName;
+
+LiteralPropertyName: IdentifierName;
+/.
+ case $rule_number: {
+ AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyAssignment: PropertyName T_COLON AssignmentExpression ;
+UiPropertyName: T_STRING_LITERAL;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LiteralPropertyName: T_STRING_LITERAL;
/.
-case $rule_number: {
- AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue(
- sym(1).PropertyName, sym(3).Expression);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyAssignment: T_GET PropertyName T_LPAREN T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+UiPropertyName: T_NUMERIC_LITERAL;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LiteralPropertyName: T_NUMERIC_LITERAL;
/.
-case $rule_number: {
- AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(
- sym(2).PropertyName, sym(6).FunctionBody);
- node->getSetToken = loc(1);
- node->lparenToken = loc(3);
- node->rparenToken = loc(4);
- node->lbraceToken = loc(5);
- node->rbraceToken = loc(7);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyAssignment: T_SET PropertyName T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+IdentifierName: IdentifierReference;
+IdentifierName: ReservedIdentifier;
+
+ReservedIdentifier: T_BREAK;
+ReservedIdentifier: T_CASE;
+ReservedIdentifier: T_CATCH;
+ReservedIdentifier: T_CONTINUE;
+ReservedIdentifier: T_DEFAULT;
+ReservedIdentifier: T_DELETE;
+ReservedIdentifier: T_DO;
+ReservedIdentifier: T_ELSE;
+ReservedIdentifier: T_ENUM;
+ReservedIdentifier: T_FALSE;
+ReservedIdentifier: T_FINALLY;
+ReservedIdentifier: T_FOR;
+ReservedIdentifier: T_FUNCTION;
+ReservedIdentifier: T_IF;
+ReservedIdentifier: T_IN;
+ReservedIdentifier: T_INSTANCEOF;
+ReservedIdentifier: T_NEW;
+ReservedIdentifier: T_NULL;
+ReservedIdentifier: T_RETURN;
+ReservedIdentifier: T_SWITCH;
+ReservedIdentifier: T_THIS;
+ReservedIdentifier: T_THROW;
+ReservedIdentifier: T_TRUE;
+ReservedIdentifier: T_TRY;
+ReservedIdentifier: T_TYPEOF;
+ReservedIdentifier: T_VAR;
+ReservedIdentifier: T_VOID;
+ReservedIdentifier: T_WHILE;
+ReservedIdentifier: T_CONST;
+ReservedIdentifier: T_LET;
+ReservedIdentifier: T_DEBUGGER;
+ReservedIdentifier: T_RESERVED_WORD;
+ReservedIdentifier: T_SUPER;
+ReservedIdentifier: T_WITH;
+ReservedIdentifier: T_CLASS;
+ReservedIdentifier: T_EXTENDS;
+ReservedIdentifier: T_EXPORT;
+
+ComputedPropertyName: T_LBRACKET AssignmentExpression_In T_RBRACKET;
/.
-case $rule_number: {
- AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(
- sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody);
- node->getSetToken = loc(1);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ComputedPropertyName *node = new (pool) AST::ComputedPropertyName(sym(2).Expression);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyAssignmentList: PropertyAssignment ;
+Initializer: T_EQ AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Initializer_In: T_EQ AssignmentExpression_In;
/.
case $rule_number: {
- sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment);
+ sym(1) = sym(2);
} break;
./
-PropertyAssignmentList: PropertyAssignmentList T_COMMA PropertyAssignment ;
+
+InitializerOpt: ;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+InitializerOpt_In: ;
/.
-case $rule_number: {
- AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList(
- sym(1).PropertyAssignmentList, sym(3).PropertyAssignment);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-PropertyName: JsIdentifier %prec SHIFT_THERE ;
+InitializerOpt: Initializer;
+InitializerOpt_In: Initializer_In;
+
+TemplateLiteral: T_NO_SUBSTITUTION_TEMPLATE;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+
+TemplateSpans: T_TEMPLATE_TAIL;
/.
-case $rule_number: {
- AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TemplateLiteral *node = new (pool) AST::TemplateLiteral(stringRef(1), nullptr);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyName: T_STRING_LITERAL ;
+TemplateSpans: T_TEMPLATE_MIDDLE Expression TemplateSpans;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+
+TemplateLiteral: T_TEMPLATE_HEAD Expression TemplateSpans;
/.
-case $rule_number: {
- AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1));
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TemplateLiteral *node = new (pool) AST::TemplateLiteral(stringRef(1), sym(2).Expression);
+ node->next = sym(3).Template;
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyName: T_NUMERIC_LITERAL ;
+
+MemberExpression: PrimaryExpression;
+
+Super: T_SUPER;
/.
-case $rule_number: {
- AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval);
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::SuperLiteral *node = new (pool) AST::SuperLiteral();
+ node->superToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-PropertyName: ReservedIdentifier ;
+
+MemberExpression: Super T_LBRACKET Expression_In T_RBRACKET;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+MemberExpression: MemberExpression T_LBRACKET Expression_In T_RBRACKET;
/.
-case $rule_number: {
- AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-ReservedIdentifier: T_BREAK ;
-ReservedIdentifier: T_CASE ;
-ReservedIdentifier: T_CATCH ;
-ReservedIdentifier: T_CONTINUE ;
-ReservedIdentifier: T_DEFAULT ;
-ReservedIdentifier: T_DELETE ;
-ReservedIdentifier: T_DO ;
-ReservedIdentifier: T_ELSE ;
-ReservedIdentifier: T_ENUM ;
-ReservedIdentifier: T_FALSE ;
-ReservedIdentifier: T_FINALLY ;
-ReservedIdentifier: T_FOR ;
-ReservedIdentifier: T_FUNCTION ;
-ReservedIdentifier: T_IF ;
-ReservedIdentifier: T_IN ;
-ReservedIdentifier: T_INSTANCEOF ;
-ReservedIdentifier: T_NEW ;
-ReservedIdentifier: T_NULL ;
-ReservedIdentifier: T_RETURN ;
-ReservedIdentifier: T_SWITCH ;
-ReservedIdentifier: T_THIS ;
-ReservedIdentifier: T_THROW ;
-ReservedIdentifier: T_TRUE ;
-ReservedIdentifier: T_TRY ;
-ReservedIdentifier: T_TYPEOF ;
-ReservedIdentifier: T_VAR ;
-ReservedIdentifier: T_VOID ;
-ReservedIdentifier: T_WHILE ;
-ReservedIdentifier: T_CONST ;
-ReservedIdentifier: T_LET ;
-ReservedIdentifier: T_DEBUGGER ;
-ReservedIdentifier: T_RESERVED_WORD ;
-ReservedIdentifier: T_WITH ;
-
-PropertyIdentifier: JsIdentifier ;
-PropertyIdentifier: ReservedIdentifier ;
-
-MemberExpression: PrimaryExpression ;
-MemberExpression: FunctionExpression ;
-
-MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
+
+-- the identifier has to be "target", catched at codegen time
+NewTarget: T_NEW T_DOT T_IDENTIFIER;
+/. case $rule_number:
+ {
+ AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1));
+ node->identifierToken= loc(1);
+ sym(1).Node = node;
+ } Q_FALLTHROUGH();
+./
+MemberExpression: Super T_DOT IdentifierName;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+MemberExpression: MemberExpression T_DOT IdentifierName;
/.
-case $rule_number: {
- AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
- node->lbracketToken = loc(2);
- node->rbracketToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
+MemberExpression: MetaProperty;
+
+MemberExpression: T_NEW MemberExpression T_LPAREN Arguments T_RPAREN;
/.
-case $rule_number: {
- AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
- node->dotToken = loc(2);
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+ } break;
./
-MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+MetaProperty: NewTarget;
+
+
+NewExpression: MemberExpression;
+
+NewExpression: T_NEW NewExpression;
/.
-case $rule_number: {
- AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList);
- node->newToken = loc(1);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-NewExpression: MemberExpression ;
-NewExpression: T_NEW NewExpression ;
+CallExpression: CallExpression TemplateLiteral;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+MemberExpression: MemberExpression TemplateLiteral;
/.
-case $rule_number: {
- AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression);
- node->newToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TaggedTemplate *node = new (pool) AST::TaggedTemplate(sym(1).Expression, sym(2).Template);
+ sym(1).Node = node;
+ } break;
./
-CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+CallExpression: MemberExpression T_LPAREN Arguments T_RPAREN;
/.
-case $rule_number: {
- AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+CallExpression: Super T_LPAREN Arguments T_RPAREN;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+CallExpression: CallExpression T_LPAREN Arguments T_RPAREN;
/.
-case $rule_number: {
- AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
+CallExpression: CallExpression T_LBRACKET Expression_In T_RBRACKET;
/.
-case $rule_number: {
- AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
- node->lbracketToken = loc(2);
- node->rbracketToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-CallExpression: CallExpression T_DOT PropertyIdentifier ;
+CallExpression: CallExpression T_DOT IdentifierName;
/.
-case $rule_number: {
- AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
- node->dotToken = loc(2);
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-ArgumentListOpt: ;
+Arguments: ;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-ArgumentListOpt: ArgumentList ;
+Arguments: ArgumentList;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Arguments: ArgumentList T_COMMA;
/.
-case $rule_number: {
- sym(1).Node = sym(1).ArgumentList->finish();
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+ } break;
./
-ArgumentList: AssignmentExpression ;
+ArgumentList: AssignmentExpression_In;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression);
+ } break;
./
-ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
+ArgumentList: T_ELLIPSIS AssignmentExpression_In;
/.
-case $rule_number: {
- AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(2).Expression);
+ node->isSpreadElement = true;
+ sym(1).Node = node;
+ } break;
./
-LeftHandSideExpression: NewExpression ;
-LeftHandSideExpression: CallExpression ;
-PostfixExpression: LeftHandSideExpression ;
+ArgumentList: ArgumentList T_COMMA AssignmentExpression_In;
+/.
+ case $rule_number: {
+ AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
-PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
+ArgumentList: ArgumentList T_COMMA T_ELLIPSIS AssignmentExpression_In;
/.
-case $rule_number: {
- AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression);
- node->incrementToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(4).Expression);
+ node->commaToken = loc(2);
+ node->isSpreadElement = true;
+ sym(1).Node = node;
+ } break;
./
-PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
+LeftHandSideExpression: NewExpression;
+LeftHandSideExpression: CallExpression;
+
+UpdateExpression: LeftHandSideExpression;
+
+UpdateExpression: LeftHandSideExpression T_PLUS_PLUS;
/.
-case $rule_number: {
- AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression);
- node->decrementToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: PostfixExpression ;
+UpdateExpression: LeftHandSideExpression T_MINUS_MINUS;
+/.
+ case $rule_number: {
+ AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
-UnaryExpression: T_DELETE UnaryExpression ;
+UpdateExpression: T_PLUS_PLUS UnaryExpression;
/.
-case $rule_number: {
- AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression);
- node->deleteToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_VOID UnaryExpression ;
+UpdateExpression: T_MINUS_MINUS UnaryExpression;
/.
-case $rule_number: {
- AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression);
- node->voidToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_TYPEOF UnaryExpression ;
+UnaryExpression: UpdateExpression;
+
+UnaryExpression: T_DELETE UnaryExpression;
/.
-case $rule_number: {
- AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression);
- node->typeofToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_PLUS_PLUS UnaryExpression ;
+UnaryExpression: T_VOID UnaryExpression;
/.
-case $rule_number: {
- AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression);
- node->incrementToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_MINUS_MINUS UnaryExpression ;
+UnaryExpression: T_TYPEOF UnaryExpression;
/.
-case $rule_number: {
- AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression);
- node->decrementToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_PLUS UnaryExpression ;
+UnaryExpression: T_PLUS UnaryExpression;
/.
-case $rule_number: {
- AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression);
- node->plusToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_MINUS UnaryExpression ;
+UnaryExpression: T_MINUS UnaryExpression;
/.
-case $rule_number: {
- AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression);
- node->minusToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_TILDE UnaryExpression ;
+UnaryExpression: T_TILDE UnaryExpression;
/.
-case $rule_number: {
- AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression);
- node->tildeToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-UnaryExpression: T_NOT UnaryExpression ;
+UnaryExpression: T_NOT UnaryExpression;
/.
-case $rule_number: {
- AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression);
- node->notToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-MultiplicativeExpression: UnaryExpression ;
+ExponentiationExpression: UnaryExpression;
-MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
+ExponentiationExpression: UpdateExpression T_STAR_STAR ExponentiationExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Mul, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Exp, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
+MultiplicativeExpression: ExponentiationExpression;
+
+MultiplicativeExpression: MultiplicativeExpression MultiplicativeOperator ExponentiationExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Div, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
+MultiplicativeOperator: T_STAR;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Mod, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::Mul;
+ } break;
./
-AdditiveExpression: MultiplicativeExpression ;
+MultiplicativeOperator: T_DIVIDE_;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::Div;
+ } break;
+./
-AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
+MultiplicativeOperator: T_REMAINDER;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Add, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::Mod;
+ } break;
./
-AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
+AdditiveExpression: MultiplicativeExpression;
+
+AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Sub, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression;
+/.
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-ShiftExpression: AdditiveExpression ;
+ShiftExpression: AdditiveExpression;
-ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
+ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::LShift, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
+ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::RShift, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
+ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::URShift, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpression: ShiftExpression ;
+RelationalExpression_In: ShiftExpression;
+RelationalExpression: ShiftExpression;
-RelationalExpression: RelationalExpression T_LT ShiftExpression ;
+RelationalExpression_In: RelationalExpression_In RelationalOperator ShiftExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+RelationalExpression: RelationalExpression RelationalOperator ShiftExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Lt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpression: RelationalExpression T_GT ShiftExpression ;
+RelationalOperator: T_LT;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Gt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::Lt;
+ } break;
+./
+RelationalOperator: T_GT;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::Gt;
+ } break;
+./
+RelationalOperator: T_LE;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::Le;
+ } break;
+./
+RelationalOperator: T_GE;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::Ge;
+ } break;
+./
+RelationalOperator: T_INSTANCEOF;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::InstanceOf;
+ } break;
./
-RelationalExpression: RelationalExpression T_LE ShiftExpression ;
+RelationalExpression_In: RelationalExpression_In T_IN ShiftExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Le, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpression: RelationalExpression T_GE ShiftExpression ;
+EqualityExpression_In: RelationalExpression_In;
+EqualityExpression: RelationalExpression;
+
+EqualityExpression_In: EqualityExpression_In EqualityOperator RelationalExpression_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+EqualityExpression: EqualityExpression EqualityOperator RelationalExpression;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Ge, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
+EqualityOperator: T_EQ_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::InstanceOf, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::Equal;
+ } break;
+./
+EqualityOperator: T_NOT_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::NotEqual;
+ } break;
./
+EqualityOperator: T_EQ_EQ_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::StrictEqual;
+ } break;
+./
+EqualityOperator: T_NOT_EQ_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::StrictNotEqual;
+ } break;
+./
+
+
+BitwiseANDExpression: EqualityExpression;
+XitwiseANDExpression_In: EqualityExpression_In;
-RelationalExpression: RelationalExpression T_IN ShiftExpression ;
+BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+XitwiseANDExpression_In: XitwiseANDExpression_In T_AND EqualityExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::In, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpressionNotIn: ShiftExpression ;
-RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
+BitwiseXORExpression: BitwiseANDExpression;
+BitwiseXORExpression_In: XitwiseANDExpression_In;
+
+BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+BitwiseXORExpression_In: BitwiseXORExpression_In T_XOR XitwiseANDExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Lt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
+BitwiseORExpression: BitwiseXORExpression;
+BitwiseORExpression_In: BitwiseXORExpression_In;
+
+BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+BitwiseORExpression_In: BitwiseORExpression_In T_OR BitwiseXORExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Gt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
+LogicalANDExpression: BitwiseORExpression;
+LogicalANDExpression_In: BitwiseORExpression_In;
+
+LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LogicalANDExpression_In: LogicalANDExpression_In T_AND_AND BitwiseORExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Le, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
+LogicalORExpression: LogicalANDExpression;
+LogicalORExpression_In: LogicalANDExpression_In;
+
+LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LogicalORExpression_In: LogicalORExpression_In T_OR_OR LogicalANDExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Ge, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
+
+ConditionalExpression: LogicalORExpression;
+ConditionalExpression_In: LogicalORExpression_In;
+
+ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+ConditionalExpression_In: LogicalORExpression_In T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::InstanceOf, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-EqualityExpression: RelationalExpression ;
+AssignmentExpression: ConditionalExpression;
+AssignmentExpression_In: ConditionalExpression_In;
+
+AssignmentExpression: YieldExpression;
+AssignmentExpression_In: YieldExpression_In;
-EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
+AssignmentExpression: ArrowFunction;
+AssignmentExpression_In: ArrowFunction_In;
+
+AssignmentExpression: LeftHandSideExpression T_EQ AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+AssignmentExpression_In: LeftHandSideExpression T_EQ AssignmentExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Equal, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ // need to convert the LHS to an AssignmentPattern if it was an Array/ObjectLiteral
+ if (AST::Pattern *p = sym(1).Expression->patternCast()) {
+ AST::SourceLocation errorLoc;
+ QString errorMsg;
+ if (!p->convertLiteralToAssignmentPattern(pool, &errorLoc, &errorMsg)) {
+ syntaxError(errorLoc, errorMsg);
+ return false;
+ }
+ }
+ // if lhs is an identifier expression and rhs is an anonymous function expression, we need to assign the name of lhs to the function
+ if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression)) {
+ if (auto *id = AST::cast<AST::IdentifierExpression *>(sym(1).Expression))
+ f->name = id->name;
+ }
+ if (auto *c = asAnonymousClassDefinition(sym(3).Expression)) {
+ if (auto *id = AST::cast<AST::IdentifierExpression *>(sym(1).Expression))
+ c->name = id->name;
+ }
+
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Assign, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
+AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+AssignmentExpression_In: LeftHandSideExpression AssignmentOperator AssignmentExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::NotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
+AssignmentOperator: T_STAR_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMul;
+ } break;
./
-EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
+AssignmentOperator: T_STAR_STAR_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictNotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceExp;
+ } break;
./
-EqualityExpressionNotIn: RelationalExpressionNotIn ;
+AssignmentOperator: T_DIVIDE_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceDiv;
+ } break;
+./
-EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
+AssignmentOperator: T_REMAINDER_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Equal, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMod;
+ } break;
./
-EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
+AssignmentOperator: T_PLUS_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::NotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAdd;
+ } break;
./
-EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
+AssignmentOperator: T_MINUS_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceSub;
+ } break;
./
-EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
+AssignmentOperator: T_LT_LT_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictNotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+ } break;
./
-BitwiseANDExpression: EqualityExpression ;
+AssignmentOperator: T_GT_GT_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+ } break;
+./
-BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
+AssignmentOperator: T_GT_GT_GT_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitAnd, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+ } break;
./
-BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
+AssignmentOperator: T_AND_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAnd;
+ } break;
+./
-BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
+AssignmentOperator: T_XOR_EQ;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitAnd, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceXor;
+ } break;
+./
+
+AssignmentOperator: T_OR_EQ;
+/.
+ case $rule_number: {
+ sym(1).ival = QSOperator::InplaceOr;
+ } break;
./
-BitwiseXORExpression: BitwiseANDExpression ;
+Expression: AssignmentExpression;
+Expression_In: AssignmentExpression_In;
-BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
+Expression: Expression T_COMMA AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Expression_In: Expression_In T_COMMA AssignmentExpression_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitXor, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
+ExpressionOpt: ;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+ExpressionOpt_In: ;
+/.
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
+./
+
+ExpressionOpt: Expression;
+ExpressionOpt_In: Expression_In;
-BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
+-- Statements
+
+Statement: ExpressionStatementLookahead T_FORCE_BLOCK BlockStatement;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitXor, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(3).Node;
+ } break;
./
-BitwiseORExpression: BitwiseXORExpression ;
+Statement: ExpressionStatementLookahead VariableStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead EmptyStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead ExpressionStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead IfStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead BreakableStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead ContinueStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead BreakStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead ReturnStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead WithStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead LabelledStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead ThrowStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead TryStatement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+Statement: ExpressionStatementLookahead DebuggerStatement;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ } break;
+./
+
+Declaration: HoistableDeclaration;
+Declaration: ClassDeclaration;
+Declaration: LexicalDeclaration_In;
+
+HoistableDeclaration: FunctionDeclaration;
+HoistableDeclaration: GeneratorDeclaration;
+
+HoistableDeclaration_Default: FunctionDeclaration_Default;
+HoistableDeclaration_Default: GeneratorDeclaration_Default;
+
+BreakableStatement: IterationStatement;
+BreakableStatement: SwitchStatement;
-BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
+BlockStatement: Block;
+
+Block: T_LBRACE StatementListOpt T_RBRACE;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitOr, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::Block *node = new (pool) AST::Block(sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
+StatementList: StatementListItem;
-BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
+StatementList: StatementList StatementListItem;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitOr, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).StatementList = sym(1).StatementList->append(sym(2).StatementList);
+ } break;
./
-LogicalANDExpression: BitwiseORExpression ;
+StatementListItem: Statement;
+/.
+ case $rule_number: {
+ sym(1).StatementList = new (pool) AST::StatementList(sym(1).Statement);
+ } break;
+./
-LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
+StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration T_AUTOMATIC_SEMICOLON;
+StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration T_SEMICOLON;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::And, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::StatementList(sym(3).FunctionDeclaration);
+ } break;
./
-LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
+StatementListOpt: ExpressionStatementLookahead;
+/.
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
+./
-LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
+StatementListOpt: StatementList;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::And, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(1).StatementList->finish();
+ } break;
./
-LogicalORExpression: LogicalANDExpression ;
+LetOrConst: T_LET;
+/.
+ case $rule_number: {
+ sym(1).scope = AST::VariableScope::Let;
+ } break;
+./
+LetOrConst: T_CONST;
+/.
+ case $rule_number: {
+ sym(1).scope = AST::VariableScope::Const;
+ } break;
+./
-LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
+Var: T_VAR;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Or, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).scope = AST::VariableScope::Var;
+ } break;
./
-LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
+LexicalDeclaration: LetOrConst BindingList;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LexicalDeclaration_In: LetOrConst BindingList_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VarDeclaration: Var VariableDeclarationList;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VarDeclaration_In: Var VariableDeclarationList_In;
+/.
+ case $rule_number: {
+ AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(sym(1).scope));
+ node->declarationKindToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
+
+VariableStatement: VarDeclaration_In T_AUTOMATIC_SEMICOLON;
+VariableStatement: VarDeclaration_In T_SEMICOLON;
-LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
+BindingList: LexicalBinding_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+BindingList_In: LexicalBinding_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclarationList: VariableDeclaration;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclarationList_In: VariableDeclaration_In;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Or, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).PatternElement);
+ } break;
./
-ConditionalExpression: LogicalORExpression ;
+BindingList: BindingList T_COMMA LexicalBinding;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+BindingList_In: BindingList_In T_COMMA LexicalBinding_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclarationList_In: VariableDeclarationList_In T_COMMA VariableDeclaration_In;
+/.
+ case $rule_number: {
+ AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).PatternElement);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
-ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
+LexicalBinding: BindingIdentifier InitializerOpt;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LexicalBinding_In: BindingIdentifier InitializerOpt_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclaration: BindingIdentifier InitializerOpt;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclaration_In: BindingIdentifier InitializerOpt_In;
/.
-case $rule_number: {
- AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression,
- sym(3).Expression, sym(5).Expression);
- node->questionToken = loc(2);
- node->colonToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ auto *node = new (pool) AST::PatternElement(stringRef(1), sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ // if initializer is an anonymous function expression, we need to assign identifierref as it's name
+ if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
+ f->name = stringRef(1);
+ if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
+ c->name = stringRef(1);
+ } break;
./
-ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
+LexicalBinding: BindingPattern Initializer;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+LexicalBinding_In: BindingPattern Initializer_In;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclaration: BindingPattern Initializer;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+VariableDeclaration_In: BindingPattern Initializer_In;
+/.
+ case $rule_number: {
+ auto *node = new (pool) AST::PatternElement(sym(1).Pattern, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
-ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
+BindingPattern: T_LBRACE ObjectBindingPattern T_RBRACE;
/.
-case $rule_number: {
- AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression,
- sym(3).Expression, sym(5).Expression);
- node->questionToken = loc(2);
- node->colonToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ auto *node = new (pool) AST::ObjectPattern(sym(2).PatternPropertyList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ node->parseMode = AST::Pattern::Binding;
+ sym(1).Node = node;
+ } break;
./
-AssignmentExpression: ConditionalExpression ;
+BindingPattern: T_LBRACKET ArrayBindingPattern T_RBRACKET;
+/.
+ case $rule_number: {
+ auto *node = new (pool) AST::ArrayPattern(sym(2).PatternElementList);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ node->parseMode = AST::Pattern::Binding;
+ sym(1).Node = node;
+ } break;
+./
+
+ObjectBindingPattern: ;
+/.
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
+./
+
+ObjectBindingPattern: BindingPropertyList;
+/. case $rule_number: ./
+ObjectBindingPattern: BindingPropertyList T_COMMA;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(1).PatternPropertyList->finish();
+ } break;
+./
+
+ArrayBindingPattern: ElisionOpt BindingRestElementOpt;
+/.
+ case $rule_number: {
+ if (sym(1).Elision || sym(2).Node) {
+ auto *l = new (pool) AST::PatternElementList(sym(1).Elision, sym(2).PatternElement);
+ sym(1).Node = l->finish();
+ } else {
+ sym(1).Node = nullptr;
+ }
+ } break;
+./
-AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
+ArrayBindingPattern: BindingElementList;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- sym(2).ival, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(1).PatternElementList->finish();
+ } break;
./
-AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
+ArrayBindingPattern: BindingElementList T_COMMA ElisionOpt BindingRestElementOpt;
+/.
+ case $rule_number: {
+ if (sym(3).Elision || sym(4).Node) {
+ auto *l = new (pool) AST::PatternElementList(sym(3).Elision, sym(4).PatternElement);
+ l = sym(1).PatternElementList->append(l);
+ sym(1).Node = l;
+ }
+ sym(1).Node = sym(1).PatternElementList->finish();
+ } break;
+./
-AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
+BindingPropertyList: BindingProperty;
/.
-case $rule_number: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- sym(2).ival, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::PatternPropertyList(sym(1).PatternProperty);
+ } break;
./
-AssignmentOperator: T_EQ ;
+BindingPropertyList: BindingPropertyList T_COMMA BindingProperty;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::Assign;
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::PatternPropertyList(sym(1).PatternPropertyList, sym(3).PatternProperty);
+ } break;
./
-AssignmentOperator: T_STAR_EQ ;
+BindingElementList: BindingElisionElement;
+
+BindingElementList: BindingElementList T_COMMA BindingElisionElement;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceMul;
-} break;
+ case $rule_number: {
+ sym(1).PatternElementList = sym(1).PatternElementList->append(sym(3).PatternElementList);
+ } break;
./
-AssignmentOperator: T_DIVIDE_EQ ;
+BindingElisionElement: ElisionOpt BindingElement;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceDiv;
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::PatternElementList(sym(1).Elision, sym(2).PatternElement);
+ } break;
./
-AssignmentOperator: T_REMAINDER_EQ ;
+
+BindingProperty: BindingIdentifier InitializerOpt_In;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceMod;
-} break;
+ case $rule_number: {
+ AST::StringLiteralPropertyName *name = new (pool) AST::StringLiteralPropertyName(stringRef(1));
+ name->propertyNameToken = loc(1);
+ // if initializer is an anonymous function expression, we need to assign identifierref as it's name
+ if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
+ f->name = stringRef(1);
+ if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
+ c->name = stringRef(1);
+ sym(1).Node = new (pool) AST::PatternProperty(name, stringRef(1), sym(2).Expression);
+ } break;
./
-AssignmentOperator: T_PLUS_EQ ;
+BindingProperty: PropertyName T_COLON BindingIdentifier InitializerOpt_In;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceAdd;
-} break;
+ case $rule_number: {
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, stringRef(3), sym(4).Expression);
+ sym(1).Node = node;
+ } break;
./
-AssignmentOperator: T_MINUS_EQ ;
+BindingProperty: PropertyName T_COLON BindingPattern InitializerOpt_In;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceSub;
-} break;
+ case $rule_number: {
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, sym(3).Pattern, sym(4).Expression);
+ sym(1).Node = node;
+ } break;
./
-AssignmentOperator: T_LT_LT_EQ ;
+BindingElement: BindingIdentifier InitializerOpt_In;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceLeftShift;
-} break;
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1), sym(2).Expression);
+ node->identifierToken = loc(1);
+ // if initializer is an anonymous function expression, we need to assign identifierref as it's name
+ if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
+ f->name = stringRef(1);
+ if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
+ c->name = stringRef(1);
+ sym(1).Node = node;
+ } break;
./
-AssignmentOperator: T_GT_GT_EQ ;
+BindingElement: BindingPattern InitializerOpt_In;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceRightShift;
-} break;
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(sym(1).Pattern, sym(2).Expression);
+ sym(1).Node = node;
+ } break;
./
-AssignmentOperator: T_GT_GT_GT_EQ ;
+BindingRestElement: T_ELLIPSIS BindingIdentifier;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceURightShift;
-} break;
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(2), nullptr, AST::PatternElement::RestElement);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-AssignmentOperator: T_AND_EQ ;
+BindingRestElement: T_ELLIPSIS BindingPattern;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceAnd;
-} break;
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(sym(2).Pattern, nullptr, AST::PatternElement::RestElement);
+ sym(1).Node = node;
+ } break;
./
-AssignmentOperator: T_XOR_EQ ;
+BindingRestElementOpt: ;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceXor;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-AssignmentOperator: T_OR_EQ ;
+BindingRestElementOpt: BindingRestElement;
+
+
+EmptyStatement: T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).ival = QSOperator::InplaceOr;
-} break;
+ case $rule_number: {
+ AST::EmptyStatement *node = new (pool) AST::EmptyStatement();
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-Expression: AssignmentExpression ;
+-- Spec says it should have a "[lookahead ∉ { {, function, class, let [ }]" before the Expression statement.
+-- This is implemented with the rule below that is run before any statement and inserts a T_EXPRESSION_STATEMENT_OK
+-- token if it's ok to parse as an expression statement.
+ExpressionStatementLookahead: ;
+/:
+#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE $rule_number
+:/
+/.
+ case $rule_number: {
+ int token = lookaheadToken(lexer);
+ if (token == T_LBRACE)
+ pushToken(T_FORCE_BLOCK);
+ else if (token == T_FUNCTION || token == T_CLASS || token == T_LET || token == T_CONST)
+ pushToken(T_FORCE_DECLARATION);
+ } break;
+./
-Expression: Expression T_COMMA AssignmentExpression ;
+ExpressionStatement: Expression_In T_AUTOMATIC_SEMICOLON;
+ExpressionStatement: Expression_In T_SEMICOLON;
/.
-case $rule_number: {
- AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-ExpressionOpt: ;
+IfStatement: T_IF T_LPAREN Expression_In T_RPAREN Statement T_ELSE Statement;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(6);
+ sym(1).Node = node;
+ } break;
./
-ExpressionOpt: Expression ;
+IfStatement: T_IF T_LPAREN Expression_In T_RPAREN Statement;
+/.
+ case $rule_number: {
+ AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
+./
-ExpressionNotIn: AssignmentExpressionNotIn ;
-ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_AUTOMATIC_SEMICOLON;
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_COMPATIBILITY_SEMICOLON; -- for JSC/V8 compatibility
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_SEMICOLON;
/.
-case $rule_number: {
- AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+ } break;
./
-ExpressionNotInOpt: ;
+IterationStatement: T_WHILE T_LPAREN Expression_In T_RPAREN Statement;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-ExpressionNotInOpt: ExpressionNotIn ;
+IterationStatement: T_FOR T_LPAREN ExpressionOpt T_SEMICOLON ExpressionOpt_In T_SEMICOLON ExpressionOpt_In T_RPAREN Statement; -- [lookahead != { let [ }]
+/.
+ case $rule_number: {
+ AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+ } break;
+./
-Statement: Block ;
-Statement: VariableStatement ;
-Statement: EmptyStatement ;
-Statement: ExpressionStatement ;
-Statement: IfStatement ;
-Statement: IterationStatement ;
-Statement: ContinueStatement ;
-Statement: BreakStatement ;
-Statement: ReturnStatement ;
-Statement: WithStatement ;
-Statement: LabelledStatement ;
-Statement: SwitchStatement ;
-Statement: ThrowStatement ;
-Statement: TryStatement ;
-Statement: DebuggerStatement ;
+IterationStatement: T_FOR T_LPAREN VarDeclaration T_SEMICOLON ExpressionOpt_In T_SEMICOLON ExpressionOpt_In T_RPAREN Statement;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+IterationStatement: T_FOR T_LPAREN LexicalDeclaration T_SEMICOLON ExpressionOpt_In T_SEMICOLON ExpressionOpt_In T_RPAREN Statement;
+/.
+ case $rule_number: {
+ // ### get rid of the static_cast!
+ AST::ForStatement *node = new (pool) AST::ForStatement(
+ static_cast<AST::VariableStatement *>(sym(3).Node)->declarations, sym(5).Expression,
+ sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+ } break;
+./
+InOrOf: T_IN;
+/.
+ case $rule_number: {
+ sym(1).forEachType = AST::ForEachType::In;
+ } break;
+./
-Block: T_LBRACE StatementListOpt T_RBRACE ;
+InOrOf: T_OF;
/.
-case $rule_number: {
- AST::Block *node = new (pool) AST::Block(sym(2).StatementList);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).forEachType = AST::ForEachType::Of;
+ } break;
./
-StatementList: Statement ;
+IterationStatement: T_FOR T_LPAREN LeftHandSideExpression InOrOf Expression_In T_RPAREN Statement;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::StatementList(sym(1).Statement);
-} break;
+ case $rule_number: {
+ // need to convert the LHS to an AssignmentPattern if it was an Array/ObjectLiteral
+ if (AST::Pattern *p = sym(3).Expression->patternCast()) {
+ AST::SourceLocation errorLoc;
+ QString errorMsg;
+ if (!p->convertLiteralToAssignmentPattern(pool, &errorLoc, &errorMsg)) {
+ syntaxError(errorLoc, errorMsg);
+ return false;
+ }
+ }
+ AST::ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inOfToken = loc(4);
+ node->rparenToken = loc(6);
+ node->type = sym(4).forEachType;
+ sym(1).Node = node;
+ } break;
./
-StatementList: StatementList Statement ;
+IterationStatement: T_FOR T_LPAREN ForDeclaration InOrOf Expression_In T_RPAREN Statement;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement);
-} break;
+ case $rule_number: {
+ AST::ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).PatternElement, sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inOfToken = loc(4);
+ node->rparenToken = loc(6);
+ node->type = sym(4).forEachType;
+ sym(1).Node = node;
+ } break;
./
-StatementListOpt: ;
+ForDeclaration: LetOrConst BindingIdentifier;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+ForDeclaration: Var BindingIdentifier;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ auto *node = new (pool) AST::PatternElement(stringRef(2), nullptr);
+ node->identifierToken = loc(2);
+ node->scope = sym(1).scope;
+ sym(1).Node = node;
+ } break;
./
-StatementListOpt: StatementList ;
+ForDeclaration: LetOrConst BindingPattern;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+ForDeclaration: Var BindingPattern;
/.
-case $rule_number: {
- sym(1).Node = sym(1).StatementList->finish ();
-} break;
+ case $rule_number: {
+ auto *node = new (pool) AST::PatternElement(sym(2).Pattern, nullptr);
+ node->scope = sym(1).scope;
+ sym(1).Node = node;
+ } break;
./
-VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
+ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON;
+ContinueStatement: T_CONTINUE T_SEMICOLON;
/.
-case $rule_number: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- if (sym(1).ival == T_LET)
- s = AST::VariableDeclaration::BlockScope;
- else if (sym(1).ival == T_CONST)
- s = AST::VariableDeclaration::ReadOnlyBlockScope;
-
- AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s));
- node->declarationKindToken = loc(1);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ContinueStatement *node = new (pool) AST::ContinueStatement();
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationKind: T_LET ;
+ContinueStatement: T_CONTINUE IdentifierReference T_AUTOMATIC_SEMICOLON;
+ContinueStatement: T_CONTINUE IdentifierReference T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).ival = T_LET;
-} break;
+ case $rule_number: {
+ AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2));
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationKind: T_CONST ;
+BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON;
+BreakStatement: T_BREAK T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).ival = T_CONST;
-} break;
+ case $rule_number: {
+ AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationKind: T_VAR ;
+BreakStatement: T_BREAK IdentifierReference T_AUTOMATIC_SEMICOLON;
+BreakStatement: T_BREAK IdentifierReference T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).ival = T_VAR;
-} break;
+ case $rule_number: {
+ AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2));
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationList: VariableDeclaration ;
+ReturnStatement: T_RETURN ExpressionOpt_In T_AUTOMATIC_SEMICOLON;
+ReturnStatement: T_RETURN ExpressionOpt_In T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
-} break;
+ case $rule_number: {
+ if (!functionNestingLevel) {
+ syntaxError(loc(1), "Return statement not allowed outside of Function declaration.");
+ return false;
+ }
+ AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
+WithStatement: T_WITH T_LPAREN Expression_In T_RPAREN Statement;
/.
-case $rule_number: {
- AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList(
- sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationListNotIn: VariableDeclarationNotIn ;
+SwitchStatement: T_SWITCH T_LPAREN Expression_In T_RPAREN CaseBlock;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
-} break;
+ case $rule_number: {
+ AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
+CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
-} break;
+ case $rule_number: {
+ AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclaration: JsIdentifier InitialiserOpt ;
+CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE;
/.
-case $rule_number: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+ } break;
./
-VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ;
+CaseClauses: CaseClause;
/.
-case $rule_number: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause);
+ } break;
./
-Initialiser: T_EQ AssignmentExpression ;
+CaseClauses: CaseClauses CaseClause;
/.
-case $rule_number: {
- // ### TODO: AST for initializer
- sym(1) = sym(2);
-} break;
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause);
+ } break;
./
-InitialiserOpt: ;
+CaseClausesOpt: ;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-InitialiserOpt: Initialiser ;
+CaseClausesOpt: CaseClauses;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(1).CaseClauses->finish();
+ } break;
+./
-InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
+CaseClause: T_CASE Expression_In T_COLON StatementListOpt;
/.
-case $rule_number: {
- // ### TODO: AST for initializer
- sym(1) = sym(2);
-} break;
+ case $rule_number: {
+ AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-InitialiserNotInOpt: ;
+DefaultClause: T_DEFAULT T_COLON StatementListOpt;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-InitialiserNotInOpt: InitialiserNotIn ;
+LabelledStatement: IdentifierReference T_COLON LabelledItem;
+/.
+ case $rule_number: {
+ AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+LabelledItem: Statement;
-EmptyStatement: T_SEMICOLON ;
+LabelledItem: ExpressionStatementLookahead T_FORCE_DECLARATION FunctionDeclaration;
/.
-case $rule_number: {
- AST::EmptyStatement *node = new (pool) AST::EmptyStatement();
- node->semicolonToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ syntaxError(loc(3), "FunctionDeclarations are not allowed after a label.");
+ return false;
+ } break;
./
-ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-ExpressionStatement: Expression T_SEMICOLON ;
+ThrowStatement: T_THROW Expression_In T_AUTOMATIC_SEMICOLON;
+ThrowStatement: T_THROW Expression_In T_SEMICOLON;
/.
-case $rule_number: {
- AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+ } break;
./
-IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
+TryStatement: T_TRY Block Catch;
/.
-case $rule_number: {
- AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement);
- node->ifToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- node->elseToken = loc(6);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
+TryStatement: T_TRY Block Finally;
/.
-case $rule_number: {
- AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement);
- node->ifToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
+TryStatement: T_TRY Block Catch Finally;
+/.
+ case $rule_number: {
+ AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
-IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_COMPATIBILITY_SEMICOLON ; -- for JSC/V8 compatibility
-IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
+Catch: T_CATCH T_LPAREN CatchParameter T_RPAREN Block;
/.
-case $rule_number: {
- AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression);
- node->doToken = loc(1);
- node->whileToken = loc(3);
- node->lparenToken = loc(4);
- node->rparenToken = loc(6);
- node->semicolonToken = loc(7);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::Catch *node = new (pool) AST::Catch(sym(3).PatternElement, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+ } break;
./
-IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
+Finally: T_FINALLY Block;
/.
-case $rule_number: {
- AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement);
- node->whileToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::Finally *node = new (pool) AST::Finally(sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+CatchParameter: BindingIdentifier;
/.
-case $rule_number: {
- AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression,
- sym(5).Expression, sym(7).Expression, sym(9).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->firstSemicolonToken = loc(4);
- node->secondSemicolonToken = loc(6);
- node->rparenToken = loc(8);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1));
+ node->identifierToken = loc(1);
+ node->scope = AST::VariableScope::Let;
+ sym(1).Node = node;
+ } break;
./
-IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+CatchParameter: BindingPattern;
/.
-case $rule_number: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- AST::LocalForStatement *node = new (pool) AST::LocalForStatement(
- sym(4).VariableDeclarationList->finish(s), sym(6).Expression,
- sym(8).Expression, sym(10).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->varToken = loc(3);
- node->firstSemicolonToken = loc(5);
- node->secondSemicolonToken = loc(7);
- node->rparenToken = loc(9);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElement *node = new (pool) AST::PatternElement(sym(1).Pattern);
+ node->scope = AST::VariableScope::Let;
+ sym(1).Node = node;
+ } break;
./
-IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
+DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON; -- automatic semicolon
+DebuggerStatement: T_DEBUGGER T_SEMICOLON;
/.
-case $rule_number: {
- AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression,
- sym(5).Expression, sym(7).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->inToken = loc(4);
- node->rparenToken = loc(6);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement();
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
+-- tell the parser to prefer function declarations to function expressions.
+-- That is, the `Function' symbol is used to mark the start of a function
+-- declaration.
+-- This is still required for parsing QML, where MemberExpression and FunctionDeclaration would
+-- otherwise conflict.
+Function: T_FUNCTION %prec REDUCE_HERE;
+
+FunctionDeclaration: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
/.
-case $rule_number: {
- AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement(
- sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->varToken = loc(3);
- node->inToken = loc(5);
- node->rparenToken = loc(7);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+ } break;
./
-ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-ContinueStatement: T_CONTINUE T_SEMICOLON ;
+
+FunctionDeclaration_Default: FunctionDeclaration;
+FunctionDeclaration_Default: Function T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
/.
-case $rule_number: {
- AST::ContinueStatement *node = new (pool) AST::ContinueStatement();
- node->continueToken = loc(1);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->lbraceToken = loc(5);
+ node->rbraceToken = loc(7);
+ sym(1).Node = node;
+ } break;
./
-ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ;
+FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
/.
-case $rule_number: {
- AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2));
- node->continueToken = loc(1);
- node->identifierToken = loc(2);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ node->functionToken = loc(1);
+ if (! stringRef(2).isNull())
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+ } break;
./
-BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-BreakStatement: T_BREAK T_SEMICOLON ;
+FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
/.
-case $rule_number: {
- AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef());
- node->breakToken = loc(1);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
+ node->functionToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->lbraceToken = loc(5);
+ node->rbraceToken = loc(7);
+ sym(1).Node = node;
+ } break;
./
-BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ;
+StrictFormalParameters: FormalParameters;
+
+FormalParameters: ;
/.
-case $rule_number: {
- AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2));
- node->breakToken = loc(1);
- node->identifierToken = loc(2);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
+FormalParameters: BindingRestElement;
/.
-case $rule_number: {
- AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression);
- node->returnToken = loc(1);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FormalParameterList *node = (new (pool) AST::FormalParameterList(nullptr, sym(1).PatternElement))->finish(pool);
+ sym(1).Node = node;
+ } break;
./
-WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
+FormalParameters: FormalParameterList;
+/. case $rule_number: ./
+FormalParameters: FormalParameterList T_COMMA;
/.
-case $rule_number: {
- AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement);
- node->withToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ sym(1).Node = sym(1).FormalParameterList->finish(pool);
+ } break;
./
-SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
+FormalParameters: FormalParameterList T_COMMA BindingRestElement;
/.
-case $rule_number: {
- AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock);
- node->switchToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FormalParameterList *node = (new (pool) AST::FormalParameterList(sym(1).FormalParameterList, sym(3).PatternElement))->finish(pool);
+ sym(1).Node = node;
+ } break;
./
-CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
+FormalParameterList: BindingElement;
/.
-case $rule_number: {
- AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FormalParameterList *node = new (pool) AST::FormalParameterList(nullptr, sym(1).PatternElement);
+ sym(1).Node = node;
+ } break;
./
-CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
+
+FormalParameterList: FormalParameterList T_COMMA BindingElement;
/.
-case $rule_number: {
- AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(5);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, sym(3).PatternElement);
+ sym(1).Node = node;
+ } break;
./
-CaseClauses: CaseClause ;
+FormalParameter: BindingElement;
+
+FunctionLBrace: T_LBRACE;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause);
-} break;
+ case $rule_number: {
+ ++functionNestingLevel;
+ } break;
./
-CaseClauses: CaseClauses CaseClause ;
+FunctionRBrace: T_RBRACE;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause);
-} break;
+ case $rule_number: {
+ --functionNestingLevel;
+ } break;
./
-CaseClausesOpt: ;
+
+FunctionBody: StatementListOpt;
+
+ArrowFunction: ArrowParameters T_ARROW ConciseBodyLookahead AssignmentExpression; -- [lookahead ≠ {]
+/. case $rule_number: Q_FALLTHROUGH(); ./
+ArrowFunction_In: ArrowParameters T_ARROW ConciseBodyLookahead AssignmentExpression_In; -- [lookahead ≠ {]
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ AST::ReturnStatement *ret = new (pool) AST::ReturnStatement(sym(4).Expression);
+ ret->returnToken = sym(4).Node->firstSourceLocation();
+ ret->semicolonToken = sym(4).Node->lastSourceLocation();
+ AST::StatementList *statements = (new (pool) AST::StatementList(ret))->finish();
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(QStringRef(), sym(1).FormalParameterList, statements);
+ f->isArrowFunction = true;
+ f->functionToken = sym(1).Node ? sym(1).Node->firstSourceLocation() : loc(1);
+ f->lbraceToken = sym(4).Node->firstSourceLocation();
+ f->rbraceToken = sym(4).Node->lastSourceLocation();
+ sym(1).Node = f;
+ } break;
./
-CaseClausesOpt: CaseClauses ;
+ArrowFunction: ArrowParameters T_ARROW ConciseBodyLookahead T_FORCE_BLOCK FunctionLBrace FunctionBody FunctionRBrace;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+ArrowFunction_In: ArrowParameters T_ARROW ConciseBodyLookahead T_FORCE_BLOCK FunctionLBrace FunctionBody FunctionRBrace;
/.
-case $rule_number: {
- sym(1).Node = sym(1).CaseClauses->finish ();
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(QStringRef(), sym(1).FormalParameterList, sym(6).StatementList);
+ f->isArrowFunction = true;
+ f->functionToken = sym(1).Node ? sym(1).Node->firstSourceLocation() : loc(1);
+ f->lbraceToken = loc(6);
+ f->rbraceToken = loc(7);
+ sym(1).Node = f;
+ } break;
./
-CaseClause: T_CASE Expression T_COLON StatementListOpt ;
+ArrowParameters: BindingIdentifier;
/.
-case $rule_number: {
- AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList);
- node->caseToken = loc(1);
- node->colonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::PatternElement *e = new (pool) AST::PatternElement(stringRef(1), nullptr, AST::PatternElement::Binding);
+ e->identifierToken = loc(1);
+ sym(1).FormalParameterList = (new (pool) AST::FormalParameterList(nullptr, e))->finish(pool);
+ } break;
./
-DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
+-- CoverParenthesizedExpressionAndArrowParameterList for ArrowParameters i being refined to:
+-- ArrowFormalParameters: T_LPAREN StrictFormalParameters T_RPAREN
+ArrowParameters: CoverParenthesizedExpressionAndArrowParameterList;
/.
-case $rule_number: {
- AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList);
- node->defaultToken = loc(1);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ if (coverExpressionType != CE_FormalParameterList) {
+ AST::NestedExpression *ne = static_cast<AST::NestedExpression *>(sym(1).Node);
+ AST::FormalParameterList *list = ne->expression->reparseAsFormalParameterList(pool);
+ if (!list) {
+ syntaxError(loc(1), "Invalid Arrow parameter list.");
+ return false;
+ }
+ sym(1).Node = list->finish(pool);
+ }
+ } break;
./
-LabelledStatement: JsIdentifier T_COLON Statement ;
+ConciseBodyLookahead: ;
+/:
+#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE $rule_number
+:/
/.
-case $rule_number: {
- AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement);
- node->identifierToken = loc(1);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ if (lookaheadToken(lexer) == T_LBRACE)
+ pushToken(T_FORCE_BLOCK);
+ } break;
./
-ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-ThrowStatement: T_THROW Expression T_SEMICOLON ;
+MethodDefinition: PropertyName T_LPAREN StrictFormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
/.
-case $rule_number: {
- AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression);
- node->throwToken = loc(1);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList);
+ f->functionToken = sym(1).PropertyName->firstSourceLocation();
+ f->lparenToken = loc(2);
+ f->rparenToken = loc(4);
+ f->lbraceToken = loc(5);
+ f->rbraceToken = loc(7);
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, f);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-TryStatement: T_TRY Block Catch ;
+MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
-case $rule_number: {
- AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch);
- node->tryToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ f->functionToken = sym(2).PropertyName->firstSourceLocation();
+ f->lparenToken = loc(3);
+ f->rparenToken = loc(5);
+ f->lbraceToken = loc(6);
+ f->rbraceToken = loc(8);
+ f->isGenerator = true;
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+
+MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+/.
+ case $rule_number: {
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), nullptr, sym(6).StatementList);
+ f->functionToken = sym(2).PropertyName->firstSourceLocation();
+ f->lparenToken = loc(3);
+ f->rparenToken = loc(4);
+ f->lbraceToken = loc(5);
+ f->rbraceToken = loc(7);
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Getter);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
+/.
+ case $rule_number: {
+ AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
+ f->functionToken = sym(2).PropertyName->firstSourceLocation();
+ f->lparenToken = loc(3);
+ f->rparenToken = loc(5);
+ f->lbraceToken = loc(6);
+ f->rbraceToken = loc(8);
+ AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Setter);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+ } break;
./
-TryStatement: T_TRY Block Finally ;
+
+PropertySetParameterList: FormalParameter;
/.
-case $rule_number: {
- AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally);
- node->tryToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FormalParameterList *node = (new (pool) AST::FormalParameterList(nullptr, sym(1).PatternElement))->finish(pool);
+ sym(1).Node = node;
+ } break;
+./
+
+GeneratorLParen: T_LPAREN;
+/.
+ case $rule_number: {
+ lexer->enterGeneratorBody();
+ } break;
./
-TryStatement: T_TRY Block Catch Finally ;
+GeneratorRBrace: T_RBRACE;
/.
-case $rule_number: {
- AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally);
- node->tryToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ --functionNestingLevel;
+ lexer->leaveGeneratorBody();
+ } break;
./
-Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ;
+GeneratorDeclaration: Function T_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
-case $rule_number: {
- AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block);
- node->catchToken = loc(1);
- node->lparenToken = loc(2);
- node->identifierToken = loc(3);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(3), sym(5).FormalParameterList, sym(8).StatementList);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->lbraceToken = loc(7);
+ node->rbraceToken = loc(9);
+ node->isGenerator = true;
+ sym(1).Node = node;
+ } break;
+./
+
+GeneratorDeclaration_Default: GeneratorDeclaration;
+GeneratorDeclaration_Default: Function T_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
+/.
+ case $rule_number: {
+ AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(1), sym(4).FormalParameterList, sym(7).StatementList);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ node->isGenerator = true;
+ sym(1).Node = node;
+ } break;
./
-Finally: T_FINALLY Block ;
+GeneratorExpression: T_FUNCTION T_STAR BindingIdentifier GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
-case $rule_number: {
- AST::Finally *node = new (pool) AST::Finally(sym(2).Block);
- node->finallyToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(3), sym(5).FormalParameterList, sym(8).StatementList);
+ node->functionToken = loc(1);
+ if (!stringRef(3).isNull())
+ node->identifierToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->lbraceToken = loc(7);
+ node->rbraceToken = loc(9);
+ node->isGenerator = true;
+ sym(1).Node = node;
+ } break;
./
-DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
-DebuggerStatement: T_DEBUGGER T_SEMICOLON ;
+GeneratorExpression: T_FUNCTION T_STAR GeneratorLParen FormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
/.
-case $rule_number: {
- AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement();
- node->debuggerToken = loc(1);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(4).FormalParameterList, sym(7).StatementList);
+ node->functionToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ node->isGenerator = true;
+ sym(1).Node = node;
+ } break;
./
--- tell the parser to prefer function declarations to function expressions.
--- That is, the `Function' symbol is used to mark the start of a function
--- declaration.
-Function: T_FUNCTION %prec REDUCE_HERE ;
+GeneratorBody: FunctionBody;
-FunctionDeclaration: Function JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+YieldExpression: T_YIELD;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+YieldExpression_In: T_YIELD;
/.
-case $rule_number: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
- node->functionToken = loc(1);
- node->identifierToken = loc(2);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::YieldExpression *node = new (pool) AST::YieldExpression();
+ node->yieldToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-FunctionExpression: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+YieldExpression: T_YIELD T_STAR AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+YieldExpression_In: T_YIELD T_STAR AssignmentExpression_In;
/.
-case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
- node->functionToken = loc(1);
- if (! stringRef(2).isNull())
- node->identifierToken = loc(2);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::YieldExpression *node = new (pool) AST::YieldExpression(sym(3).Expression);
+ node->yieldToken = loc(1);
+ node->isYieldStar = true;
+ sym(1).Node = node;
+ } break;
./
-FunctionExpression: T_FUNCTION T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+YieldExpression: T_YIELD AssignmentExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+YieldExpression_In: T_YIELD AssignmentExpression_In;
/.
-case $rule_number: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody);
- node->functionToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- node->lbraceToken = loc(5);
- node->rbraceToken = loc(7);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::YieldExpression *node = new (pool) AST::YieldExpression(sym(2).Expression);
+ node->yieldToken = loc(1);
+ sym(1).Node = node;
+ } break;
./
-FormalParameterList: JsIdentifier ;
+
+ClassDeclaration: T_CLASS BindingIdentifier ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace;
/.
-case $rule_number: {
- AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ClassDeclaration *node = new (pool) AST::ClassDeclaration(stringRef(2), sym(3).Expression, sym(5).ClassElementList);
+ node->classToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lbraceToken = loc(4);
+ node->rbraceToken = loc(6);
+ sym(1).Node = node;
+ } break;
./
-FormalParameterList: FormalParameterList T_COMMA JsIdentifier ;
+ClassExpression: T_CLASS BindingIdentifier ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace;
/.
-case $rule_number: {
- AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3));
- node->commaToken = loc(2);
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
+ case $rule_number: {
+ AST::ClassExpression *node = new (pool) AST::ClassExpression(stringRef(2), sym(3).Expression, sym(5).ClassElementList);
+ node->classToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lbraceToken = loc(4);
+ node->rbraceToken = loc(6);
+ sym(1).Node = node;
+ } break;
./
-FormalParameterListOpt: ;
+ClassDeclaration_Default: T_CLASS ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ AST::ClassDeclaration *node = new (pool) AST::ClassDeclaration(QStringRef(), sym(2).Expression, sym(4).ClassElementList);
+ node->classToken = loc(1);
+ node->lbraceToken = loc(3);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+ } break;
./
-FormalParameterListOpt: FormalParameterList ;
+ClassExpression: T_CLASS ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace;
/.
-case $rule_number: {
- sym(1).Node = sym(1).FormalParameterList->finish ();
-} break;
+ case $rule_number: {
+ AST::ClassExpression *node = new (pool) AST::ClassExpression(QStringRef(), sym(2).Expression, sym(4).ClassElementList);
+ node->classToken = loc(1);
+ node->lbraceToken = loc(3);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+ } break;
./
-FunctionBodyOpt: ;
+ClassDeclaration_Default: ClassDeclaration;
+
+ClassLBrace: T_LBRACE;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ lexer->setStaticIsKeyword(true);
+ } break;
./
-FunctionBodyOpt: FunctionBody ;
+ClassRBrace: T_RBRACE;
+/. case $rule_number: ./
+ClassStaticQualifier: T_STATIC;
+/.
+ case $rule_number: {
+ lexer->setStaticIsKeyword(false);
+ } break;
+./
-FunctionBody: SourceElements ;
+ClassHeritageOpt: ;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ());
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-Program: Empty ;
+ClassHeritageOpt: T_EXTENDS LeftHandSideExpression;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ } break;
+./
-Program: SourceElements ;
+ClassBodyOpt: ;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ());
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-SourceElements: SourceElement ;
+ClassBodyOpt: ClassElementList;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement);
-} break;
+ case $rule_number: {
+ if (sym(1).Node)
+ sym(1).Node = sym(1).ClassElementList->finish();
+ } break;
./
-SourceElements: SourceElements SourceElement ;
+ClassElementList: ClassElement;
+
+ClassElementList: ClassElementList ClassElement;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement);
-} break;
+ case $rule_number: {
+ if (sym(2).Node)
+ sym(1).ClassElementList = sym(1).ClassElementList->append(sym(2).ClassElementList);
+ } break;
./
-SourceElement: Statement ;
+ClassElement: MethodDefinition;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement);
-} break;
+ case $rule_number: {
+ AST::ClassElementList *node = new (pool) AST::ClassElementList(sym(1).PatternProperty, false);
+ sym(1).Node = node;
+ } break;
./
-SourceElement: FunctionDeclaration ;
+ClassElement: ClassStaticQualifier MethodDefinition;
/.
-case $rule_number: {
- sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration);
-} break;
+ case $rule_number: {
+ lexer->setStaticIsKeyword(true);
+ AST::ClassElementList *node = new (pool) AST::ClassElementList(sym(2).PatternProperty, true);
+ sym(1).Node = node;
+ } break;
./
-PropertyAssignmentListOpt: ;
+ClassElement: T_SEMICOLON;
/.
-case $rule_number: {
- sym(1).Node = 0;
-} break;
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
+./
+
+-- Scripts and Modules
+
+Script: ;
+/.
+ case $rule_number: {
+ sym(1).Node = nullptr;
+ } break;
./
-PropertyAssignmentListOpt: PropertyAssignmentList ;
+Script: ScriptBody;
+ScriptBody: StatementList;
/.
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::Program(sym(1).StatementList->finish());
+ } break;
+./
+
+Module: ModuleBodyOpt;
+/. case $rule_number: { UNIMPLEMENTED; } ./
+
+ModuleBody: ModuleItemList;
+
+ModuleBodyOpt: ;
+ModuleBodyOpt: ModuleBody;
+
+ModuleItemList: ModuleItem;
+ModuleItemList: ModuleItemList ModuleItem;
+
+ModuleItem: ImportDeclaration T_AUTOMATIC_SEMICOLON;
+ModuleItem: ImportDeclaration T_SEMICOLON;
+ModuleItem: ExportDeclaration T_AUTOMATIC_SEMICOLON;
+ModuleItem: ExportDeclaration T_SEMICOLON;
+ModuleItem: StatementListItem;
+
+ImportDeclaration: T_IMPORT ImportClause FromClause;
+ImportDeclaration: T_IMPORT ModuleSpecifier;
+
+ImportClause: ImportedDefaultBinding;
+ImportClause: NameSpaceImport;
+ImportClause: NamedImports;
+ImportClause: ImportedDefaultBinding T_COMMA NameSpaceImport;
+ImportClause: ImportedDefaultBinding T_COMMA NamedImports;
+
+ImportedDefaultBinding: ImportedBinding;
+
+NameSpaceImport: T_STAR T_AS ImportedBinding;
+
+NamedImports: T_LBRACE T_RBRACE;
+NamedImports: T_LBRACE ImportsList T_RBRACE;
+NamedImports: T_LBRACE ImportsList T_COMMA T_RBRACE;
+
+FromClause: T_FROM ModuleSpecifier;
+
+ImportsList: ImportSpecifier;
+ImportsList: ImportsList T_COMMA ImportSpecifier;
+
+ImportSpecifier: ImportedBinding;
+ImportSpecifier: IdentifierName T_AS ImportedBinding;
+
+ModuleSpecifier: T_STRING_LITERAL;
+
+ImportedBinding: BindingIdentifier;
+
+ExportDeclarationLookahead: ;
+/:
+#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE $rule_number
+:/
+/.
+ case $rule_number: {
+ int token = lookaheadToken(lexer);
+ if (token == T_FUNCTION || token == T_CLASS)
+ pushToken(T_FORCE_DECLARATION);
+ } break;
+./
+
+ExportDeclaration: T_EXPORT T_STAR FromClause;
+ExportDeclaration: T_EXPORT ExportClause FromClause;
+ExportDeclaration: T_EXPORT ExportClause;
+ExportDeclaration: T_EXPORT VariableStatement;
+ExportDeclaration: T_EXPORT Declaration;
+ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead T_FORCE_DECLARATION HoistableDeclaration_Default;
+ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead T_FORCE_DECLARATION ClassDeclaration_Default;
+ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead AssignmentExpression_In; -- [lookahead ∉ { function, class }]
+
+ExportClause: T_LBRACE T_RBRACE;
+ExportClause: T_LBRACE ExportsList T_RBRACE;
+ExportClause: T_LBRACE ExportsList T_COMMA T_RBRACE;
+
+ExportsList: ExportSpecifier;
+ExportsList: ExportsList T_COMMA ExportSpecifier;
+
+ExportSpecifier: IdentifierName;
+ExportSpecifier: IdentifierName T_AS IdentifierName;
+
+-- Old top level code
+
+/.
+ // ------------ end of switch statement
} // switch
action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
} // if
} while (action != 0);
+#ifdef PARSER_DEBUG
+ qDebug() << "Done or error.";
+#endif
+
if (first_token == last_token) {
const int errorState = state_stack[tos];
// automatic insertion of `;'
if (yytoken != -1 && ((t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken))
|| t_action(errorState, T_COMPATIBILITY_SEMICOLON))) {
+#ifdef PARSER_DEBUG
+ qDebug() << "Inserting automatic semicolon.";
+#endif
SavedToken &tk = token_buffer[0];
tk.token = yytoken;
tk.dval = yylval;
@@ -3260,8 +4211,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ;
for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM ||
- tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION ||
- tk == T_FEED_JS_SOURCE_ELEMENT)
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION)
continue;
int a = t_action(errorState, tk);
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index 0d1b512c92..d254279cbf 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -45,6 +45,27 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS { namespace AST {
+FunctionExpression *asAnonymousFunctionDefinition(Node *n)
+{
+ if (!n)
+ return nullptr;
+ FunctionExpression *f = n->asFunctionDefinition();
+ if (!f || !f->name.isNull())
+ return nullptr;
+ return f;
+}
+
+ClassExpression *asAnonymousClassDefinition(Node *n)
+{
+ if (!n)
+ return nullptr;
+ ClassExpression *c = n->asClassDefinition();
+ if (!c || !c->name.isNull())
+ return nullptr;
+ return c;
+}
+
+
void Node::accept(Visitor *visitor)
{
if (visitor->preVisit(this)) {
@@ -79,11 +100,67 @@ UiObjectMember *Node::uiObjectMemberCast()
return nullptr;
}
+LeftHandSideExpression *Node::leftHandSideExpressionCast()
+{
+ return nullptr;
+}
+
+Pattern *Node::patternCast()
+{
+ return nullptr;
+}
+
+FunctionExpression *Node::asFunctionDefinition()
+{
+ return nullptr;
+}
+
+ClassExpression *Node::asClassDefinition()
+{
+ return nullptr;
+}
+
ExpressionNode *ExpressionNode::expressionCast()
{
return this;
}
+FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *pool)
+{
+ AST::ExpressionNode *expr = this;
+ AST::FormalParameterList *f = nullptr;
+ if (AST::Expression *commaExpr = AST::cast<AST::Expression *>(expr)) {
+ f = commaExpr->left->reparseAsFormalParameterList(pool);
+ if (!f)
+ return nullptr;
+
+ expr = commaExpr->right;
+ }
+
+ AST::ExpressionNode *rhs = nullptr;
+ if (AST::BinaryExpression *assign = AST::cast<AST::BinaryExpression *>(expr)) {
+ if (assign->op != QSOperator::Assign)
+ return nullptr;
+ expr = assign->left;
+ rhs = assign->right;
+ }
+ AST::PatternElement *binding = nullptr;
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) {
+ binding = new (pool) AST::PatternElement(idExpr->name, rhs);
+ binding->identifierToken = idExpr->identifierToken;
+ } else if (AST::Pattern *p = expr->patternCast()) {
+ SourceLocation loc;
+ QString s;
+ if (!p->convertLiteralToAssignmentPattern(pool, &loc, &s))
+ return nullptr;
+ binding = new (pool) AST::PatternElement(p, rhs);
+ binding->identifierToken = p->firstSourceLocation();
+ }
+ if (!binding)
+ return nullptr;
+ return new (pool) AST::FormalParameterList(f, binding);
+}
+
BinaryExpression *BinaryExpression::binaryExpressionCast()
{
return this;
@@ -107,6 +184,16 @@ void NestedExpression::accept0(Visitor *visitor)
visitor->endVisit(this);
}
+FunctionExpression *NestedExpression::asFunctionDefinition()
+{
+ return expression->asFunctionDefinition();
+}
+
+ClassExpression *NestedExpression::asClassDefinition()
+{
+ return expression->asClassDefinition();
+}
+
void ThisExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -147,7 +234,7 @@ void FalseLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void StringLiteral::accept0(Visitor *visitor)
+void SuperLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
@@ -155,7 +242,8 @@ void StringLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void NumericLiteral::accept0(Visitor *visitor)
+
+void StringLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
@@ -163,81 +251,229 @@ void NumericLiteral::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void RegExpLiteral::accept0(Visitor *visitor)
+void TemplateLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
+ if (next)
+ accept(next, visitor);
}
visitor->endVisit(this);
}
-void ArrayLiteral::accept0(Visitor *visitor)
+void NumericLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- accept(elements, visitor);
- accept(elision, visitor);
}
visitor->endVisit(this);
}
-void ObjectLiteral::accept0(Visitor *visitor)
+void RegExpLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- accept(properties, visitor);
}
visitor->endVisit(this);
}
-void ElementList::accept0(Visitor *visitor)
+void ArrayPattern::accept0(Visitor *visitor)
{
- if (visitor->visit(this)) {
- for (ElementList *it = this; it; it = it->next) {
- accept(it->elision, visitor);
- accept(it->expression, visitor);
- }
- }
+ if (visitor->visit(this))
+ accept(elements, visitor);
visitor->endVisit(this);
}
-void Elision::accept0(Visitor *visitor)
+bool ArrayPattern::isValidArrayLiteral(SourceLocation *errorLocation) const {
+ for (PatternElementList *it = elements; it != nullptr; it = it->next) {
+ PatternElement *e = it->element;
+ if (e && e->bindingTarget != nullptr) {
+ if (errorLocation)
+ *errorLocation = e->firstSourceLocation();
+ return false;
+ }
+ }
+ return true;
+}
+
+void ObjectPattern::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- // ###
+ accept(properties, visitor);
}
visitor->endVisit(this);
}
-void PropertyNameAndValue::accept0(Visitor *visitor)
-{
- if (visitor->visit(this)) {
- accept(name, visitor);
- accept(value, visitor);
+/*
+ This is the grammar for AssignmentPattern that we need to convert the literal to:
+
+ AssignmentPattern:
+ ObjectAssignmentPattern
+ ArrayAssignmentPattern
+ ArrayAssignmentPattern:
+ [ ElisionOpt AssignmentRestElementOpt ]
+ [ AssignmentElementList ]
+ [ AssignmentElementList , ElisionOpt AssignmentRestElementOpt ]
+ AssignmentElementList:
+ AssignmentElisionElement
+ AssignmentElementList , AssignmentElisionElement
+ AssignmentElisionElement:
+ ElisionOpt AssignmentElement
+ AssignmentRestElement:
+ ... DestructuringAssignmentTarget
+
+ ObjectAssignmentPattern:
+ {}
+ { AssignmentPropertyList }
+ { AssignmentPropertyList, }
+ AssignmentPropertyList:
+ AssignmentProperty
+ AssignmentPropertyList , AssignmentProperty
+ AssignmentProperty:
+ IdentifierReference InitializerOpt_In
+ PropertyName:
+ AssignmentElement
+
+ AssignmentElement:
+ DestructuringAssignmentTarget InitializerOpt_In
+ DestructuringAssignmentTarget:
+ LeftHandSideExpression
+
+ It was originally parsed with the following grammar:
+
+ArrayLiteral:
+ [ ElisionOpt ]
+ [ ElementList ]
+ [ ElementList , ElisionOpt ]
+ElementList:
+ ElisionOpt AssignmentExpression_In
+ ElisionOpt SpreadElement
+ ElementList , ElisionOpt AssignmentExpression_In
+ ElementList , Elisionopt SpreadElement
+SpreadElement:
+ ... AssignmentExpression_In
+ObjectLiteral:
+ {}
+ { PropertyDefinitionList }
+ { PropertyDefinitionList , }
+PropertyDefinitionList:
+ PropertyDefinition
+ PropertyDefinitionList , PropertyDefinition
+PropertyDefinition:
+ IdentifierReference
+ CoverInitializedName
+ PropertyName : AssignmentExpression_In
+ MethodDefinition
+PropertyName:
+ LiteralPropertyName
+ ComputedPropertyName
+
+*/
+bool ArrayPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
+{
+ if (parseMode == Binding)
+ return true;
+ for (auto *it = elements; it; it = it->next) {
+ if (!it->element)
+ continue;
+ if (it->element->type == PatternElement::SpreadElement && it->next) {
+ *errorLocation = it->element->firstSourceLocation();
+ *errorMessage = QString::fromLatin1("'...' can only appear as last element in a destructuring list.");
+ return false;
+ }
+ if (!it->element->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage))
+ return false;
}
+ parseMode = Binding;
+ return true;
+}
- visitor->endVisit(this);
+bool ObjectPattern::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
+{
+ if (parseMode == Binding)
+ return true;
+ for (auto *it = properties; it; it = it->next) {
+ if (!it->property->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage))
+ return false;
+ }
+ parseMode = Binding;
+ return true;
}
-void PropertyGetterSetter::accept0(Visitor *visitor)
+bool PatternElement::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
{
- if (visitor->visit(this)) {
- accept(name, visitor);
- accept(formals, visitor);
- accept(functionBody, visitor);
+ Q_ASSERT(type == Literal || type == SpreadElement);
+ Q_ASSERT(bindingIdentifier.isNull());
+ Q_ASSERT(bindingTarget == nullptr);
+ Q_ASSERT(bindingTarget == nullptr);
+ Q_ASSERT(initializer);
+ ExpressionNode *init = initializer;
+
+ initializer = nullptr;
+ LeftHandSideExpression *lhs = init->leftHandSideExpressionCast();
+ if (type == SpreadElement) {
+ if (!lhs) {
+ *errorLocation = init->firstSourceLocation();
+ *errorMessage = QString::fromLatin1("Invalid lhs expression after '...' in destructuring expression.");
+ return false;
+ }
+ } else {
+ type = PatternElement::Binding;
+
+ if (BinaryExpression *b = init->binaryExpressionCast()) {
+ if (b->op != QSOperator::Assign) {
+ *errorLocation = b->operatorToken;
+ *errorMessage = QString::fromLatin1("Invalid assignment operation in destructuring expression");
+ return false;
+ }
+ lhs = b->left->leftHandSideExpressionCast();
+ initializer = b->right;
+ Q_ASSERT(lhs);
+ } else {
+ lhs = init->leftHandSideExpressionCast();
+ }
+ if (!lhs) {
+ *errorLocation = init->firstSourceLocation();
+ *errorMessage = QString::fromLatin1("Destructuring target is not a left hand side expression.");
+ return false;
+ }
}
- visitor->endVisit(this);
+ if (auto *i = cast<IdentifierExpression *>(lhs)) {
+ bindingIdentifier = i->name;
+ identifierToken = i->identifierToken;
+ return true;
+ }
+
+ bindingTarget = lhs;
+ if (auto *p = lhs->patternCast()) {
+ if (!p->convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage))
+ return false;
+ }
+ return true;
+}
+
+bool PatternProperty::convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage)
+{
+ Q_ASSERT(type != SpreadElement);
+ if (type == Binding)
+ return true;
+ if (type == Getter || type == Setter) {
+ *errorLocation = firstSourceLocation();
+ *errorMessage = QString::fromLatin1("Invalid getter/setter in destructuring expression.");
+ return false;
+ }
+ Q_ASSERT(type == Literal);
+ return PatternElement::convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage);
}
-void PropertyAssignmentList::accept0(Visitor *visitor)
+
+void Elision::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- for (PropertyAssignmentList *it = this; it; it = it->next) {
- accept(it->assignment, visitor);
- }
+ // ###
}
visitor->endVisit(this);
@@ -518,15 +754,6 @@ void VariableDeclarationList::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void VariableDeclaration::accept0(Visitor *visitor)
-{
- if (visitor->visit(this)) {
- accept(expression, visitor);
- }
-
- visitor->endVisit(this);
-}
-
void EmptyStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -579,17 +806,6 @@ void ForStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(initialiser, visitor);
- accept(condition, visitor);
- accept(expression, visitor);
- accept(statement, visitor);
- }
-
- visitor->endVisit(this);
-}
-
-void LocalForStatement::accept0(Visitor *visitor)
-{
- if (visitor->visit(this)) {
accept(declarations, visitor);
accept(condition, visitor);
accept(expression, visitor);
@@ -602,7 +818,7 @@ void LocalForStatement::accept0(Visitor *visitor)
void ForEachStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- accept(initialiser, visitor);
+ accept(lhs, visitor);
accept(expression, visitor);
accept(statement, visitor);
}
@@ -610,18 +826,15 @@ void ForEachStatement::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void LocalForEachStatement::accept0(Visitor *visitor)
+void ContinueStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- accept(declaration, visitor);
- accept(expression, visitor);
- accept(statement, visitor);
}
visitor->endVisit(this);
}
-void ContinueStatement::accept0(Visitor *visitor)
+void BreakStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
@@ -629,15 +842,16 @@ void ContinueStatement::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void BreakStatement::accept0(Visitor *visitor)
+void ReturnStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
+ accept(expression, visitor);
}
visitor->endVisit(this);
}
-void ReturnStatement::accept0(Visitor *visitor)
+void YieldExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(expression, visitor);
@@ -646,6 +860,7 @@ void ReturnStatement::accept0(Visitor *visitor)
visitor->endVisit(this);
}
+
void WithStatement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -739,6 +954,7 @@ void TryStatement::accept0(Visitor *visitor)
void Catch::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
+ accept(patternElement, visitor);
accept(statement, visitor);
}
@@ -774,57 +990,69 @@ void FunctionExpression::accept0(Visitor *visitor)
visitor->endVisit(this);
}
-void FormalParameterList::accept0(Visitor *visitor)
+FunctionExpression *FunctionExpression::asFunctionDefinition()
{
- if (visitor->visit(this)) {
- // ###
- }
-
- visitor->endVisit(this);
+ return this;
}
-void FunctionBody::accept0(Visitor *visitor)
+QStringList FormalParameterList::formals() const
{
- if (visitor->visit(this)) {
- accept(elements, visitor);
+ QStringList formals;
+ int i = 0;
+ for (const FormalParameterList *it = this; it; it = it->next) {
+ if (it->element) {
+ QString name = it->element->bindingIdentifier.toString();
+ int duplicateIndex = formals.indexOf(name);
+ if (duplicateIndex >= 0) {
+ // change the name of the earlier argument to enforce the lookup semantics from the spec
+ formals[duplicateIndex] += QLatin1String("#") + QString::number(i);
+ }
+ formals += name;
+ }
+ ++i;
}
-
- visitor->endVisit(this);
+ return formals;
}
-void Program::accept0(Visitor *visitor)
+QStringList FormalParameterList::boundNames() const
{
- if (visitor->visit(this)) {
- accept(elements, visitor);
+ QStringList names;
+ for (const FormalParameterList *it = this; it; it = it->next) {
+ if (it->element)
+ it->element->boundNames(&names);
}
-
- visitor->endVisit(this);
+ return names;
}
-void SourceElements::accept0(Visitor *visitor)
+void FormalParameterList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- for (SourceElements *it = this; it; it = it->next) {
- accept(it->element, visitor);
- }
+ accept(element, visitor);
+ if (next)
+ accept(next, visitor);
}
visitor->endVisit(this);
}
-void FunctionSourceElement::accept0(Visitor *visitor)
+FormalParameterList *FormalParameterList::finish(QQmlJS::MemoryPool *pool)
{
- if (visitor->visit(this)) {
- accept(declaration, visitor);
- }
+ FormalParameterList *front = next;
+ next = nullptr;
- visitor->endVisit(this);
+ int i = 0;
+ for (const FormalParameterList *it = this; it; it = it->next) {
+ if (it->element && it->element->bindingIdentifier.isEmpty())
+ it->element->bindingIdentifier = pool->newString(QLatin1String("arg#") + QString::number(i));
+ ++i;
+ }
+ return front;
}
-void StatementSourceElement::accept0(Visitor *visitor)
+void Program::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
- accept(statement, visitor);
+ accept(statements, visitor);
}
visitor->endVisit(this);
@@ -1006,6 +1234,153 @@ void UiEnumMemberList::accept0(Visitor *visitor)
visitor->endVisit(this);
}
+void TaggedTemplate::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(templateLiteral, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PatternElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(bindingTarget, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PatternElement::boundNames(QStringList *names)
+{
+ if (bindingTarget) {
+ if (PatternElementList *e = elementList())
+ e->boundNames(names);
+ else if (PatternPropertyList *p = propertyList())
+ p->boundNames(names);
+ } else {
+ names->append(bindingIdentifier.toString());
+ }
+}
+
+void PatternElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elision, visitor);
+ accept(element, visitor);
+ if (next)
+ accept(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PatternElementList::boundNames(QStringList *names)
+{
+ for (PatternElementList *it = this; it; it = it->next) {
+ if (it->element)
+ it->element->boundNames(names);
+ }
+}
+
+void PatternProperty::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ accept(bindingTarget, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PatternProperty::boundNames(QStringList *names)
+{
+ PatternElement::boundNames(names);
+}
+
+void PatternPropertyList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(property, visitor);
+ if (next)
+ accept(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PatternPropertyList::boundNames(QStringList *names)
+{
+ for (PatternPropertyList *it = this; it; it = it->next)
+ it->property->boundNames(names);
+}
+
+void ComputedPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ClassExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(heritage, visitor);
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+ClassExpression *ClassExpression::asClassDefinition()
+{
+ return this;
+}
+
+void ClassDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(heritage, visitor);
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ClassElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(property, visitor);
+ if (next)
+ accept(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+ClassElementList *ClassElementList::finish()
+{
+ ClassElementList *front = next;
+ next = nullptr;
+ return front;
+}
+
+Pattern *Pattern::patternCast()
+{
+ return this;
+}
+
+LeftHandSideExpression *LeftHandSideExpression::leftHandSideExpressionCast()
+{
+ return this;
+}
+
} } // namespace QQmlJS::AST
QT_QML_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 9c5fd5adf6..07999404b4 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -77,6 +77,8 @@ enum Op {
Div,
InplaceDiv,
Equal,
+ Exp,
+ InplaceExp,
Ge,
Gt,
In,
@@ -110,6 +112,13 @@ namespace QQmlJS {
namespace AST {
+enum class VariableScope {
+ NoScope,
+ Var,
+ Let,
+ Const
+};
+
template <typename T1, typename T2>
T1 cast(T2 *ast)
{
@@ -119,6 +128,9 @@ T1 cast(T2 *ast)
return 0;
}
+FunctionExpression *asAnonymousFunctionDefinition(AST::Node *n);
+ClassExpression *asAnonymousClassDefinition(AST::Node *n);
+
class QML_PARSER_EXPORT Node: public Managed
{
public:
@@ -126,7 +138,7 @@ public:
Kind_Undefined,
Kind_ArgumentList,
- Kind_ArrayLiteral,
+ Kind_ArrayPattern,
Kind_ArrayMemberExpression,
Kind_BinaryExpression,
Kind_Block,
@@ -148,6 +160,7 @@ public:
Kind_Expression,
Kind_ExpressionStatement,
Kind_FalseLiteral,
+ Kind_SuperLiteral,
Kind_FieldMemberExpression,
Kind_Finally,
Kind_ForEachStatement,
@@ -156,38 +169,38 @@ public:
Kind_FunctionBody,
Kind_FunctionDeclaration,
Kind_FunctionExpression,
- Kind_FunctionSourceElement,
+ Kind_ClassExpression,
+ Kind_ClassDeclaration,
Kind_IdentifierExpression,
Kind_IdentifierPropertyName,
+ Kind_ComputedPropertyName,
Kind_IfStatement,
Kind_LabelledStatement,
- Kind_LocalForEachStatement,
- Kind_LocalForStatement,
Kind_NewExpression,
Kind_NewMemberExpression,
Kind_NotExpression,
Kind_NullExpression,
+ Kind_YieldExpression,
Kind_NumericLiteral,
Kind_NumericLiteralPropertyName,
- Kind_ObjectLiteral,
+ Kind_ObjectPattern,
Kind_PostDecrementExpression,
Kind_PostIncrementExpression,
Kind_PreDecrementExpression,
Kind_PreIncrementExpression,
Kind_Program,
- Kind_PropertyAssignmentList,
+ Kind_PropertyDefinitionList,
Kind_PropertyGetterSetter,
Kind_PropertyName,
Kind_PropertyNameAndValue,
Kind_RegExpLiteral,
Kind_ReturnStatement,
- Kind_SourceElement,
- Kind_SourceElements,
Kind_StatementList,
- Kind_StatementSourceElement,
Kind_StringLiteral,
Kind_StringLiteralPropertyName,
Kind_SwitchStatement,
+ Kind_TemplateLiteral,
+ Kind_TaggedTemplate,
Kind_ThisExpression,
Kind_ThrowStatement,
Kind_TildeExpression,
@@ -203,6 +216,12 @@ public:
Kind_WhileStatement,
Kind_WithStatement,
Kind_NestedExpression,
+ Kind_ClassElementList,
+ Kind_PatternElement,
+ Kind_PatternElementList,
+ Kind_PatternProperty,
+ Kind_PatternPropertyList,
+
Kind_UiArrayBinding,
Kind_UiImport,
@@ -235,6 +254,11 @@ public:
virtual BinaryExpression *binaryExpressionCast();
virtual Statement *statementCast();
virtual UiObjectMember *uiObjectMemberCast();
+ virtual LeftHandSideExpression *leftHandSideExpressionCast();
+ virtual Pattern *patternCast();
+ // implements the IsFunctionDefinition rules in the spec
+ virtual FunctionExpression *asFunctionDefinition();
+ virtual ClassExpression *asClassDefinition();
void accept(Visitor *visitor);
static void accept(Node *node, Visitor *visitor);
@@ -256,6 +280,14 @@ public:
ExpressionNode() {}
ExpressionNode *expressionCast() override;
+
+ AST::FormalParameterList *reparseAsFormalParameterList(MemoryPool *pool);
+
+};
+
+class QML_PARSER_EXPORT LeftHandSideExpression : public ExpressionNode
+{
+ LeftHandSideExpression *leftHandSideExpressionCast() override;
};
class QML_PARSER_EXPORT Statement: public Node
@@ -266,7 +298,7 @@ public:
Statement *statementCast() override;
};
-class QML_PARSER_EXPORT NestedExpression: public ExpressionNode
+class QML_PARSER_EXPORT NestedExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(NestedExpression)
@@ -283,13 +315,17 @@ public:
SourceLocation lastSourceLocation() const override
{ return rparenToken; }
+ FunctionExpression *asFunctionDefinition() override;
+ ClassExpression *asClassDefinition() override;
+
+
// attributes
ExpressionNode *expression;
SourceLocation lparenToken;
SourceLocation rparenToken;
};
-class QML_PARSER_EXPORT ThisExpression: public ExpressionNode
+class QML_PARSER_EXPORT ThisExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(ThisExpression)
@@ -308,7 +344,7 @@ public:
SourceLocation thisToken;
};
-class QML_PARSER_EXPORT IdentifierExpression: public ExpressionNode
+class QML_PARSER_EXPORT IdentifierExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(IdentifierExpression)
@@ -329,7 +365,7 @@ public:
SourceLocation identifierToken;
};
-class QML_PARSER_EXPORT NullExpression: public ExpressionNode
+class QML_PARSER_EXPORT NullExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(NullExpression)
@@ -348,7 +384,7 @@ public:
SourceLocation nullToken;
};
-class QML_PARSER_EXPORT TrueLiteral: public ExpressionNode
+class QML_PARSER_EXPORT TrueLiteral: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(TrueLiteral)
@@ -367,7 +403,7 @@ public:
SourceLocation trueToken;
};
-class QML_PARSER_EXPORT FalseLiteral: public ExpressionNode
+class QML_PARSER_EXPORT FalseLiteral: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(FalseLiteral)
@@ -386,7 +422,27 @@ public:
SourceLocation falseToken;
};
-class QML_PARSER_EXPORT NumericLiteral: public ExpressionNode
+class QML_PARSER_EXPORT SuperLiteral : public LeftHandSideExpression
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(SuperLiteral)
+
+ SuperLiteral() { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return superToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return superToken; }
+
+// attributes
+ SourceLocation superToken;
+};
+
+
+class QML_PARSER_EXPORT NumericLiteral: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(NumericLiteral)
@@ -407,7 +463,7 @@ public:
SourceLocation literalToken;
};
-class QML_PARSER_EXPORT StringLiteral: public ExpressionNode
+class QML_PARSER_EXPORT StringLiteral: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(StringLiteral)
@@ -428,7 +484,30 @@ public:
SourceLocation literalToken;
};
-class QML_PARSER_EXPORT RegExpLiteral: public ExpressionNode
+class QML_PARSER_EXPORT TemplateLiteral : public LeftHandSideExpression
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(TemplateLiteral)
+
+ TemplateLiteral(const QStringRef &str, ExpressionNode *e)
+ : value(str), expression(e), next(nullptr)
+ { kind = K; }
+
+ SourceLocation firstSourceLocation() const override
+ { return literalToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return next ? next->lastSourceLocation() : (expression ? expression->lastSourceLocation() : literalToken); }
+
+ void accept0(Visitor *visitor) override;
+
+ QStringRef value;
+ ExpressionNode *expression;
+ TemplateLiteral *next;
+ SourceLocation literalToken;
+};
+
+class QML_PARSER_EXPORT RegExpLiteral: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(RegExpLiteral)
@@ -450,22 +529,26 @@ public:
SourceLocation literalToken;
};
-class QML_PARSER_EXPORT ArrayLiteral: public ExpressionNode
+class QML_PARSER_EXPORT Pattern : public LeftHandSideExpression
{
public:
- QQMLJS_DECLARE_AST_NODE(ArrayLiteral)
-
- ArrayLiteral(Elision *e):
- elements (nullptr), elision (e)
- { kind = K; }
+ enum ParseMode {
+ Literal,
+ Binding
+ };
+ Pattern *patternCast() override;
+ virtual bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) = 0;
+ ParseMode parseMode = Literal;
+};
- ArrayLiteral(ElementList *elts):
- elements (elts), elision (nullptr)
- { kind = K; }
+class QML_PARSER_EXPORT ArrayPattern : public Pattern
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(ArrayPattern)
- ArrayLiteral(ElementList *elts, Elision *e):
- elements (elts), elision (e)
- { kind = K; }
+ ArrayPattern(PatternElementList *elts)
+ : elements(elts)
+ { kind = K; }
void accept0(Visitor *visitor) override;
@@ -475,24 +558,28 @@ public:
SourceLocation lastSourceLocation() const override
{ return rbracketToken; }
+ bool isValidArrayLiteral(SourceLocation *errorLocation = nullptr) const;
+
+ bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) override;
+
// attributes
- ElementList *elements;
- Elision *elision;
+ PatternElementList *elements = nullptr;
SourceLocation lbracketToken;
SourceLocation commaToken;
SourceLocation rbracketToken;
};
-class QML_PARSER_EXPORT ObjectLiteral: public ExpressionNode
+class QML_PARSER_EXPORT ObjectPattern : public Pattern
{
public:
- QQMLJS_DECLARE_AST_NODE(ObjectLiteral)
+ QQMLJS_DECLARE_AST_NODE(ObjectPattern)
- ObjectLiteral()
+ ObjectPattern()
{ kind = K; }
- ObjectLiteral(PropertyAssignmentList *plist):
- properties (plist) { kind = K; }
+ ObjectPattern(PatternPropertyList *plist)
+ : properties(plist)
+ { kind = K; }
void accept0(Visitor *visitor) override;
@@ -502,8 +589,10 @@ public:
SourceLocation lastSourceLocation() const override
{ return rbraceToken; }
+ bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) override;
+
// attributes
- PropertyAssignmentList *properties = nullptr;
+ PatternPropertyList *properties = nullptr;
SourceLocation lbraceToken;
SourceLocation rbraceToken;
};
@@ -543,53 +632,6 @@ public:
SourceLocation commaToken;
};
-class QML_PARSER_EXPORT ElementList: public Node
-{
-public:
- QQMLJS_DECLARE_AST_NODE(ElementList)
-
- ElementList(Elision *e, ExpressionNode *expr):
- elision (e), expression (expr), next (this)
- { kind = K; }
-
- ElementList(ElementList *previous, Elision *e, ExpressionNode *expr):
- elision (e), expression (expr)
- {
- kind = K;
- next = previous->next;
- previous->next = this;
- }
-
- inline ElementList *finish ()
- {
- ElementList *front = next;
- next = nullptr;
- return front;
- }
-
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- {
- if (elision)
- return elision->firstSourceLocation();
- return expression->firstSourceLocation();
- }
-
- SourceLocation lastSourceLocation() const override
- {
- if (next)
- return next->lastSourceLocation();
- return expression->lastSourceLocation();
- }
-
-// attributes
- Elision *elision;
- ExpressionNode *expression;
- ElementList *next;
- SourceLocation commaToken;
-};
-
class QML_PARSER_EXPORT PropertyName: public Node
{
public:
@@ -609,116 +651,184 @@ public:
SourceLocation propertyNameToken;
};
-class QML_PARSER_EXPORT PropertyAssignment: public Node
+class QML_PARSER_EXPORT PatternElement : public Node
{
public:
- PropertyAssignment(PropertyName *n)
- : name(n)
- {}
+ QQMLJS_DECLARE_AST_NODE(PatternElement)
+
+ enum Type {
+ // object literal types
+ Literal,
+ Getter,
+ Setter,
+
+ // used by both bindings and literals
+ SpreadElement,
+ RestElement = SpreadElement,
+
+ // binding types
+ Binding,
+ };
+
+ PatternElement(ExpressionNode *i = nullptr, Type t = Literal)
+ : initializer(i), type(t)
+ { kind = K; }
+
+ PatternElement(const QStringRef &n, ExpressionNode *i = nullptr, Type t = Binding)
+ : bindingIdentifier(n), initializer(i), type(t)
+ {
+ Q_ASSERT(t >= RestElement);
+ kind = K;
+ }
+
+ PatternElement(Pattern *pattern, ExpressionNode *i = nullptr, Type t = Binding)
+ : bindingTarget(pattern), initializer(i), type(t)
+ {
+ Q_ASSERT(t >= RestElement);
+ kind = K;
+ }
+
+ void accept0(Visitor *visitor) override;
+ virtual bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage);
+
+ SourceLocation firstSourceLocation() const override
+ { return identifierToken.isValid() ? identifierToken : (bindingTarget ? bindingTarget->firstSourceLocation() : initializer->firstSourceLocation()); }
+
+ SourceLocation lastSourceLocation() const override
+ { return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : identifierToken); }
+
+ ExpressionNode *destructuringTarget() const { return bindingTarget; }
+ Pattern *destructuringPattern() const { return bindingTarget ? bindingTarget->patternCast() : nullptr; }
+ PatternElementList *elementList() const { ArrayPattern *a = cast<ArrayPattern *>(bindingTarget); return a ? a->elements : nullptr; }
+ PatternPropertyList *propertyList() const { ObjectPattern *o = cast<ObjectPattern *>(bindingTarget); return o ? o->properties : nullptr; }
+
+ bool isVariableDeclaration() const { return scope != VariableScope::NoScope; }
+ bool isLexicallyScoped() const { return scope == VariableScope::Let || scope == VariableScope::Const; }
+
+ virtual void boundNames(QStringList *names);
+
// attributes
- PropertyName *name;
+ SourceLocation identifierToken;
+ QStringRef bindingIdentifier;
+ ExpressionNode *bindingTarget = nullptr;
+ ExpressionNode *initializer = nullptr;
+ Type type = Literal;
+ // when used in a VariableDeclarationList
+ VariableScope scope = VariableScope::NoScope;
};
-class QML_PARSER_EXPORT PropertyAssignmentList: public Node
+class QML_PARSER_EXPORT PatternElementList : public Node
{
public:
- QQMLJS_DECLARE_AST_NODE(PropertyAssignmentList)
+ QQMLJS_DECLARE_AST_NODE(PatternElementList)
- PropertyAssignmentList(PropertyAssignment *assignment)
- : assignment(assignment)
- , next(this)
+ PatternElementList(Elision *elision, PatternElement *element)
+ : elision(elision), element(element), next(this)
{ kind = K; }
- PropertyAssignmentList(PropertyAssignmentList *previous, PropertyAssignment *assignment)
- : assignment(assignment)
- {
- kind = K;
- next = previous->next;
- previous->next = this;
+ PatternElementList *append(PatternElementList *n) {
+ n->next = next;
+ next = n;
+ return n;
}
- inline PropertyAssignmentList *finish ()
+ inline PatternElementList *finish ()
{
- PropertyAssignmentList *front = next;
- next = nullptr;
+ PatternElementList *front = next;
+ next = 0;
return front;
}
void accept0(Visitor *visitor) override;
+ void boundNames(QStringList *names);
+
SourceLocation firstSourceLocation() const override
- { return assignment->firstSourceLocation(); }
+ { return elision ? elision->firstSourceLocation() : element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : assignment->lastSourceLocation(); }
+ { return next ? next->lastSourceLocation() : (element ? element->lastSourceLocation() : elision->lastSourceLocation()); }
-// attributes
- PropertyAssignment *assignment;
- PropertyAssignmentList *next;
- SourceLocation commaToken;
+ Elision *elision = nullptr;
+ PatternElement *element = nullptr;
+ PatternElementList *next;
};
-class QML_PARSER_EXPORT PropertyNameAndValue: public PropertyAssignment
+class QML_PARSER_EXPORT PatternProperty : public PatternElement
{
public:
- QQMLJS_DECLARE_AST_NODE(PropertyNameAndValue)
+ QQMLJS_DECLARE_AST_NODE(PatternProperty)
+
+ PatternProperty(PropertyName *name, ExpressionNode *i = nullptr, Type t = Literal)
+ : PatternElement(i, t), name(name)
+ { kind = K; }
- PropertyNameAndValue(PropertyName *n, ExpressionNode *v)
- : PropertyAssignment(n), value(v)
+ PatternProperty(PropertyName *name, const QStringRef &n, ExpressionNode *i = nullptr)
+ : PatternElement(n, i), name(name)
+ { kind = K; }
+
+ PatternProperty(PropertyName *name, Pattern *pattern, ExpressionNode *i = nullptr)
+ : PatternElement(pattern, i), name(name)
{ kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return name->firstSourceLocation(); }
-
SourceLocation lastSourceLocation() const override
- { return value->lastSourceLocation(); }
+ {
+ SourceLocation loc = PatternElement::lastSourceLocation();
+ return loc.isValid() ? loc : name->lastSourceLocation();
+ }
+
+ void boundNames(QStringList *names) override;
+ bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) override;
// attributes
+ PropertyName *name;
SourceLocation colonToken;
- ExpressionNode *value;
- SourceLocation commaToken;
};
-class QML_PARSER_EXPORT PropertyGetterSetter: public PropertyAssignment
+
+class QML_PARSER_EXPORT PatternPropertyList : public Node
{
public:
- QQMLJS_DECLARE_AST_NODE(PropertyGetterSetter)
-
- enum Type {
- Getter,
- Setter
- };
+ QQMLJS_DECLARE_AST_NODE(PatternPropertyList)
- PropertyGetterSetter(PropertyName *n, FunctionBody *b)
- : PropertyAssignment(n), type(Getter), formals(nullptr), functionBody (b)
+ PatternPropertyList(PatternProperty *property)
+ : property(property), next(this)
{ kind = K; }
- PropertyGetterSetter(PropertyName *n, FormalParameterList *f, FunctionBody *b)
- : PropertyAssignment(n), type(Setter), formals(f), functionBody (b)
- { kind = K; }
+ PatternPropertyList(PatternPropertyList *previous, PatternProperty *property)
+ : property(property), next(this)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
void accept0(Visitor *visitor) override;
+ void boundNames(QStringList *names);
+
+ inline PatternPropertyList *finish ()
+ {
+ PatternPropertyList *front = next;
+ next = 0;
+ return front;
+ }
+
SourceLocation firstSourceLocation() const override
- { return getSetToken; }
+ { return property->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return rbraceToken; }
+ { return next ? next->lastSourceLocation() : property->lastSourceLocation(); }
-// attributes
- Type type;
- SourceLocation getSetToken;
- SourceLocation lparenToken;
- FormalParameterList *formals;
- SourceLocation rparenToken;
- SourceLocation lbraceToken;
- FunctionBody *functionBody;
- SourceLocation rbraceToken;
+ PatternProperty *property;
+ PatternPropertyList *next;
};
-class QML_PARSER_EXPORT IdentifierPropertyName: public PropertyName
+class QML_PARSER_EXPORT IdentifierPropertyName : public PropertyName
{
public:
QQMLJS_DECLARE_AST_NODE(IdentifierPropertyName)
@@ -766,7 +876,31 @@ public:
double id;
};
-class QML_PARSER_EXPORT ArrayMemberExpression: public ExpressionNode
+class QML_PARSER_EXPORT ComputedPropertyName : public PropertyName
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(ComputedPropertyName)
+
+ ComputedPropertyName(ExpressionNode *expression)
+ : expression(expression)
+ { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ QString asString() const override { return QString(); }
+
+ SourceLocation firstSourceLocation() const override
+ { return expression->firstSourceLocation(); }
+
+ SourceLocation lastSourceLocation() const override
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+};
+
+
+class QML_PARSER_EXPORT ArrayMemberExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(ArrayMemberExpression)
@@ -790,7 +924,7 @@ public:
SourceLocation rbracketToken;
};
-class QML_PARSER_EXPORT FieldMemberExpression: public ExpressionNode
+class QML_PARSER_EXPORT FieldMemberExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(FieldMemberExpression)
@@ -814,7 +948,29 @@ public:
SourceLocation identifierToken;
};
-class QML_PARSER_EXPORT NewMemberExpression: public ExpressionNode
+class QML_PARSER_EXPORT TaggedTemplate : public LeftHandSideExpression
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(TaggedTemplate)
+
+ TaggedTemplate(ExpressionNode *b, TemplateLiteral *t)
+ : base (b), templateLiteral(t)
+ { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return base->firstSourceLocation(); }
+
+ SourceLocation lastSourceLocation() const override
+ { return templateLiteral->lastSourceLocation(); }
+
+ // attributes
+ ExpressionNode *base;
+ TemplateLiteral *templateLiteral;
+};
+
+class QML_PARSER_EXPORT NewMemberExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(NewMemberExpression)
@@ -839,7 +995,7 @@ public:
SourceLocation rparenToken;
};
-class QML_PARSER_EXPORT NewExpression: public ExpressionNode
+class QML_PARSER_EXPORT NewExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(NewExpression)
@@ -860,7 +1016,7 @@ public:
SourceLocation newToken;
};
-class QML_PARSER_EXPORT CallExpression: public ExpressionNode
+class QML_PARSER_EXPORT CallExpression: public LeftHandSideExpression
{
public:
QQMLJS_DECLARE_AST_NODE(CallExpression)
@@ -924,6 +1080,7 @@ public:
ExpressionNode *expression;
ArgumentList *next;
SourceLocation commaToken;
+ bool isSpreadElement = false;
};
class QML_PARSER_EXPORT PostIncrementExpression: public ExpressionNode
@@ -1257,16 +1414,15 @@ class QML_PARSER_EXPORT StatementList: public Node
public:
QQMLJS_DECLARE_AST_NODE(StatementList)
- StatementList(Statement *stmt):
- statement (stmt), next (this)
- { kind = K; }
+ // ### This should be a Statement, but FunctionDeclaration currently doesn't inherit it.
+ StatementList(Node *stmt)
+ : statement(stmt), next (this)
+ { kind = K; }
- StatementList(StatementList *previous, Statement *stmt):
- statement (stmt)
- {
- kind = K;
- next = previous->next;
- previous->next = this;
+ StatementList *append(StatementList *n) {
+ n->next = next;
+ next = n;
+ return n;
}
void accept0(Visitor *visitor) override;
@@ -1285,76 +1441,21 @@ public:
}
// attributes
- Statement *statement;
+ Node *statement = nullptr;
StatementList *next;
};
-class QML_PARSER_EXPORT VariableStatement: public Statement
-{
-public:
- QQMLJS_DECLARE_AST_NODE(VariableStatement)
-
- VariableStatement(VariableDeclarationList *vlist):
- declarations (vlist)
- { kind = K; }
-
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return declarationKindToken; }
-
- SourceLocation lastSourceLocation() const override
- { return semicolonToken; }
-
-// attributes
- VariableDeclarationList *declarations;
- SourceLocation declarationKindToken;
- SourceLocation semicolonToken;
-};
-
-class QML_PARSER_EXPORT VariableDeclaration: public Node
-{
-public:
- QQMLJS_DECLARE_AST_NODE(VariableDeclaration)
-
- enum VariableScope {
- FunctionScope,
- BlockScope, // let
- ReadOnlyBlockScope // const
- };
-
- VariableDeclaration(const QStringRef &n, ExpressionNode *e, VariableScope s):
- name (n), expression (e), scope(s)
- { kind = K; }
-
- bool isLexicallyScoped() const { return scope != FunctionScope; }
-
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return identifierToken; }
-
- SourceLocation lastSourceLocation() const override
- { return expression ? expression->lastSourceLocation() : identifierToken; }
-
-// attributes
- QStringRef name;
- ExpressionNode *expression;
- SourceLocation identifierToken;
- VariableScope scope;
-};
-
class QML_PARSER_EXPORT VariableDeclarationList: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(VariableDeclarationList)
- VariableDeclarationList(VariableDeclaration *decl):
- declaration (decl), next (this)
- { kind = K; }
+ VariableDeclarationList(PatternElement *decl)
+ : declaration(decl), next(this)
+ { kind = K; }
- VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl):
- declaration (decl)
+ VariableDeclarationList(VariableDeclarationList *previous, PatternElement *decl)
+ : declaration(decl)
{
kind = K;
next = previous->next;
@@ -1373,7 +1474,7 @@ public:
return declaration->lastSourceLocation();
}
- inline VariableDeclarationList *finish(VariableDeclaration::VariableScope s)
+ inline VariableDeclarationList *finish(VariableScope s)
{
VariableDeclarationList *front = next;
next = nullptr;
@@ -1385,11 +1486,33 @@ public:
}
// attributes
- VariableDeclaration *declaration;
+ PatternElement *declaration;
VariableDeclarationList *next;
SourceLocation commaToken;
};
+class QML_PARSER_EXPORT VariableStatement: public Statement
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(VariableStatement)
+
+ VariableStatement(VariableDeclarationList *vlist):
+ declarations (vlist)
+ { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return declarationKindToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return declarations->lastSourceLocation(); }
+
+// attributes
+ VariableDeclarationList *declarations;
+ SourceLocation declarationKindToken;
+};
+
class QML_PARSER_EXPORT EmptyStatement: public Statement
{
public:
@@ -1423,7 +1546,7 @@ public:
{ return expression->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return semicolonToken; }
+ { return expression->lastSourceLocation(); }
// attributes
ExpressionNode *expression;
@@ -1523,35 +1646,11 @@ public:
initialiser (i), condition (c), expression (e), statement (stmt)
{ kind = K; }
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return forToken; }
-
- SourceLocation lastSourceLocation() const override
- { return statement->lastSourceLocation(); }
-
-// attributes
- ExpressionNode *initialiser;
- ExpressionNode *condition;
- ExpressionNode *expression;
- Statement *statement;
- SourceLocation forToken;
- SourceLocation lparenToken;
- SourceLocation firstSemicolonToken;
- SourceLocation secondSemicolonToken;
- SourceLocation rparenToken;
-};
-
-class QML_PARSER_EXPORT LocalForStatement: public Statement
-{
-public:
- QQMLJS_DECLARE_AST_NODE(LocalForStatement)
-
- LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ ForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
declarations (vlist), condition (c), expression (e), statement (stmt)
{ kind = K; }
+
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
@@ -1561,26 +1660,34 @@ public:
{ return statement->lastSourceLocation(); }
// attributes
- VariableDeclarationList *declarations;
+ ExpressionNode *initialiser = nullptr;
+ VariableDeclarationList *declarations = nullptr;
ExpressionNode *condition;
ExpressionNode *expression;
Statement *statement;
SourceLocation forToken;
SourceLocation lparenToken;
- SourceLocation varToken;
SourceLocation firstSemicolonToken;
SourceLocation secondSemicolonToken;
SourceLocation rparenToken;
};
+enum class ForEachType {
+ In,
+ Of
+};
+
class QML_PARSER_EXPORT ForEachStatement: public Statement
{
public:
QQMLJS_DECLARE_AST_NODE(ForEachStatement)
- ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt):
- initialiser (i), expression (e), statement (stmt)
- { kind = K; }
+ ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt)
+ : lhs(i), expression(e), statement(stmt)
+ { kind = K; }
+ ForEachStatement(PatternElement *v, ExpressionNode *e, Statement *stmt)
+ : lhs(v), expression(e), statement(stmt)
+ { kind = K; }
void accept0(Visitor *visitor) override;
@@ -1590,42 +1697,19 @@ public:
SourceLocation lastSourceLocation() const override
{ return statement->lastSourceLocation(); }
-// attributes
- ExpressionNode *initialiser;
- ExpressionNode *expression;
- Statement *statement;
- SourceLocation forToken;
- SourceLocation lparenToken;
- SourceLocation inToken;
- SourceLocation rparenToken;
-};
-
-class QML_PARSER_EXPORT LocalForEachStatement: public Statement
-{
-public:
- QQMLJS_DECLARE_AST_NODE(LocalForEachStatement)
-
- LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt):
- declaration (v), expression (e), statement (stmt)
- { kind = K; }
-
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return forToken; }
-
- SourceLocation lastSourceLocation() const override
- { return statement->lastSourceLocation(); }
+ PatternElement *declaration() const {
+ return AST::cast<PatternElement *>(lhs);
+ }
// attributes
- VariableDeclaration *declaration;
+ Node *lhs;
ExpressionNode *expression;
Statement *statement;
SourceLocation forToken;
SourceLocation lparenToken;
- SourceLocation varToken;
- SourceLocation inToken;
+ SourceLocation inOfToken;
SourceLocation rparenToken;
+ ForEachType type;
};
class QML_PARSER_EXPORT ContinueStatement: public Statement
@@ -1696,6 +1780,28 @@ public:
SourceLocation semicolonToken;
};
+class QML_PARSER_EXPORT YieldExpression: public ExpressionNode
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(YieldExpression)
+
+ YieldExpression(ExpressionNode *e = nullptr):
+ expression (e) { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return yieldToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return expression ? expression->lastSourceLocation() : yieldToken; }
+
+// attributes
+ ExpressionNode *expression;
+ bool isYieldStar = false;
+ SourceLocation yieldToken;
+};
+
class QML_PARSER_EXPORT WithStatement: public Statement
{
public:
@@ -1906,9 +2012,9 @@ class QML_PARSER_EXPORT Catch: public Node
public:
QQMLJS_DECLARE_AST_NODE(Catch)
- Catch(const QStringRef &n, Block *stmt):
- name (n), statement (stmt)
- { kind = K; }
+ Catch(PatternElement *p, Block *stmt)
+ : patternElement(p), statement(stmt)
+ { kind = K; }
void accept0(Visitor *visitor) override;
@@ -1919,7 +2025,7 @@ public:
{ return statement->lastSourceLocation(); }
// attributes
- QStringRef name;
+ PatternElement *patternElement;
Block *statement;
SourceLocation catchToken;
SourceLocation lparenToken;
@@ -1993,7 +2099,7 @@ class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode
public:
QQMLJS_DECLARE_AST_NODE(FunctionExpression)
- FunctionExpression(const QStringRef &n, FormalParameterList *f, FunctionBody *b):
+ FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b):
name (n), formals (f), body (b)
{ kind = K; }
@@ -2005,10 +2111,14 @@ public:
SourceLocation lastSourceLocation() const override
{ return rbraceToken; }
+ FunctionExpression *asFunctionDefinition() override;
+
// attributes
QStringRef name;
+ bool isArrowFunction = false;
+ bool isGenerator = false;
FormalParameterList *formals;
- FunctionBody *body;
+ StatementList *body;
SourceLocation functionToken;
SourceLocation identifierToken;
SourceLocation lparenToken;
@@ -2022,7 +2132,7 @@ class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression
public:
QQMLJS_DECLARE_AST_NODE(FunctionDeclaration)
- FunctionDeclaration(const QStringRef &n, FormalParameterList *f, FunctionBody *b):
+ FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b):
FunctionExpression(n, f, b)
{ kind = K; }
@@ -2034,65 +2144,68 @@ class QML_PARSER_EXPORT FormalParameterList: public Node
public:
QQMLJS_DECLARE_AST_NODE(FormalParameterList)
- FormalParameterList(const QStringRef &n):
- name (n), next (this)
- { kind = K; }
-
- FormalParameterList(FormalParameterList *previous, const QStringRef &n):
- name (n)
+ FormalParameterList(FormalParameterList *previous, PatternElement *e)
+ : element(e)
{
kind = K;
- next = previous->next;
- previous->next = this;
+ if (previous) {
+ next = previous->next;
+ previous->next = this;
+ } else {
+ next = this;
+ }
}
- void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return identifierToken; }
-
- SourceLocation lastSourceLocation() const override
- { return next ? next->lastSourceLocation() : identifierToken; }
+ FormalParameterList *append(FormalParameterList *n) {
+ n->next = next;
+ next = n;
+ return n;
+ }
- inline FormalParameterList *finish ()
+ bool isSimpleParameterList()
{
- FormalParameterList *front = next;
- next = nullptr;
- return front;
+ AST::FormalParameterList *formals = this;
+ while (formals) {
+ PatternElement *e = formals->element;
+ if (e && e->type == PatternElement::RestElement)
+ return false;
+ if (e && (e->initializer || e->bindingTarget))
+ return false;
+ formals = formals->next;
+ }
+ return true;
}
-// attributes
- QStringRef name;
- FormalParameterList *next;
- SourceLocation commaToken;
- SourceLocation identifierToken;
-};
-
-class QML_PARSER_EXPORT SourceElement: public Node
-{
-public:
- QQMLJS_DECLARE_AST_NODE(SourceElement)
-
- inline SourceElement()
- { kind = K; }
-};
+ int length()
+ {
+ // the length property of Function objects
+ int l = 0;
+ AST::FormalParameterList *formals = this;
+ while (formals) {
+ PatternElement *e = formals->element;
+ if (!e || e->initializer)
+ break;
+ if (e->type == PatternElement::RestElement)
+ break;
+ ++l;
+ formals = formals->next;
+ }
+ return l;
+ }
-class QML_PARSER_EXPORT SourceElements: public Node
-{
-public:
- QQMLJS_DECLARE_AST_NODE(SourceElements)
+ bool containsName(const QString &name) const {
+ for (const FormalParameterList *it = this; it; it = it->next) {
+ PatternElement *b = it->element;
+ // ### handle binding patterns
+ if (b && b->bindingIdentifier == name)
+ return true;
+ }
+ return false;
+ }
- SourceElements(SourceElement *elt):
- element (elt), next (this)
- { kind = K; }
+ QStringList formals() const;
- SourceElements(SourceElements *previous, SourceElement *elt):
- element (elt)
- {
- kind = K;
- next = previous->next;
- previous->next = this;
- }
+ QStringList boundNames() const;
void accept0(Visitor *visitor) override;
@@ -2102,100 +2215,111 @@ public:
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : element->lastSourceLocation(); }
- inline SourceElements *finish ()
- {
- SourceElements *front = next;
- next = nullptr;
- return front;
- }
+ FormalParameterList *finish(MemoryPool *pool);
// attributes
- SourceElement *element;
- SourceElements *next;
+ PatternElement *element = nullptr;
+ FormalParameterList *next;
};
-class QML_PARSER_EXPORT FunctionBody: public Node
+class QML_PARSER_EXPORT ClassExpression : public ExpressionNode
{
public:
- QQMLJS_DECLARE_AST_NODE(FunctionBody)
+ QQMLJS_DECLARE_AST_NODE(ClassExpression)
- FunctionBody(SourceElements *elts):
- elements (elts)
+ ClassExpression(const QStringRef &n, ExpressionNode *heritage, ClassElementList *elements)
+ : name(n), heritage(heritage), elements(elements)
{ kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
- { return elements ? elements->firstSourceLocation() : SourceLocation(); }
+ { return classToken; }
SourceLocation lastSourceLocation() const override
- { return elements ? elements->lastSourceLocation() : SourceLocation(); }
+ { return rbraceToken; }
+
+ ClassExpression *asClassDefinition() override;
// attributes
- SourceElements *elements;
+ QStringRef name;
+ ExpressionNode *heritage;
+ ClassElementList *elements;
+ SourceLocation classToken;
+ SourceLocation identifierToken;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
};
-class QML_PARSER_EXPORT Program: public Node
+class QML_PARSER_EXPORT ClassDeclaration: public ClassExpression
{
public:
- QQMLJS_DECLARE_AST_NODE(Program)
+ QQMLJS_DECLARE_AST_NODE(ClassDeclaration)
- Program(SourceElements *elts):
- elements (elts)
+ ClassDeclaration(const QStringRef &n, ExpressionNode *heritage, ClassElementList *elements)
+ : ClassExpression(n, heritage, elements)
{ kind = K; }
void accept0(Visitor *visitor) override;
-
- SourceLocation firstSourceLocation() const override
- { return elements ? elements->firstSourceLocation() : SourceLocation(); }
-
- SourceLocation lastSourceLocation() const override
- { return elements ? elements->lastSourceLocation() : SourceLocation(); }
-
-// attributes
- SourceElements *elements;
};
-class QML_PARSER_EXPORT FunctionSourceElement: public SourceElement
+
+class QML_PARSER_EXPORT ClassElementList : public Node
{
public:
- QQMLJS_DECLARE_AST_NODE(FunctionSourceElement)
+ QQMLJS_DECLARE_AST_NODE(ClassElementList)
- FunctionSourceElement(FunctionDeclaration *f):
- declaration (f)
- { kind = K; }
+ ClassElementList(PatternProperty *property, bool isStatic)
+ : isStatic(isStatic), property(property)
+ {
+ kind = K;
+ next = this;
+ }
+
+ ClassElementList *append(ClassElementList *n) {
+ n->next = next;
+ next = n;
+ return n;
+ }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
- { return declaration->firstSourceLocation(); }
+ { return property->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return declaration->lastSourceLocation(); }
+ {
+ if (next)
+ return next->lastSourceLocation();
+ return property->lastSourceLocation();
+ }
-// attributes
- FunctionDeclaration *declaration;
+ ClassElementList *finish();
+
+ bool isStatic;
+ ClassElementList *next;
+ PatternProperty *property;
};
-class QML_PARSER_EXPORT StatementSourceElement: public SourceElement
+class QML_PARSER_EXPORT Program: public Node
{
public:
- QQMLJS_DECLARE_AST_NODE(StatementSourceElement)
+ QQMLJS_DECLARE_AST_NODE(Program)
- StatementSourceElement(Statement *stmt):
- statement (stmt)
- { kind = K; }
+ Program(StatementList *statements)
+ : statements(statements)
+ { kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
- { return statement->firstSourceLocation(); }
+ { return statements ? statements->firstSourceLocation() : SourceLocation(); }
SourceLocation lastSourceLocation() const override
- { return statement->lastSourceLocation(); }
+ { return statements ? statements->lastSourceLocation() : SourceLocation(); }
// attributes
- Statement *statement;
+ StatementList *statements;
};
class QML_PARSER_EXPORT DebuggerStatement: public Statement
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index 140a757e51..406a06c6db 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -89,22 +89,27 @@ class IdentifierExpression;
class NullExpression;
class TrueLiteral;
class FalseLiteral;
+class SuperLiteral;
class NumericLiteral;
class StringLiteral;
+class TemplateLiteral;
class RegExpLiteral;
-class ArrayLiteral;
-class ObjectLiteral;
-class ElementList;
+class Pattern;
+class ArrayPattern;
+class ObjectPattern;
+class PatternElement;
+class PatternElementList;
+class PatternProperty;
+class PatternPropertyList;
class Elision;
-class PropertyAssignmentList;
-class PropertyGetterSetter;
-class PropertyNameAndValue;
class PropertyName;
class IdentifierPropertyName;
class StringLiteralPropertyName;
class NumericLiteralPropertyName;
+class ComputedPropertyName;
class ArrayMemberExpression;
class FieldMemberExpression;
+class TaggedTemplate;
class NewMemberExpression;
class NewExpression;
class CallExpression;
@@ -123,20 +128,19 @@ class NotExpression;
class BinaryExpression;
class ConditionalExpression;
class Expression; // ### rename
+class YieldExpression;
class Block;
+class LeftHandSideExpression;
class StatementList;
class VariableStatement;
class VariableDeclarationList;
-class VariableDeclaration;
class EmptyStatement;
class ExpressionStatement;
class IfStatement;
class DoWhileStatement;
class WhileStatement;
class ForStatement;
-class LocalForStatement;
class ForEachStatement;
-class LocalForEachStatement;
class ContinueStatement;
class BreakStatement;
class ReturnStatement;
@@ -154,14 +158,12 @@ class Finally;
class FunctionDeclaration;
class FunctionExpression;
class FormalParameterList;
-class FunctionBody;
class Program;
-class SourceElements;
-class SourceElement;
-class FunctionSourceElement;
-class StatementSourceElement;
class DebuggerStatement;
class NestedExpression;
+class ClassExpression;
+class ClassDeclaration;
+class ClassElementList;
// ui elements
class UiProgram;
diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h
index 13218f0e98..6e1fed9dbb 100644
--- a/src/qml/parser/qqmljsastvisitor_p.h
+++ b/src/qml/parser/qqmljsastvisitor_p.h
@@ -122,35 +122,41 @@ public:
virtual bool visit(FalseLiteral *) { return true; }
virtual void endVisit(FalseLiteral *) {}
+ virtual bool visit(SuperLiteral *) { return true; }
+ virtual void endVisit(SuperLiteral *) {}
+
virtual bool visit(StringLiteral *) { return true; }
virtual void endVisit(StringLiteral *) {}
+ virtual bool visit(TemplateLiteral *) { return true; }
+ virtual void endVisit(TemplateLiteral *) {}
+
virtual bool visit(NumericLiteral *) { return true; }
virtual void endVisit(NumericLiteral *) {}
virtual bool visit(RegExpLiteral *) { return true; }
virtual void endVisit(RegExpLiteral *) {}
- virtual bool visit(ArrayLiteral *) { return true; }
- virtual void endVisit(ArrayLiteral *) {}
+ virtual bool visit(ArrayPattern *) { return true; }
+ virtual void endVisit(ArrayPattern *) {}
- virtual bool visit(ObjectLiteral *) { return true; }
- virtual void endVisit(ObjectLiteral *) {}
+ virtual bool visit(ObjectPattern *) { return true; }
+ virtual void endVisit(ObjectPattern *) {}
- virtual bool visit(ElementList *) { return true; }
- virtual void endVisit(ElementList *) {}
+ virtual bool visit(PatternElementList *) { return true; }
+ virtual void endVisit(PatternElementList *) {}
- virtual bool visit(Elision *) { return true; }
- virtual void endVisit(Elision *) {}
+ virtual bool visit(PatternPropertyList *) { return true; }
+ virtual void endVisit(PatternPropertyList *) {}
- virtual bool visit(PropertyAssignmentList *) { return true; }
- virtual void endVisit(PropertyAssignmentList *) {}
+ virtual bool visit(PatternElement *) { return true; }
+ virtual void endVisit(PatternElement *) {}
- virtual bool visit(PropertyNameAndValue *) { return true; }
- virtual void endVisit(PropertyNameAndValue *) {}
+ virtual bool visit(PatternProperty *) { return true; }
+ virtual void endVisit(PatternProperty *) {}
- virtual bool visit(PropertyGetterSetter *) { return true; }
- virtual void endVisit(PropertyGetterSetter *) {}
+ virtual bool visit(Elision *) { return true; }
+ virtual void endVisit(Elision *) {}
virtual bool visit(NestedExpression *) { return true; }
virtual void endVisit(NestedExpression *) {}
@@ -164,12 +170,18 @@ public:
virtual bool visit(NumericLiteralPropertyName *) { return true; }
virtual void endVisit(NumericLiteralPropertyName *) {}
+ virtual bool visit(ComputedPropertyName *) { return true; }
+ virtual void endVisit(ComputedPropertyName *) {}
+
virtual bool visit(ArrayMemberExpression *) { return true; }
virtual void endVisit(ArrayMemberExpression *) {}
virtual bool visit(FieldMemberExpression *) { return true; }
virtual void endVisit(FieldMemberExpression *) {}
+ virtual bool visit(TaggedTemplate *) { return true; }
+ virtual void endVisit(TaggedTemplate *) {}
+
virtual bool visit(NewMemberExpression *) { return true; }
virtual void endVisit(NewMemberExpression *) {}
@@ -236,9 +248,6 @@ public:
virtual bool visit(VariableDeclarationList *) { return true; }
virtual void endVisit(VariableDeclarationList *) {}
- virtual bool visit(VariableDeclaration *) { return true; }
- virtual void endVisit(VariableDeclaration *) {}
-
virtual bool visit(EmptyStatement *) { return true; }
virtual void endVisit(EmptyStatement *) {}
@@ -257,15 +266,9 @@ public:
virtual bool visit(ForStatement *) { return true; }
virtual void endVisit(ForStatement *) {}
- virtual bool visit(LocalForStatement *) { return true; }
- virtual void endVisit(LocalForStatement *) {}
-
virtual bool visit(ForEachStatement *) { return true; }
virtual void endVisit(ForEachStatement *) {}
- virtual bool visit(LocalForEachStatement *) { return true; }
- virtual void endVisit(LocalForEachStatement *) {}
-
virtual bool visit(ContinueStatement *) { return true; }
virtual void endVisit(ContinueStatement *) {}
@@ -275,6 +278,9 @@ public:
virtual bool visit(ReturnStatement *) { return true; }
virtual void endVisit(ReturnStatement *) {}
+ virtual bool visit(YieldExpression *) { return true; }
+ virtual void endVisit(YieldExpression *) {}
+
virtual bool visit(WithStatement *) { return true; }
virtual void endVisit(WithStatement *) {}
@@ -317,20 +323,17 @@ public:
virtual bool visit(FormalParameterList *) { return true; }
virtual void endVisit(FormalParameterList *) {}
- virtual bool visit(FunctionBody *) { return true; }
- virtual void endVisit(FunctionBody *) {}
-
- virtual bool visit(Program *) { return true; }
- virtual void endVisit(Program *) {}
+ virtual bool visit(ClassExpression *) { return true; }
+ virtual void endVisit(ClassExpression *) {}
- virtual bool visit(SourceElements *) { return true; }
- virtual void endVisit(SourceElements *) {}
+ virtual bool visit(ClassDeclaration *) { return true; }
+ virtual void endVisit(ClassDeclaration *) {}
- virtual bool visit(FunctionSourceElement *) { return true; }
- virtual void endVisit(FunctionSourceElement *) {}
+ virtual bool visit(ClassElementList *) { return true; }
+ virtual void endVisit(ClassElementList *) {}
- virtual bool visit(StatementSourceElement *) { return true; }
- virtual void endVisit(StatementSourceElement *) {}
+ virtual bool visit(Program *) { return true; }
+ virtual void endVisit(Program *) {}
virtual bool visit(DebuggerStatement *) { return true; }
virtual void endVisit(DebuggerStatement *) {}
diff --git a/src/qml/parser/qqmljsengine_p.cpp b/src/qml/parser/qqmljsengine_p.cpp
index b4f0debf85..97ce6ebea3 100644
--- a/src/qml/parser/qqmljsengine_p.cpp
+++ b/src/qml/parser/qqmljsengine_p.cpp
@@ -112,13 +112,6 @@ double integerFromString(const char *buf, int size, int radix)
return result;
}
-double integerFromString(const QString &str, int radix)
-{
- QByteArray ba = QStringRef(&str).trimmed().toLatin1();
- return integerFromString(ba.constData(), ba.size(), radix);
-}
-
-
Engine::Engine()
: _lexer(nullptr), _directives(nullptr)
{ }
diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h
index af26bac0ff..1de907d296 100644
--- a/src/qml/parser/qqmljsengine_p.h
+++ b/src/qml/parser/qqmljsengine_p.h
@@ -63,9 +63,35 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS {
class Lexer;
-class Directives;
class MemoryPool;
+class QML_PARSER_EXPORT Directives {
+public:
+ virtual ~Directives() {}
+
+ virtual void pragmaLibrary()
+ {
+ }
+
+ virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
+ {
+ Q_UNUSED(jsfile);
+ Q_UNUSED(module);
+ Q_UNUSED(line);
+ Q_UNUSED(column);
+ }
+
+ virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column)
+ {
+ Q_UNUSED(uri);
+ Q_UNUSED(version);
+ Q_UNUSED(module);
+ Q_UNUSED(line);
+ Q_UNUSED(column);
+ }
+};
+
+
class QML_PARSER_EXPORT DiagnosticMessage
{
public:
diff --git a/src/qml/parser/qqmljsgrammar.cpp b/src/qml/parser/qqmljsgrammar.cpp
deleted file mode 100644
index 2aaeb385e3..0000000000
--- a/src/qml/parser/qqmljsgrammar.cpp
+++ /dev/null
@@ -1,1167 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// This file was generated by qlalr - DO NOT EDIT!
-#include "qqmljsgrammar_p.h"
-
-QT_BEGIN_NAMESPACE
-
-const char *const QQmlJSGrammar::spell [] = {
- "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue",
- "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
- "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
- "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
- "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
- "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
- ")", ";", nullptr, "*", "*=", "string literal", "property", "signal", "readonly", "switch",
- "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^",
- "^=", "null", "true", "false", "const", "let", "debugger", "reserved word", "multiline string literal", "comment",
- nullptr, "enum", "public", "import", "pragma", "as", "on", "get", "set", nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
-};
-
-const short QQmlJSGrammar::lhs [] = {
- 108, 108, 108, 108, 108, 108, 109, 115, 115, 118,
- 118, 118, 118, 121, 123, 119, 119, 120, 120, 120,
- 120, 120, 120, 120, 120, 124, 125, 117, 116, 128,
- 128, 129, 129, 130, 130, 127, 113, 113, 113, 113,
- 132, 132, 132, 132, 132, 132, 132, 113, 140, 140,
- 140, 140, 141, 141, 142, 142, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 145, 145, 145,
- 145, 126, 126, 126, 126, 126, 126, 126, 146, 146,
- 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
- 146, 146, 146, 146, 146, 146, 131, 148, 148, 148,
- 148, 147, 147, 152, 152, 152, 150, 150, 153, 153,
- 153, 153, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 157, 157, 122, 122, 122,
- 122, 122, 160, 160, 161, 161, 161, 161, 159, 159,
- 162, 162, 163, 163, 164, 164, 164, 165, 165, 165,
- 165, 165, 165, 165, 165, 165, 165, 166, 166, 166,
- 166, 167, 167, 167, 168, 168, 168, 168, 169, 169,
- 169, 169, 169, 169, 169, 170, 170, 170, 170, 170,
- 170, 171, 171, 171, 171, 171, 172, 172, 172, 172,
- 172, 173, 173, 174, 174, 175, 175, 176, 176, 177,
- 177, 178, 178, 179, 179, 180, 180, 181, 181, 182,
- 182, 183, 183, 184, 184, 151, 151, 185, 185, 186,
- 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
- 186, 111, 111, 187, 187, 188, 188, 189, 189, 110,
- 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
- 110, 110, 110, 110, 133, 198, 198, 197, 197, 144,
- 144, 199, 199, 199, 200, 200, 202, 202, 201, 203,
- 206, 204, 204, 207, 205, 205, 134, 135, 135, 136,
- 136, 190, 190, 190, 190, 190, 190, 190, 190, 191,
- 191, 191, 191, 192, 192, 192, 192, 193, 193, 137,
- 138, 208, 208, 211, 211, 209, 209, 212, 210, 194,
- 195, 195, 139, 139, 139, 213, 214, 196, 196, 215,
- 143, 158, 158, 216, 216, 155, 155, 154, 154, 217,
- 114, 114, 218, 218, 112, 112, 149, 149, 219
-};
-
-const short QQmlJSGrammar::rhs [] = {
- 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
- 1, 2, 2, 1, 1, 2, 2, 2, 2, 3,
- 3, 5, 5, 4, 4, 2, 2, 0, 1, 1,
- 2, 1, 3, 2, 3, 2, 1, 5, 4, 4,
- 1, 1, 1, 1, 1, 1, 1, 3, 1, 1,
- 1, 3, 0, 1, 2, 4, 6, 6, 3, 3,
- 7, 7, 4, 4, 5, 5, 8, 8, 5, 6,
- 6, 10, 6, 7, 1, 1, 5, 1, 3, 3,
- 5, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 3, 4, 5, 3, 4, 3, 1, 1, 2, 3,
- 4, 1, 2, 3, 7, 8, 1, 3, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,
- 3, 5, 1, 2, 4, 4, 4, 3, 0, 1,
- 1, 3, 1, 1, 1, 2, 2, 1, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 1, 3, 3,
- 3, 1, 3, 3, 1, 3, 3, 3, 1, 3,
- 3, 3, 3, 3, 3, 1, 3, 3, 3, 3,
- 3, 1, 3, 3, 3, 3, 1, 3, 3, 3,
- 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
- 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
- 3, 1, 5, 1, 5, 1, 3, 1, 3, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 3, 0, 1, 1, 3, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 3, 1, 2, 0, 1, 3,
- 3, 1, 1, 1, 1, 3, 1, 3, 2, 2,
- 2, 0, 1, 2, 0, 1, 1, 2, 2, 7,
- 5, 7, 7, 7, 5, 9, 10, 7, 8, 2,
- 2, 3, 3, 2, 2, 3, 3, 3, 3, 5,
- 5, 3, 5, 1, 2, 0, 1, 4, 3, 3,
- 3, 3, 3, 3, 4, 5, 2, 2, 2, 1,
- 8, 8, 7, 1, 3, 0, 1, 0, 1, 1,
- 1, 1, 1, 2, 1, 1, 0, 1, 2
-};
-
-const short QQmlJSGrammar::action_default [] = {
- 0, 0, 28, 0, 0, 0, 28, 0, 195, 262,
- 226, 234, 230, 174, 246, 222, 3, 159, 90, 175,
- 238, 242, 163, 192, 173, 178, 158, 212, 199, 0,
- 97, 98, 93, 0, 87, 82, 367, 0, 0, 0,
- 0, 95, 0, 0, 91, 94, 86, 0, 0, 83,
- 85, 88, 84, 96, 89, 0, 92, 0, 0, 188,
- 0, 0, 175, 194, 177, 176, 0, 0, 0, 190,
- 191, 189, 193, 0, 223, 0, 0, 0, 0, 213,
- 0, 0, 0, 0, 0, 0, 203, 0, 0, 0,
- 197, 198, 196, 201, 205, 204, 202, 200, 215, 214,
- 216, 0, 231, 0, 227, 0, 0, 169, 156, 168,
- 157, 123, 124, 125, 151, 126, 153, 127, 128, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 138, 152,
- 139, 140, 154, 141, 142, 143, 144, 145, 146, 147,
- 148, 149, 150, 155, 0, 0, 167, 263, 170, 0,
- 171, 0, 172, 166, 0, 259, 252, 250, 257, 258,
- 256, 255, 261, 254, 253, 251, 260, 247, 0, 235,
- 0, 0, 239, 0, 0, 243, 0, 0, 169, 161,
- 0, 160, 0, 165, 179, 0, 356, 356, 357, 0,
- 354, 0, 355, 0, 358, 270, 277, 276, 284, 272,
- 0, 273, 0, 359, 0, 366, 274, 275, 90, 280,
- 278, 363, 360, 365, 281, 0, 293, 0, 0, 0,
- 0, 350, 0, 367, 292, 264, 307, 0, 0, 0,
- 294, 0, 0, 282, 283, 0, 271, 279, 308, 309,
- 0, 356, 0, 0, 358, 0, 351, 352, 0, 340,
- 364, 0, 324, 325, 326, 327, 0, 320, 321, 322,
- 323, 348, 349, 0, 0, 0, 0, 0, 312, 313,
- 314, 268, 266, 228, 236, 232, 248, 224, 269, 0,
- 175, 240, 244, 217, 206, 0, 0, 225, 0, 0,
- 0, 0, 218, 0, 0, 0, 0, 0, 210, 208,
- 211, 209, 207, 220, 219, 221, 0, 233, 0, 229,
- 0, 267, 175, 0, 249, 264, 265, 0, 264, 0,
- 0, 316, 0, 0, 0, 318, 0, 237, 0, 0,
- 241, 0, 0, 245, 305, 0, 297, 306, 300, 0,
- 304, 0, 264, 298, 0, 264, 0, 0, 317, 0,
- 0, 0, 319, 0, 0, 0, 311, 0, 310, 90,
- 117, 368, 0, 0, 122, 286, 289, 0, 123, 293,
- 126, 153, 128, 129, 93, 134, 135, 87, 136, 292,
- 139, 91, 94, 264, 88, 96, 142, 89, 144, 92,
- 146, 147, 294, 149, 150, 155, 0, 119, 118, 121,
- 105, 120, 104, 0, 114, 287, 285, 0, 0, 0,
- 358, 0, 115, 163, 164, 169, 0, 162, 0, 328,
- 329, 0, 356, 0, 0, 358, 0, 116, 0, 0,
- 0, 331, 336, 334, 337, 0, 0, 335, 336, 0,
- 332, 0, 333, 288, 339, 0, 288, 338, 0, 341,
- 342, 0, 288, 343, 344, 0, 0, 345, 0, 0,
- 0, 346, 347, 181, 180, 0, 0, 0, 315, 0,
- 0, 0, 330, 302, 295, 0, 303, 299, 0, 301,
- 290, 0, 291, 296, 0, 0, 358, 0, 353, 108,
- 0, 0, 112, 99, 0, 101, 110, 0, 102, 111,
- 113, 103, 109, 100, 0, 106, 185, 183, 187, 184,
- 182, 186, 361, 6, 362, 4, 2, 75, 107, 0,
- 0, 0, 83, 85, 84, 37, 5, 0, 76, 0,
- 51, 50, 49, 0, 0, 51, 0, 0, 0, 52,
- 0, 67, 68, 0, 65, 0, 66, 41, 42, 43,
- 44, 46, 47, 71, 45, 0, 0, 0, 78, 0,
- 77, 80, 0, 81, 0, 79, 0, 51, 0, 0,
- 0, 0, 0, 61, 0, 62, 0, 0, 32, 0,
- 0, 72, 33, 0, 36, 34, 30, 0, 35, 31,
- 0, 63, 0, 64, 163, 0, 69, 73, 0, 0,
- 0, 0, 163, 288, 0, 70, 90, 123, 293, 126,
- 153, 128, 129, 93, 134, 135, 136, 292, 139, 91,
- 94, 264, 96, 142, 89, 144, 92, 146, 147, 294,
- 149, 150, 155, 74, 0, 59, 53, 60, 54, 0,
- 0, 0, 0, 56, 0, 57, 58, 55, 0, 0,
- 0, 0, 48, 0, 38, 39, 0, 40, 8, 0,
- 0, 9, 0, 11, 0, 10, 0, 1, 27, 15,
- 14, 26, 13, 12, 29, 7, 0, 18, 0, 19,
- 0, 24, 25, 0, 20, 21, 0, 22, 23, 16,
- 17, 369
-};
-
-const short QQmlJSGrammar::goto_default [] = {
- 7, 667, 213, 200, 211, 526, 513, 662, 675, 512,
- 661, 665, 663, 671, 22, 668, 666, 664, 18, 525,
- 587, 577, 584, 579, 553, 195, 199, 201, 206, 237,
- 214, 234, 568, 639, 638, 205, 236, 557, 26, 491,
- 490, 362, 361, 9, 360, 363, 204, 484, 364, 109,
- 17, 149, 24, 13, 148, 19, 25, 59, 23, 8,
- 28, 27, 283, 15, 277, 10, 273, 12, 275, 11,
- 274, 20, 281, 21, 282, 14, 276, 272, 313, 418,
- 278, 279, 207, 197, 196, 210, 209, 233, 198, 367,
- 366, 235, 475, 474, 335, 336, 477, 338, 476, 337,
- 431, 435, 438, 434, 433, 453, 454, 202, 188, 203,
- 212, 0
-};
-
-const short QQmlJSGrammar::action_index [] = {
- 350, 1528, 3041, 3041, 2937, 1235, 115, 105, 239, -108,
- 102, 93, 95, 205, -108, 422, 110, -108, -108, 727,
- 92, 118, 265, 256, -108, -108, -108, 507, 247, 1528,
- -108, -108, -108, 665, -108, -108, 2729, 1826, 1528, 1528,
- 1528, -108, 1041, 1528, -108, -108, -108, 1528, 1528, -108,
- -108, -108, -108, -108, -108, 1528, -108, 1528, 1528, -108,
- 1528, 1528, 174, 221, -108, -108, 1528, 1528, 1528, -108,
- -108, -108, 177, 1528, 422, 1528, 1528, 1528, 1528, 411,
- 1528, 1528, 1528, 1528, 1528, 1528, 211, 1528, 1528, 1528,
- 142, 148, 154, 217, 223, 226, 227, 231, 507, 385,
- 395, 1528, 57, 1528, 83, 2521, 1528, 1528, -108, -108,
- -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
- -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
- -108, -108, -108, -108, -108, -108, -108, -108, -108, -108,
- -108, -108, -108, -108, 179, 1528, -108, -108, 77, 36,
- -108, 1528, -108, -108, 1528, -108, -108, -108, -108, -108,
- -108, -108, -108, -108, -108, -108, -108, -108, 1528, 56,
- 1528, 1528, 80, 74, 1528, -108, 2521, 1528, 1528, -108,
- 125, -108, 55, -108, -108, 53, 410, 418, 72, 52,
- -108, 392, -108, 46, 3041, -108, -108, -108, -108, -108,
- 273, -108, 396, -108, 44, -108, -108, -108, 76, -108,
- -108, -108, 3041, -108, -108, 744, -108, 589, 98, 2937,
- 91, 90, 88, 3249, -108, 1528, -108, 86, 1528, 81,
- -108, 75, 73, -108, -108, 586, -108, -108, -108, -108,
- 71, 491, 69, 65, 3041, 64, -108, -108, 2937, -108,
- -108, 139, -108, -108, -108, -108, 134, -108, -108, -108,
- -108, -108, -108, 63, 66, 1528, 147, 264, -108, -108,
- -108, 1726, -108, 87, 68, 70, -108, 334, 82, 78,
- 796, 89, 121, 349, 318, 469, 1528, 330, 1528, 1528,
- 1528, 1528, 359, 1528, 1528, 1528, 1528, 1528, 284, 289,
- 303, 306, 313, 365, 369, 375, 1528, 58, 1528, 85,
- 1528, -108, 849, 1528, -108, 1528, 79, 59, 1528, 61,
- 2937, -108, 1528, 146, 2937, -108, 1528, 62, 1528, 1528,
- 106, 99, 1528, -108, 96, 176, 171, -108, -108, 1528,
- -108, 407, 1528, -108, 97, 1528, -52, 2937, -108, 1528,
- 120, 2937, -108, 1528, 123, 2937, 101, 2937, -108, 116,
- -108, 84, 45, 0, -108, -108, 2937, -39, 641, -3,
- 652, 156, 1528, 2937, -7, -11, 567, 2625, -21, 5,
- 945, 2, 94, 1629, 2625, -1, -26, 6, 1528, 10,
- -15, 1528, 14, 1528, -25, -12, 2833, -108, -108, -108,
- -108, -108, -108, 1528, -108, -108, -108, -14, -58, -13,
- 3041, -36, -108, 287, -108, 1528, -46, -108, 153, -108,
- -108, -31, 586, -57, -32, 3041, 11, -108, 1528, 168,
- 29, -108, 47, -108, 48, 169, 1528, -108, 49, 50,
- -108, 9, -108, 2937, -108, 136, 2937, -108, 275, -108,
- -108, 126, 2937, 35, -108, 33, 37, -108, 466, -4,
- 38, -108, -108, -108, -108, 1528, 130, 2937, -108, 1528,
- 117, 2937, -108, 34, -108, 296, -108, -108, 1528, -108,
- -108, 404, -108, -108, 12, 40, 3041, 13, -108, -108,
- 155, 1926, -108, -108, 2026, -108, -108, 2126, -108, -108,
- -108, -108, -108, -108, 144, -108, -108, -108, -108, -108,
- -108, -108, -108, -108, 3041, -108, -108, -108, 132, -27,
- 15, 1137, 218, -23, 17, -108, -108, 196, -108, 242,
- 8, -108, -108, 579, 237, -108, 127, 18, 415, -108,
- 103, -108, -108, 236, -108, 2223, -108, -108, -108, -108,
- -108, -108, -108, -108, -108, 27, 21, 137, 31, 20,
- -108, 23, -5, -108, -9, -108, 332, -10, 571, 201,
- 195, 586, 225, -108, 7, -108, 1137, 165, -108, 4,
- 1137, -108, -108, 1333, -108, -108, -108, 1431, -108, -108,
- 184, -108, 2223, -108, 331, 3, -108, -108, 202, 531,
- 26, 2417, 327, 3145, 1, -108, 25, 629, 24, 649,
- 124, 1528, 2937, 22, -6, 514, -8, 19, 1041, 16,
- 94, 1629, 28, 42, 67, 1528, 60, 43, 1528, 54,
- 1528, 41, 39, -108, 234, -108, 228, -108, 51, -2,
- 564, 233, 575, -108, 100, -108, -108, -108, 2320, 1137,
- 1826, 32, -108, 122, -108, -108, 30, -108, -108, 1137,
- 1137, 104, 903, -108, 308, -108, 108, -108, -108, 133,
- 119, -108, -108, -108, -108, -108, 451, -108, 164, -108,
- 161, -108, -108, 458, -108, -108, 151, -108, -108, -108,
- -108, -108,
-
- -112, 18, 86, 97, 69, 316, 7, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -64,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, 66,
- -112, -112, -112, -17, -112, -112, -10, -36, 3, 90,
- 95, -112, 149, 74, -112, -112, -112, 67, 13, -112,
- -112, -112, -112, -112, -112, 178, -112, 181, 185, -112,
- 189, 190, -112, -112, -112, -112, 198, 208, 212, -112,
- -112, -112, -112, 209, -112, 201, 164, 111, 113, -112,
- 116, 130, 131, 132, 134, 142, -112, 118, 124, 144,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, 154, -112, 155, -112, 268, 28, -8, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, 42, -112, -112, -112, -112,
- -112, 47, -112, -112, 50, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, 159, -112,
- 158, 56, -112, -112, 57, -112, 362, 60, 157, -112,
- -112, -112, -112, -112, -112, -112, 20, 151, -112, -112,
- -112, 25, -112, -112, 30, -112, -112, -112, -112, -112,
- -112, -112, 31, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, 233, -112, -112, 34, -112, 35, -112, 225,
- -112, 36, -112, 216, -112, 55, -112, -112, 53, 39,
- -112, -112, -112, -112, -112, 19, -112, -112, -112, -112,
- -112, 94, -112, -112, 92, -112, -112, -112, 117, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, 33, -112, -112, -112, -112,
- -112, 88, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, 51, 220, -112, 227, 235,
- 236, 244, -112, 21, 17, 102, 91, 89, -112, -112,
- -112, -112, -112, -112, -112, -112, 211, -112, 247, -112,
- 257, -112, -112, 264, -112, 75, -112, -112, 103, -112,
- 112, -112, 29, -112, 73, -112, 263, -112, 255, 254,
- -112, -112, 245, -112, -112, -112, -112, -112, -112, 248,
- -112, 65, 105, -112, -112, 99, -112, 162, -112, 37,
- -112, 115, -112, 44, -112, 135, -112, 137, -112, -112,
- -112, -112, -112, -112, -112, -112, 138, -112, 24, -112,
- 26, -112, 104, 140, -112, -112, 32, 64, -112, -112,
- 174, -112, -112, 48, 87, -112, -112, -112, 54, -112,
- 40, 71, -112, 150, -112, -112, 197, -112, -112, -112,
- -112, -112, -112, 12, -112, -112, -112, -112, -112, -112,
- 206, -112, -112, -112, -112, 207, -112, -112, -112, -112,
- -112, -112, 231, -112, -112, 239, -112, -112, 43, -112,
- -112, -112, -112, -112, -59, -112, 38, -112, -62, -112,
- -112, -112, -112, 258, -112, -112, 259, -112, -112, -112,
- -112, -112, 163, -72, -112, -112, 41, -112, 62, -112,
- 61, -112, -112, -112, -112, 59, -112, 193, -112, 58,
- -112, 204, -112, -112, -112, -112, -112, -112, 52, -112,
- -112, 175, -112, -112, -112, -112, 186, -112, -112, -112,
- -112, 49, -112, -112, 173, -112, -112, 45, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, 213, -112, -112, -112, -112, -112,
- -112, 46, -112, -112, -112, -112, -112, -112, -112, 27,
- -112, -112, -112, -18, -9, -112, -112, -112, 15, -112,
- -112, -112, -112, -112, -112, 331, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -112, -112, 11, -6,
- -112, 10, -112, -112, -112, -112, 156, -112, -112, -112,
- 240, -112, -112, 330, -112, -112, -112, 332, -112, -112,
- -112, -112, 376, -112, -112, 8, -112, -112, -7, 76,
- -112, 358, -112, 228, 5, -112, -112, 6, -112, 4,
- -112, 79, 221, -112, -112, 2, -112, -112, 174, -112,
- -112, 16, -112, -112, -112, 14, -112, -16, 70, -112,
- 63, -112, -112, -112, -112, -112, -30, -112, -112, -112,
- -15, -28, -13, -112, -112, -112, -112, -112, 460, 93,
- 307, -12, -112, -112, -112, -112, -11, -112, -112, -2,
- -1, 85, 84, -112, -112, -112, -112, -112, -112, -112,
- -112, -112, -112, -112, -112, -112, -3, -112, -112, -112,
- -112, -112, -112, 0, -112, -112, -112, -112, -112, -112,
- -112, -112
-};
-
-const short QQmlJSGrammar::action_info [] = {
- -132, 425, 409, 424, -151, 422, -120, 403, 347, -140,
- 428, 465, -152, -143, 417, 353, 406, -145, 452, 412,
- 410, -148, 408, -140, 469, 271, -152, 569, 353, -132,
- 271, -151, 248, 601, 583, -120, 583, 583, 565, 529,
- 562, 576, 563, 598, 555, 534, 634, 539, 564, 561,
- 558, 478, 436, 436, 436, 456, 460, 443, 644, 641,
- 556, -148, 432, 583, 442, 583, 427, -145, 488, 458,
- 452, 452, 485, 486, -143, 469, 452, 465, 428, 194,
- 191, 174, 168, 248, 73, 151, 286, 145, 286, 187,
- 310, 326, 396, 0, 168, 0, 153, 0, 244, 247,
- 402, -121, 265, 73, 101, 691, 332, 241, 326, 469,
- 306, 465, 193, 339, 452, 183, 306, 357, 145, 246,
- 318, 320, 428, 248, 353, 145, 186, 271, 145, 243,
- 580, 145, 455, 145, 176, 0, 103, 308, 145, 315,
- 264, 101, 537, 446, 145, 559, 456, 176, 176, 308,
- 0, 538, 145, 177, 145, 145, 0, 0, 345, 262,
- 261, 646, 645, 494, 542, 541, 177, 177, 170, 690,
- 689, 328, 171, 580, 103, 329, 145, 471, 654, 439,
- 351, 181, 60, 355, 341, 262, 261, 145, 60, 66,
- 467, 592, 560, 61, 60, 260, 259, 659, 660, 61,
- 255, 254, 349, 648, 505, 61, 324, 267, 659, 660,
- 537, 495, 688, 687, 420, 419, 64, 262, 261, 571,
- 105, 581, 682, 681, 440, 685, 684, 65, 430, 583,
- 535, 535, 574, 66, 67, 146, 87, 342, 88, 106,
- 68, 107, 87, 545, 88, 593, 591, 567, 87, 89,
- 88, 87, 87, 88, 88, 89, 87, 535, 88, 683,
- 0, 89, 535, 0, 89, 89, 535, 0, 66, 89,
- 636, 530, 87, 0, 88, 0, 532, 532, 67, 60,
- 176, 145, 0, 145, 68, 89, 575, 573, 531, 531,
- 61, 0, 649, 532, 0, 637, 635, 546, 544, 177,
- 0, 178, 176, 532, 481, 531, 0, 0, 532, 87,
- 0, 88, 532, 67, 87, 531, 88, 532, 0, 68,
- 531, 177, 89, 415, 531, 270, 268, 89, 87, 531,
- 88, 87, 0, 88, 239, 238, 450, 449, 87, 0,
- 88, 89, 176, 87, 89, 88, 176, 176, 288, 289,
- 0, 89, 288, 289, 269, 678, 89, 482, 480, 0,
- -107, 177, 0, 178, -107, 177, 177, 178, 415, 679,
- 677, 0, 293, 294, 0, 290, 291, 0, 0, 290,
- 291, 295, 293, 294, 296, 0, 297, 0, 293, 294,
- 0, 295, 293, 294, 296, 0, 297, 295, 293, 294,
- 296, 295, 297, 676, 296, 0, 297, 295, 80, 81,
- 296, 0, 297, 0, 0, 0, 82, 83, 80, 81,
- 84, 35, 85, 0, 0, 35, 82, 83, 0, 0,
- 84, 0, 85, 35, 80, 81, 35, 0, 0, 35,
- 75, 76, 82, 83, 35, 0, 84, 35, 85, 0,
- 6, 5, 4, 1, 3, 2, 0, 0, 49, 52,
- 50, 0, 49, 52, 50, 0, 0, 77, 78, 0,
- 49, 52, 50, 49, 52, 50, 49, 52, 50, 0,
- 35, 49, 52, 50, 49, 52, 50, 35, 46, 34,
- 51, 0, 46, 34, 51, 35, 0, 0, 35, 0,
- 46, 34, 51, 46, 34, 51, 46, 34, 51, 0,
- 0, 46, 34, 51, 46, 34, 51, 49, 52, 50,
- 35, 0, 0, 0, 49, 52, 50, 0, 0, 0,
- 80, 81, 49, 52, 50, 49, 52, 50, 82, 83,
- 0, 0, 84, 35, 85, 0, 537, 46, 34, 51,
- 186, 0, 0, 0, 46, 34, 51, 49, 52, 50,
- 35, 0, 46, 34, 51, 46, 34, 51, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 537,
- 49, 52, 50, 0, 0, 0, 537, 46, 34, 51,
- 537, 0, 0, 35, 537, 0, 35, 49, 52, 50,
- 35, 0, 0, 186, 35, 0, 0, 0, 35, 0,
- 46, 34, 51, 0, 0, 35, 0, 0, 35, 0,
- 0, 0, 0, 0, 0, 0, 0, 46, 34, 51,
- 49, 52, 50, 49, 52, 50, 0, 49, 52, 50,
- 0, 49, 52, 50, 0, 49, 52, 50, 0, 0,
- 258, 257, 49, 52, 50, 49, 52, 50, 35, 0,
- 46, 34, 51, 46, 34, 51, 0, 46, 34, 51,
- 35, 46, 34, 51, 0, 46, 34, 51, 35, 0,
- 0, 35, 46, 34, 51, 46, 34, 51, 0, 0,
- 253, 252, 0, 0, 35, 49, 52, 50, 0, 0,
- 0, 186, 253, 252, 0, 0, 0, 49, 52, 50,
- 258, 257, 0, 258, 257, 49, 52, 50, 49, 52,
- 50, 0, 0, 0, 0, 46, 34, 51, 0, 0,
- 155, 49, 52, 50, 0, 0, 0, 46, 34, 51,
- 156, 0, 0, 0, 157, 46, 34, 51, 46, 34,
- 51, 0, 0, 158, 0, 159, 0, 0, 0, 0,
- 0, 46, 34, 51, 0, 0, 160, 0, 161, 64,
- 0, 0, 0, 35, 0, 0, 162, 0, 0, 163,
- 65, 0, 0, 0, 0, 164, 0, 0, 0, 0,
- 0, 165, 0, 0, 0, 0, 0, 0, 0, 155,
- 0, 0, 0, 0, 0, 253, 252, 166, 0, 156,
- 49, 52, 50, 157, 0, 0, 0, 0, 0, 0,
- 0, 0, 158, 0, 159, 0, 0, 322, 0, 0,
- 0, 0, 0, 0, 0, 160, 0, 161, 64, 0,
- 46, 34, 51, 0, 0, 162, 0, 0, 163, 65,
- 0, 0, 155, 0, 164, 0, 0, 0, 0, 0,
- 165, 0, 156, 0, 0, 0, 157, 0, 0, 0,
- 0, 0, 0, 0, 0, 158, 166, 159, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 160, 0,
- 161, 64, 0, 0, 0, 0, 0, 0, 162, 0,
- 0, 163, 65, 0, 0, 0, 0, 164, 0, 0,
- 0, 0, 0, 165, 0, 30, 31, 0, 0, 0,
- 0, 0, 0, 0, 0, 33, 0, 0, 0, 166,
- 0, 0, 35, 0, 0, 0, 36, 37, 0, 38,
- 0, 0, 0, 0, 0, 0, 521, 0, 0, 0,
- 45, 0, 0, 0, 0, 0, 0, 30, 31, 0,
- 0, 0, 0, 0, 0, 0, 0, 33, 53, 49,
- 52, 50, 0, 54, 35, 0, 0, 0, 36, 37,
- 0, 38, 0, 0, 44, 56, 32, 0, 42, 0,
- 0, 41, 45, 0, 0, 0, 0, 0, 0, 46,
- 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
- 53, 49, 52, 50, 0, 54, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 44, 56, 32, 0,
- 0, 0, 0, 41, 0, 0, 0, 0, 0, 0,
- 0, 46, 34, 51, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 30, 31, 0, 0, 0, 0, 0,
- 0, 0, 0, 33, 0, 0, 0, 0, 0, 0,
- 35, 0, 0, 0, 36, 37, 0, 38, 0, 0,
- 0, 0, 0, 0, 42, 0, 0, 0, 45, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 53, 49, 52, 50,
- 0, 54, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 44, 56, 32, 0, 0, 0, 0, 41,
- 0, 0, 0, 0, 0, 0, 0, 46, 34, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,
- 31, 0, 0, 0, 0, 0, 0, 0, 0, 33,
- 0, 0, 0, 0, 0, 0, 35, 0, 0, 0,
- 36, 37, 0, 38, 0, 0, 0, 0, 0, 0,
- 521, 0, 0, 0, 45, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 53, 49, 52, 50, 0, 54, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 44, 56,
- 32, 0, 0, 0, 0, 41, 0, 0, 0, 0,
- 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 519, 0, 30, 31, 0,
- 0, 0, 0, 0, 0, 0, 0, 221, 0, 0,
- 0, 0, 0, 0, 35, 0, 0, 0, 36, 37,
- 0, 38, 0, 0, 0, 0, 0, 0, 521, 0,
- 0, 0, 45, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 53, 522, 524, 523, 0, 54, 0, 0, 0, 0,
- 230, 0, 0, 0, 0, 0, 44, 56, 32, 216,
- 224, 0, 0, 41, 0, 0, 520, 0, 0, 0,
- 0, 46, 34, 51, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 519, 0, 30, 31, 0, 0, 0,
- 0, 0, 0, 0, 0, 221, 0, 0, 0, 0,
- 0, 0, 35, 0, 0, 0, 36, 37, 0, 38,
- 0, 0, 0, 0, 0, 0, 521, 0, 0, 0,
- 45, 0, 0, 0, 0, 0, 0, 0, 585, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 53, 522,
- 524, 523, 0, 54, 0, 0, 0, 0, 230, 0,
- 0, 0, 0, 0, 44, 56, 32, 216, 224, 0,
- 0, 41, 0, 0, 520, 0, 0, 0, 0, 46,
- 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 519, 0, 30, 31, 0, 0, 0, 0, 0,
- 0, 0, 0, 221, 0, 0, 0, 0, 0, 0,
- 35, 0, 0, 0, 36, 37, 0, 38, 0, 0,
- 0, 0, 0, 0, 521, 0, 0, 0, 45, 0,
- 0, 0, 0, 0, 0, 0, 588, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 53, 522, 524, 523,
- 0, 54, 0, 0, 0, 0, 230, 0, 0, 0,
- 0, 0, 44, 56, 32, 216, 224, 0, 0, 41,
- 0, 0, 520, 0, 0, 0, 0, 46, 34, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 29,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
- 33, 0, 0, 0, 0, 0, 0, 35, 0, 0,
- 0, 36, 37, 0, 38, 0, 0, 0, 39, 0,
- 40, 42, 43, 0, 0, 45, 0, 0, 0, 47,
- 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 53, 49, 52, 50, 0, 54, 0,
- 55, 0, 57, 0, 58, 0, 0, 0, 0, 44,
- 56, 32, 0, 0, 0, 0, 41, 0, 0, 0,
- 0, 0, 0, 0, 46, 34, 51, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, -141, 0, 0, 0,
- 29, 30, 31, 0, 0, 0, 0, 0, 0, 0,
- 0, 33, 0, 0, 0, 0, 0, 0, 35, 0,
- 0, 0, 36, 37, 0, 38, 0, 0, 0, 39,
- 0, 40, 42, 43, 0, 0, 45, 0, 0, 0,
- 47, 0, 48, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 53, 49, 52, 50, 0, 54,
- 0, 55, 0, 57, 0, 58, 0, 0, 0, 0,
- 44, 56, 32, 0, 0, 0, 0, 41, 0, 0,
- 0, 0, 0, 0, 0, 46, 34, 51, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
- 57, 285, 58, 0, 0, 0, 0, 44, 56, 32,
- 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 492, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 493, 0, 0, 0, 0, 0, 0, 0,
- 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
- 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
- 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 500, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 503, 0, 0, 0, 0, 0, 0, 0,
- 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
- 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
- 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 492, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 498, 0, 0, 0, 0, 0, 0, 0,
- 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
- 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
- 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 500, 0, 0, 29, 30, 31,
- 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 35, 0, 0, 0, 36,
- 37, 0, 38, 0, 0, 0, 39, 0, 40, 42,
- 43, 0, 0, 45, 0, 0, 0, 47, 0, 48,
- 0, 0, 501, 0, 0, 0, 0, 0, 0, 0,
- 0, 53, 49, 52, 50, 0, 54, 0, 55, 0,
- 57, 0, 58, 0, 0, 0, 0, 44, 56, 32,
- 0, 0, 0, 0, 41, 0, 0, 0, 0, 0,
- 0, 0, 46, 34, 51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 29, 30, 31, 0, 0, 0,
- 0, 0, 0, 0, 0, 33, 0, 0, 0, 0,
- 0, 0, 35, 222, 0, 0, 223, 37, 0, 38,
- 0, 0, 0, 39, 0, 40, 42, 43, 0, 0,
- 45, 0, 0, 0, 47, 0, 48, 0, 0, 0,
- 0, 0, 0, 0, 226, 0, 0, 0, 53, 49,
- 52, 50, 227, 54, 0, 55, 229, 57, 0, 58,
- 0, 232, 0, 0, 44, 56, 32, 0, 0, 0,
- 0, 41, 0, 0, 0, 0, 0, 0, 0, 46,
- 34, 51, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 29, 30, 31, 0, 0, 0, 0, 0, 0,
- 0, 0, 33, 0, 0, 0, 0, 0, 0, 35,
- 222, 0, 0, 603, 650, 0, 38, 0, 0, 0,
- 39, 0, 40, 42, 43, 0, 0, 45, 0, 0,
- 0, 47, 0, 48, 0, 0, 0, 0, 0, 0,
- 0, 226, 0, 0, 0, 53, 49, 52, 50, 227,
- 54, 0, 55, 229, 57, 0, 58, 0, 232, 0,
- 0, 44, 56, 32, 0, 0, 0, 0, 41, 0,
- 0, 0, 0, 0, 0, 0, 46, 34, 51, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 29, 30,
- 31, 0, 0, 0, 0, 0, 0, 0, 0, 33,
- 0, 0, 0, 0, 0, 0, 35, 222, 0, 0,
- 603, 37, 0, 38, 0, 0, 0, 39, 0, 40,
- 42, 43, 0, 0, 45, 0, 0, 0, 47, 0,
- 48, 0, 0, 0, 0, 0, 0, 0, 226, 0,
- 0, 0, 53, 49, 52, 50, 227, 54, 0, 55,
- 229, 57, 0, 58, 0, 232, 0, 0, 44, 56,
- 32, 0, 0, 0, 0, 41, 0, 0, 0, 0,
- 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 111, 112, 113, 0, 0,
- 115, 117, 118, 0, 0, 119, 0, 120, 0, 0,
- 0, 123, 124, 125, 0, 0, 0, 0, 0, 0,
- 35, 126, 127, 128, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 130, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 133, 0, 0, 0, 0, 0, 0, 49, 52, 50,
- 134, 135, 136, 0, 138, 139, 140, 141, 142, 143,
- 0, 0, 131, 137, 122, 114, 129, 116, 132, 0,
- 0, 0, 121, 0, 0, 0, 0, 46, 34, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 111,
- 112, 113, 0, 0, 115, 117, 118, 0, 0, 119,
- 0, 120, 0, 0, 0, 123, 124, 125, 0, 0,
- 0, 0, 0, 0, 35, 126, 127, 128, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 130, 0,
- 0, 0, 399, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 133, 0, 0, 0, 0, 0,
- 401, 49, 52, 50, 134, 135, 136, 0, 138, 139,
- 140, 141, 142, 143, 0, 0, 131, 137, 122, 114,
- 129, 116, 132, 0, 0, 0, 121, 0, 0, 0,
- 0, 46, 34, 51, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 111, 112, 113, 0, 0, 115, 117,
- 118, 0, 0, 119, 0, 120, 0, 0, 0, 123,
- 124, 125, 0, 0, 0, 0, 0, 0, 35, 126,
- 127, 128, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 130, 0, 0, 0, 399, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 133, 0,
- 0, 0, 0, 0, 401, 49, 52, 50, 134, 135,
- 136, 0, 138, 139, 140, 141, 142, 143, 0, 0,
- 131, 137, 122, 114, 129, 116, 132, 0, 0, 0,
- 121, 0, 0, 0, 0, 46, 377, 384, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 111, 112, 113,
- 0, 0, 115, 117, 118, 0, 0, 119, 0, 120,
- 0, 0, 0, 123, 124, 125, 0, 0, 0, 0,
- 0, 0, 35, 126, 127, 128, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 130, 0, 0, 0,
- 399, 0, 0, 0, 0, 0, 0, 0, 400, 0,
- 0, 0, 133, 0, 0, 0, 0, 0, 401, 49,
- 52, 50, 134, 135, 136, 0, 138, 139, 140, 141,
- 142, 143, 0, 0, 131, 137, 122, 114, 129, 116,
- 132, 0, 0, 0, 121, 0, 0, 0, 0, 46,
- 377, 384, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 215, 0, 0, 0, 0, 217, 0, 29, 30,
- 31, 219, 0, 0, 0, 0, 0, 0, 220, 33,
- 0, 0, 0, 0, 0, 0, 35, 222, 0, 0,
- 223, 37, 0, 38, 0, 0, 0, 39, 0, 40,
- 42, 43, 0, 0, 45, 0, 0, 0, 47, 0,
- 48, 0, 0, 0, 0, 0, 225, 0, 226, 0,
- 0, 0, 53, 49, 52, 50, 227, 54, 228, 55,
- 229, 57, 230, 58, 231, 232, 0, 0, 44, 56,
- 32, 216, 224, 218, 0, 41, 0, 0, 0, 0,
- 0, 0, 0, 46, 34, 51, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 215, 0, 0, 0, 0,
- 217, 0, 29, 30, 31, 219, 0, 0, 0, 0,
- 0, 0, 220, 221, 0, 0, 0, 0, 0, 0,
- 35, 222, 0, 0, 223, 37, 0, 38, 0, 0,
- 0, 39, 0, 40, 42, 43, 0, 0, 45, 0,
- 0, 0, 47, 0, 48, 0, 0, 0, 0, 0,
- 225, 0, 226, 0, 0, 0, 53, 49, 52, 50,
- 227, 54, 228, 55, 229, 57, 230, 58, 231, 232,
- 0, 0, 44, 56, 32, 216, 224, 218, 0, 41,
- 0, 0, 0, 0, 0, 0, 0, 46, 34, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 607,
- 112, 113, 0, 0, 609, 117, 611, 30, 31, 612,
- 0, 120, 0, 0, 0, 123, 614, 615, 0, 0,
- 0, 0, 0, 0, 35, 616, 127, 128, 223, 37,
- 0, 38, 0, 0, 0, 39, 0, 40, 618, 43,
- 0, 0, 620, 0, 0, 0, 47, 0, 48, 0,
- 0, 0, 0, 0, 621, 0, 226, 0, 0, 0,
- 622, 49, 52, 50, 623, 624, 625, 55, 627, 628,
- 629, 630, 631, 632, 0, 0, 619, 626, 613, 608,
- 617, 610, 132, 41, 0, 0, 121, 0, 0, 0,
- 0, 46, 377, 384, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 368, 112, 113, 0, 0, 370, 117,
- 372, 30, 31, 373, 0, 120, 0, 0, 0, 123,
- 375, 376, 0, 0, 0, 0, 0, 0, 35, 378,
- 127, 128, 223, 37, 0, 38, 0, 0, 0, 39,
- 0, 40, 380, 43, 0, 0, 382, 0, 0, 0,
- 47, 0, 48, 0, -288, 0, 0, 0, 383, 0,
- 226, 0, 0, 0, 385, 49, 52, 50, 386, 387,
- 388, 55, 390, 391, 392, 393, 394, 395, 0, 0,
- 381, 389, 374, 369, 379, 371, 132, 41, 0, 0,
- 121, 0, 0, 0, 0, 46, 377, 384, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-
- 543, 185, 640, 647, 642, 643, 504, 489, 397, 451,
- 655, 657, 669, 670, 154, 680, 658, 448, 686, 316,
- 185, 16, 256, 536, 251, 599, 570, 633, 572, 590,
- 597, 144, 323, 540, 457, 150, 266, 473, 190, 441,
- 350, 445, 251, 192, 256, 437, 429, 354, 208, 240,
- 185, 316, 251, 256, 185, 404, 448, 448, 316, 533,
- 566, 470, 466, 180, 451, 451, 462, 0, 62, 334,
- 510, 516, 62, 0, 0, 325, 62, 299, 316, 0,
- 459, 298, 397, 334, 0, 147, 461, 208, 499, 0,
- 152, 208, 502, 167, 600, 479, 673, 672, 518, 173,
- 175, 515, 316, 674, 208, 397, 316, 518, 316, 407,
- 208, 0, 190, 0, 321, 208, 656, 352, 62, 249,
- 464, 62, 62, 184, 509, 62, 62, 463, 463, 62,
- 208, 508, 421, 208, 62, 208, 184, 356, 245, 358,
- 405, 242, 263, 280, 62, 62, 62, 506, 284, 302,
- 62, 301, 507, 208, 317, 208, 208, 62, 208, 62,
- 343, 184, 300, 413, 348, 365, 62, 0, 62, 190,
- 518, 62, 99, 62, 100, 578, 86, 90, 346, 62,
- 208, 208, 319, 91, 344, 62, 62, 62, 413, 62,
- 93, 94, 95, 473, 96, 468, 514, 62, 189, 62,
- 150, 414, 97, 92, 208, 62, 472, 464, 182, 62,
- 62, 208, 497, 62, 62, 397, 496, 250, 365, 62,
- 104, 102, 208, 263, 208, 98, 414, 263, 169, 172,
- 365, 208, 487, 62, 359, 511, 62, 250, 463, 208,
- 62, 398, 464, 208, 62, 62, 606, 63, 72, 190,
- 150, 208, 411, 62, 518, 69, 62, 208, 416, 582,
- 365, 365, 79, 62, 62, 70, 62, 62, 483, 71,
- 0, 284, 74, 0, 0, 62, 208, 208, 423, 307,
- 284, 0, 62, 0, 287, 426, 108, 284, 0, 292,
- 62, 62, 0, 0, 0, 284, 284, 303, 304, 62,
- 312, 0, 62, 312, 284, 284, 305, 284, 284, 312,
- 62, 0, 312, 309, 284, 284, 110, 284, 62, 312,
- 0, 594, 333, 284, 284, 340, 578, 330, 653, 0,
- 518, 331, 0, 327, 311, 586, 0, 589, 0, 527,
- 0, 314, 0, 0, 518, 0, 518, 444, 447, 0,
- 489, 517, 528, 527, 0, 527, 547, 548, 549, 550,
- 554, 551, 552, 0, 0, 517, 528, 517, 528, 0,
- 0, 0, 602, 0, 0, 0, 0, 0, 0, 0,
- 108, 604, 605, 547, 548, 549, 550, 554, 551, 552,
- 594, 0, 0, 0, 0, 0, 0, 0, 0, 595,
- 596, 547, 548, 549, 550, 554, 551, 552, 0, 0,
- 110, 179, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 602, 0, 0, 0, 0, 0,
- 0, 0, 0, 651, 652, 547, 548, 549, 550, 554,
- 551, 552, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0
-};
-
-const short QQmlJSGrammar::action_check [] = {
- 7, 33, 60, 60, 7, 36, 7, 7, 60, 7,
- 36, 36, 7, 7, 60, 36, 55, 7, 33, 55,
- 33, 7, 36, 7, 36, 36, 7, 37, 36, 7,
- 36, 7, 7, 7, 33, 7, 33, 33, 47, 66,
- 17, 34, 47, 66, 29, 37, 29, 29, 17, 29,
- 29, 17, 5, 5, 5, 20, 60, 7, 60, 8,
- 33, 7, 33, 33, 55, 33, 55, 7, 55, 36,
- 33, 33, 60, 33, 7, 36, 33, 36, 36, 33,
- 8, 7, 2, 7, 1, 8, 1, 8, 1, 36,
- 8, 2, 8, -1, 2, -1, 60, -1, 33, 55,
- 55, 7, 36, 1, 48, 0, 7, 36, 2, 36,
- 48, 36, 60, 17, 33, 60, 48, 16, 8, 55,
- 61, 60, 36, 7, 36, 8, 36, 36, 8, 60,
- 8, 8, 6, 8, 15, -1, 79, 79, 8, 61,
- 77, 48, 15, 7, 8, 8, 20, 15, 15, 79,
- -1, 24, 8, 34, 8, 8, -1, -1, 61, 61,
- 62, 61, 62, 8, 61, 62, 34, 34, 50, 61,
- 62, 50, 54, 8, 79, 54, 8, 60, 56, 10,
- 60, 56, 40, 60, 8, 61, 62, 8, 40, 12,
- 60, 7, 55, 51, 40, 61, 62, 93, 94, 51,
- 61, 62, 31, 7, 60, 51, 60, 60, 93, 94,
- 15, 56, 61, 62, 61, 62, 42, 61, 62, 24,
- 15, 56, 61, 62, 55, 61, 62, 53, 60, 33,
- 29, 29, 7, 12, 57, 56, 25, 61, 27, 34,
- 63, 36, 25, 7, 27, 61, 62, 29, 25, 38,
- 27, 25, 25, 27, 27, 38, 25, 29, 27, 95,
- -1, 38, 29, -1, 38, 38, 29, -1, 12, 38,
- 36, 29, 25, -1, 27, -1, 75, 75, 57, 40,
- 15, 8, -1, 8, 63, 38, 61, 62, 87, 87,
- 51, -1, 96, 75, -1, 61, 62, 61, 62, 34,
- -1, 36, 15, 75, 8, 87, -1, -1, 75, 25,
- -1, 27, 75, 57, 25, 87, 27, 75, -1, 63,
- 87, 34, 38, 36, 87, 61, 62, 38, 25, 87,
- 27, 25, -1, 27, 61, 62, 61, 62, 25, -1,
- 27, 38, 15, 25, 38, 27, 15, 15, 18, 19,
- -1, 38, 18, 19, 90, 47, 38, 61, 62, -1,
- 33, 34, -1, 36, 33, 34, 34, 36, 36, 61,
- 62, -1, 23, 24, -1, 45, 46, -1, -1, 45,
- 46, 32, 23, 24, 35, -1, 37, -1, 23, 24,
- -1, 32, 23, 24, 35, -1, 37, 32, 23, 24,
- 35, 32, 37, 95, 35, -1, 37, 32, 23, 24,
- 35, -1, 37, -1, -1, -1, 31, 32, 23, 24,
- 35, 29, 37, -1, -1, 29, 31, 32, -1, -1,
- 35, -1, 37, 29, 23, 24, 29, -1, -1, 29,
- 18, 19, 31, 32, 29, -1, 35, 29, 37, -1,
- 100, 101, 102, 103, 104, 105, -1, -1, 66, 67,
- 68, -1, 66, 67, 68, -1, -1, 45, 46, -1,
- 66, 67, 68, 66, 67, 68, 66, 67, 68, -1,
- 29, 66, 67, 68, 66, 67, 68, 29, 96, 97,
- 98, -1, 96, 97, 98, 29, -1, -1, 29, -1,
- 96, 97, 98, 96, 97, 98, 96, 97, 98, -1,
- -1, 96, 97, 98, 96, 97, 98, 66, 67, 68,
- 29, -1, -1, -1, 66, 67, 68, -1, -1, -1,
- 23, 24, 66, 67, 68, 66, 67, 68, 31, 32,
- -1, -1, 35, 29, 37, -1, 15, 96, 97, 98,
- 36, -1, -1, -1, 96, 97, 98, 66, 67, 68,
- 29, -1, 96, 97, 98, 96, 97, 98, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 15,
- 66, 67, 68, -1, -1, -1, 15, 96, 97, 98,
- 15, -1, -1, 29, 15, -1, 29, 66, 67, 68,
- 29, -1, -1, 36, 29, -1, -1, -1, 29, -1,
- 96, 97, 98, -1, -1, 29, -1, -1, 29, -1,
- -1, -1, -1, -1, -1, -1, -1, 96, 97, 98,
- 66, 67, 68, 66, 67, 68, -1, 66, 67, 68,
- -1, 66, 67, 68, -1, 66, 67, 68, -1, -1,
- 61, 62, 66, 67, 68, 66, 67, 68, 29, -1,
- 96, 97, 98, 96, 97, 98, -1, 96, 97, 98,
- 29, 96, 97, 98, -1, 96, 97, 98, 29, -1,
- -1, 29, 96, 97, 98, 96, 97, 98, -1, -1,
- 61, 62, -1, -1, 29, 66, 67, 68, -1, -1,
- -1, 36, 61, 62, -1, -1, -1, 66, 67, 68,
- 61, 62, -1, 61, 62, 66, 67, 68, 66, 67,
- 68, -1, -1, -1, -1, 96, 97, 98, -1, -1,
- 3, 66, 67, 68, -1, -1, -1, 96, 97, 98,
- 13, -1, -1, -1, 17, 96, 97, 98, 96, 97,
- 98, -1, -1, 26, -1, 28, -1, -1, -1, -1,
- -1, 96, 97, 98, -1, -1, 39, -1, 41, 42,
- -1, -1, -1, 29, -1, -1, 49, -1, -1, 52,
- 53, -1, -1, -1, -1, 58, -1, -1, -1, -1,
- -1, 64, -1, -1, -1, -1, -1, -1, -1, 3,
- -1, -1, -1, -1, -1, 61, 62, 80, -1, 13,
- 66, 67, 68, 17, -1, -1, -1, -1, -1, -1,
- -1, -1, 26, -1, 28, -1, -1, 31, -1, -1,
- -1, -1, -1, -1, -1, 39, -1, 41, 42, -1,
- 96, 97, 98, -1, -1, 49, -1, -1, 52, 53,
- -1, -1, 3, -1, 58, -1, -1, -1, -1, -1,
- 64, -1, 13, -1, -1, -1, 17, -1, -1, -1,
- -1, -1, -1, -1, -1, 26, 80, 28, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 39, -1,
- 41, 42, -1, -1, -1, -1, -1, -1, 49, -1,
- -1, 52, 53, -1, -1, -1, -1, 58, -1, -1,
- -1, -1, -1, 64, -1, 12, 13, -1, -1, -1,
- -1, -1, -1, -1, -1, 22, -1, -1, -1, 80,
- -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
- -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
- 47, -1, -1, -1, -1, -1, -1, 12, 13, -1,
- -1, -1, -1, -1, -1, -1, -1, 22, 65, 66,
- 67, 68, -1, 70, 29, -1, -1, -1, 33, 34,
- -1, 36, -1, -1, 81, 82, 83, -1, 43, -1,
- -1, 88, 47, -1, -1, -1, -1, -1, -1, 96,
- 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
- 65, 66, 67, 68, -1, 70, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 81, 82, 83, -1,
- -1, -1, -1, 88, -1, -1, -1, -1, -1, -1,
- -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 12, 13, -1, -1, -1, -1, -1,
- -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
- 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
- -1, -1, -1, -1, 43, -1, -1, -1, 47, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 65, 66, 67, 68,
- -1, 70, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 81, 82, 83, -1, -1, -1, -1, 88,
- -1, -1, -1, -1, -1, -1, -1, 96, 97, 98,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 12,
- 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
- -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
- 33, 34, -1, 36, -1, -1, -1, -1, -1, -1,
- 43, -1, -1, -1, 47, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 65, 66, 67, 68, -1, 70, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 81, 82,
- 83, -1, -1, -1, -1, 88, -1, -1, -1, -1,
- -1, -1, -1, 96, 97, 98, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 10, -1, 12, 13, -1,
- -1, -1, -1, -1, -1, -1, -1, 22, -1, -1,
- -1, -1, -1, -1, 29, -1, -1, -1, 33, 34,
- -1, 36, -1, -1, -1, -1, -1, -1, 43, -1,
- -1, -1, 47, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 65, 66, 67, 68, -1, 70, -1, -1, -1, -1,
- 75, -1, -1, -1, -1, -1, 81, 82, 83, 84,
- 85, -1, -1, 88, -1, -1, 91, -1, -1, -1,
- -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 10, -1, 12, 13, -1, -1, -1,
- -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
- -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
- -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
- 47, -1, -1, -1, -1, -1, -1, -1, 55, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
- 67, 68, -1, 70, -1, -1, -1, -1, 75, -1,
- -1, -1, -1, -1, 81, 82, 83, 84, 85, -1,
- -1, 88, -1, -1, 91, -1, -1, -1, -1, 96,
- 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 10, -1, 12, 13, -1, -1, -1, -1, -1,
- -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
- 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
- -1, -1, -1, -1, 43, -1, -1, -1, 47, -1,
- -1, -1, -1, -1, -1, -1, 55, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 65, 66, 67, 68,
- -1, 70, -1, -1, -1, -1, 75, -1, -1, -1,
- -1, -1, 81, 82, 83, 84, 85, -1, -1, 88,
- -1, -1, 91, -1, -1, -1, -1, 96, 97, 98,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 11,
- 12, 13, -1, -1, -1, -1, -1, -1, -1, -1,
- 22, -1, -1, -1, -1, -1, -1, 29, -1, -1,
- -1, 33, 34, -1, 36, -1, -1, -1, 40, -1,
- 42, 43, 44, -1, -1, 47, -1, -1, -1, 51,
- -1, 53, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 65, 66, 67, 68, -1, 70, -1,
- 72, -1, 74, -1, 76, -1, -1, -1, -1, 81,
- 82, 83, -1, -1, -1, -1, 88, -1, -1, -1,
- -1, -1, -1, -1, 96, 97, 98, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 7, -1, -1, -1,
- 11, 12, 13, -1, -1, -1, -1, -1, -1, -1,
- -1, 22, -1, -1, -1, -1, -1, -1, 29, -1,
- -1, -1, 33, 34, -1, 36, -1, -1, -1, 40,
- -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
- 51, -1, 53, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 65, 66, 67, 68, -1, 70,
- -1, 72, -1, 74, -1, 76, -1, -1, -1, -1,
- 81, 82, 83, -1, -1, -1, -1, 88, -1, -1,
- -1, -1, -1, -1, -1, 96, 97, 98, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
- 74, 75, 76, -1, -1, -1, -1, 81, 82, 83,
- -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
- -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
- -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
- 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
- -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
- -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
- -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
- 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
- -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
- -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
- -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
- 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
- -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
- -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 8, -1, -1, 11, 12, 13,
- -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
- -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
- 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
- -1, -1, 56, -1, -1, -1, -1, -1, -1, -1,
- -1, 65, 66, 67, 68, -1, 70, -1, 72, -1,
- 74, -1, 76, -1, -1, -1, -1, 81, 82, 83,
- -1, -1, -1, -1, 88, -1, -1, -1, -1, -1,
- -1, -1, 96, 97, 98, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 11, 12, 13, -1, -1, -1,
- -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
- -1, -1, 29, 30, -1, -1, 33, 34, -1, 36,
- -1, -1, -1, 40, -1, 42, 43, 44, -1, -1,
- 47, -1, -1, -1, 51, -1, 53, -1, -1, -1,
- -1, -1, -1, -1, 61, -1, -1, -1, 65, 66,
- 67, 68, 69, 70, -1, 72, 73, 74, -1, 76,
- -1, 78, -1, -1, 81, 82, 83, -1, -1, -1,
- -1, 88, -1, -1, -1, -1, -1, -1, -1, 96,
- 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
- -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
- 30, -1, -1, 33, 34, -1, 36, -1, -1, -1,
- 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
- -1, 51, -1, 53, -1, -1, -1, -1, -1, -1,
- -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
- 70, -1, 72, 73, 74, -1, 76, -1, 78, -1,
- -1, 81, 82, 83, -1, -1, -1, -1, 88, -1,
- -1, -1, -1, -1, -1, -1, 96, 97, 98, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
- 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
- -1, -1, -1, -1, -1, -1, 29, 30, -1, -1,
- 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
- 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
- 53, -1, -1, -1, -1, -1, -1, -1, 61, -1,
- -1, -1, 65, 66, 67, 68, 69, 70, -1, 72,
- 73, 74, -1, 76, -1, 78, -1, -1, 81, 82,
- 83, -1, -1, -1, -1, 88, -1, -1, -1, -1,
- -1, -1, -1, 96, 97, 98, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4, 5, 6, -1, -1,
- 9, 10, 11, -1, -1, 14, -1, 16, -1, -1,
- -1, 20, 21, 22, -1, -1, -1, -1, -1, -1,
- 29, 30, 31, 32, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 43, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 59, -1, -1, -1, -1, -1, -1, 66, 67, 68,
- 69, 70, 71, -1, 73, 74, 75, 76, 77, 78,
- -1, -1, 81, 82, 83, 84, 85, 86, 87, -1,
- -1, -1, 91, -1, -1, -1, -1, 96, 97, 98,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 4,
- 5, 6, -1, -1, 9, 10, 11, -1, -1, 14,
- -1, 16, -1, -1, -1, 20, 21, 22, -1, -1,
- -1, -1, -1, -1, 29, 30, 31, 32, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 43, -1,
- -1, -1, 47, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 59, -1, -1, -1, -1, -1,
- 65, 66, 67, 68, 69, 70, 71, -1, 73, 74,
- 75, 76, 77, 78, -1, -1, 81, 82, 83, 84,
- 85, 86, 87, -1, -1, -1, 91, -1, -1, -1,
- -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4, 5, 6, -1, -1, 9, 10,
- 11, -1, -1, 14, -1, 16, -1, -1, -1, 20,
- 21, 22, -1, -1, -1, -1, -1, -1, 29, 30,
- 31, 32, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 43, -1, -1, -1, 47, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 59, -1,
- -1, -1, -1, -1, 65, 66, 67, 68, 69, 70,
- 71, -1, 73, 74, 75, 76, 77, 78, -1, -1,
- 81, 82, 83, 84, 85, 86, 87, -1, -1, -1,
- 91, -1, -1, -1, -1, 96, 97, 98, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4, 5, 6,
- -1, -1, 9, 10, 11, -1, -1, 14, -1, 16,
- -1, -1, -1, 20, 21, 22, -1, -1, -1, -1,
- -1, -1, 29, 30, 31, 32, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
- 47, -1, -1, -1, -1, -1, -1, -1, 55, -1,
- -1, -1, 59, -1, -1, -1, -1, -1, 65, 66,
- 67, 68, 69, 70, 71, -1, 73, 74, 75, 76,
- 77, 78, -1, -1, 81, 82, 83, 84, 85, 86,
- 87, -1, -1, -1, 91, -1, -1, -1, -1, 96,
- 97, 98, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4, -1, -1, -1, -1, 9, -1, 11, 12,
- 13, 14, -1, -1, -1, -1, -1, -1, 21, 22,
- -1, -1, -1, -1, -1, -1, 29, 30, -1, -1,
- 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
- 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
- 53, -1, -1, -1, -1, -1, 59, -1, 61, -1,
- -1, -1, 65, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78, -1, -1, 81, 82,
- 83, 84, 85, 86, -1, 88, -1, -1, -1, -1,
- -1, -1, -1, 96, 97, 98, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4, -1, -1, -1, -1,
- 9, -1, 11, 12, 13, 14, -1, -1, -1, -1,
- -1, -1, 21, 22, -1, -1, -1, -1, -1, -1,
- 29, 30, -1, -1, 33, 34, -1, 36, -1, -1,
- -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
- -1, -1, 51, -1, 53, -1, -1, -1, -1, -1,
- 59, -1, 61, -1, -1, -1, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- -1, -1, 81, 82, 83, 84, 85, 86, -1, 88,
- -1, -1, -1, -1, -1, -1, -1, 96, 97, 98,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 4,
- 5, 6, -1, -1, 9, 10, 11, 12, 13, 14,
- -1, 16, -1, -1, -1, 20, 21, 22, -1, -1,
- -1, -1, -1, -1, 29, 30, 31, 32, 33, 34,
- -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
- -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
- -1, -1, -1, -1, 59, -1, 61, -1, -1, -1,
- 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, -1, -1, 81, 82, 83, 84,
- 85, 86, 87, 88, -1, -1, 91, -1, -1, -1,
- -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4, 5, 6, -1, -1, 9, 10,
- 11, 12, 13, 14, -1, 16, -1, -1, -1, 20,
- 21, 22, -1, -1, -1, -1, -1, -1, 29, 30,
- 31, 32, 33, 34, -1, 36, -1, -1, -1, 40,
- -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
- 51, -1, 53, -1, 55, -1, -1, -1, 59, -1,
- 61, -1, -1, -1, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, -1, -1,
- 81, 82, 83, 84, 85, 86, 87, 88, -1, -1,
- 91, -1, -1, -1, -1, 96, 97, 98, -1, -1,
- -1, -1, -1, -1, -1, -1, -1,
-
- 18, 18, 32, 18, 32, 18, 3, 43, 18, 25,
- 22, 22, 14, 14, 78, 18, 9, 3, 18, 3,
- 18, 3, 18, 32, 18, 32, 32, 22, 18, 18,
- 22, 3, 3, 18, 106, 43, 3, 18, 18, 101,
- 3, 3, 18, 18, 18, 104, 3, 3, 18, 18,
- 18, 3, 18, 18, 18, 43, 3, 3, 3, 32,
- 14, 3, 3, 3, 25, 25, 25, -1, 55, 18,
- 57, 2, 55, -1, -1, 2, 55, 60, 3, -1,
- 18, 60, 18, 18, -1, 43, 25, 18, 43, -1,
- 43, 18, 43, 43, 18, 43, 11, 12, 14, 43,
- 43, 4, 3, 19, 18, 18, 3, 14, 3, 45,
- 18, -1, 18, -1, 2, 18, 23, 2, 55, 2,
- 57, 55, 55, 57, 57, 55, 55, 57, 57, 55,
- 18, 57, 45, 18, 55, 18, 57, 2, 46, 2,
- 2, 47, 2, 55, 55, 55, 55, 57, 60, 60,
- 55, 60, 57, 18, 79, 18, 18, 55, 18, 55,
- 95, 57, 60, 14, 2, 2, 55, -1, 55, 18,
- 14, 55, 61, 55, 61, 19, 60, 59, 79, 55,
- 18, 18, 79, 59, 79, 55, 55, 55, 14, 55,
- 60, 60, 60, 18, 60, 2, 110, 55, 47, 55,
- 43, 52, 60, 59, 18, 55, 2, 57, 51, 55,
- 55, 18, 39, 55, 55, 18, 43, 4, 2, 55,
- 65, 67, 18, 2, 18, 61, 52, 2, 69, 71,
- 2, 18, 46, 55, 18, 57, 55, 4, 57, 18,
- 55, 44, 57, 18, 55, 55, 18, 58, 58, 18,
- 43, 18, 46, 55, 14, 57, 55, 18, 51, 19,
- 2, 2, 61, 55, 55, 57, 55, 55, 93, 57,
- -1, 60, 63, -1, -1, 55, 18, 18, 47, 68,
- 60, -1, 55, -1, 64, 46, 18, 60, -1, 62,
- 55, 55, -1, -1, -1, 60, 60, 62, 62, 55,
- 55, -1, 55, 55, 60, 60, 62, 60, 60, 55,
- 55, -1, 55, 66, 60, 60, 48, 60, 55, 55,
- -1, 14, 77, 60, 60, 77, 19, 72, 21, -1,
- 14, 77, -1, 70, 77, 5, -1, 5, -1, 23,
- -1, 77, -1, -1, 14, -1, 14, 89, 89, -1,
- 43, 35, 36, 23, -1, 23, 25, 26, 27, 28,
- 29, 30, 31, -1, -1, 35, 36, 35, 36, -1,
- -1, -1, 14, -1, -1, -1, -1, -1, -1, -1,
- 18, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 14, -1, -1, -1, -1, -1, -1, -1, -1, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, -1, -1,
- 48, 49, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 14, -1, -1, -1, -1, -1,
- -1, -1, -1, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1
-};
-
-QT_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsgrammar_p.h b/src/qml/parser/qqmljsgrammar_p.h
deleted file mode 100644
index 9d028f2191..0000000000
--- a/src/qml/parser/qqmljsgrammar_p.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-// This file was generated by qlalr - DO NOT EDIT!
-#ifndef QQMLJSGRAMMAR_P_H
-#define QQMLJSGRAMMAR_P_H
-
-#include <QtCore/qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlJSGrammar
-{
-public:
- enum VariousConstants {
- EOF_SYMBOL = 0,
- REDUCE_HERE = 107,
- SHIFT_THERE = 106,
- T_AND = 1,
- T_AND_AND = 2,
- T_AND_EQ = 3,
- T_AS = 95,
- T_AUTOMATIC_SEMICOLON = 62,
- T_BREAK = 4,
- T_CASE = 5,
- T_CATCH = 6,
- T_COLON = 7,
- T_COMMA = 8,
- T_COMMENT = 89,
- T_COMPATIBILITY_SEMICOLON = 90,
- T_CONST = 84,
- T_CONTINUE = 9,
- T_DEBUGGER = 86,
- T_DEFAULT = 10,
- T_DELETE = 11,
- T_DIVIDE_ = 12,
- T_DIVIDE_EQ = 13,
- T_DO = 14,
- T_DOT = 15,
- T_ELSE = 16,
- T_ENUM = 91,
- T_EQ = 17,
- T_EQ_EQ = 18,
- T_EQ_EQ_EQ = 19,
- T_ERROR = 99,
- T_FALSE = 83,
- T_FEED_JS_EXPRESSION = 103,
- T_FEED_JS_PROGRAM = 105,
- T_FEED_JS_SOURCE_ELEMENT = 104,
- T_FEED_JS_STATEMENT = 102,
- T_FEED_UI_OBJECT_MEMBER = 101,
- T_FEED_UI_PROGRAM = 100,
- T_FINALLY = 20,
- T_FOR = 21,
- T_FUNCTION = 22,
- T_GE = 23,
- T_GET = 97,
- T_GT = 24,
- T_GT_GT = 25,
- T_GT_GT_EQ = 26,
- T_GT_GT_GT = 27,
- T_GT_GT_GT_EQ = 28,
- T_IDENTIFIER = 29,
- T_IF = 30,
- T_IMPORT = 93,
- T_IN = 31,
- T_INSTANCEOF = 32,
- T_LBRACE = 33,
- T_LBRACKET = 34,
- T_LE = 35,
- T_LET = 85,
- T_LPAREN = 36,
- T_LT = 37,
- T_LT_LT = 38,
- T_LT_LT_EQ = 39,
- T_MINUS = 40,
- T_MINUS_EQ = 41,
- T_MINUS_MINUS = 42,
- T_MULTILINE_STRING_LITERAL = 88,
- T_NEW = 43,
- T_NOT = 44,
- T_NOT_EQ = 45,
- T_NOT_EQ_EQ = 46,
- T_NULL = 81,
- T_NUMERIC_LITERAL = 47,
- T_ON = 96,
- T_OR = 48,
- T_OR_EQ = 49,
- T_OR_OR = 50,
- T_PLUS = 51,
- T_PLUS_EQ = 52,
- T_PLUS_PLUS = 53,
- T_PRAGMA = 94,
- T_PROPERTY = 66,
- T_PUBLIC = 92,
- T_QUESTION = 54,
- T_RBRACE = 55,
- T_RBRACKET = 56,
- T_READONLY = 68,
- T_REMAINDER = 57,
- T_REMAINDER_EQ = 58,
- T_RESERVED_WORD = 87,
- T_RETURN = 59,
- T_RPAREN = 60,
- T_SEMICOLON = 61,
- T_SET = 98,
- T_SIGNAL = 67,
- T_STAR = 63,
- T_STAR_EQ = 64,
- T_STRING_LITERAL = 65,
- T_SWITCH = 69,
- T_THIS = 70,
- T_THROW = 71,
- T_TILDE = 72,
- T_TRUE = 82,
- T_TRY = 73,
- T_TYPEOF = 74,
- T_VAR = 75,
- T_VOID = 76,
- T_WHILE = 77,
- T_WITH = 78,
- T_XOR = 79,
- T_XOR_EQ = 80,
-
- ACCEPT_STATE = 691,
- RULE_COUNT = 369,
- STATE_COUNT = 692,
- TERMINAL_COUNT = 108,
- NON_TERMINAL_COUNT = 112,
-
- GOTO_INDEX_OFFSET = 692,
- GOTO_INFO_OFFSET = 3357,
- GOTO_CHECK_OFFSET = 3357
- };
-
- static const char *const spell[];
- static const short lhs[];
- static const short rhs[];
- static const short goto_default[];
- static const short action_default[];
- static const short action_index[];
- static const short action_info[];
- static const short action_check[];
-
- static inline int nt_action (int state, int nt)
- {
- const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
- if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
- return goto_default [nt];
-
- return action_info [GOTO_INFO_OFFSET + yyn];
- }
-
- static inline int t_action (int state, int token)
- {
- const int yyn = action_index [state] + token;
-
- if (yyn < 0 || action_check [yyn] != token)
- return - action_default [state];
-
- return action_info [yyn];
- }
-};
-
-
-QT_END_NAMESPACE
-#endif // QQMLJSGRAMMAR_P_H
-
diff --git a/src/qml/parser/qqmljskeywords_p.h b/src/qml/parser/qqmljskeywords_p.h
index 20daf545a9..40094ecdf8 100644
--- a/src/qml/parser/qqmljskeywords_p.h
+++ b/src/qml/parser/qqmljskeywords_p.h
@@ -57,10 +57,10 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS {
-static inline int classify2(const QChar *s, bool qmlMode) {
+static inline int classify2(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'a') {
if (s[1].unicode() == 's') {
- return qmlMode ? Lexer::T_AS : Lexer::T_IDENTIFIER;
+ return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_AS : Lexer::T_IDENTIFIER;
}
}
else if (s[0].unicode() == 'd') {
@@ -76,15 +76,18 @@ static inline int classify2(const QChar *s, bool qmlMode) {
return Lexer::T_IN;
}
}
- else if (qmlMode && s[0].unicode() == 'o') {
+ else if (s[0].unicode() == 'o') {
if (s[1].unicode() == 'n') {
- return qmlMode ? Lexer::T_ON : Lexer::T_IDENTIFIER;
+ return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_ON : Lexer::T_IDENTIFIER;
+ }
+ else if (s[1].unicode() == 'f') {
+ return Lexer::T_OF;
}
}
return Lexer::T_IDENTIFIER;
}
-static inline int classify3(const QChar *s, bool qmlMode) {
+static inline int classify3(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'f') {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'r') {
@@ -102,7 +105,7 @@ static inline int classify3(const QChar *s, bool qmlMode) {
else if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'n') {
if (s[2].unicode() == 't') {
- return qmlMode ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -144,12 +147,12 @@ static inline int classify3(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify4(const QChar *s, bool qmlMode) {
+static inline int classify4(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'y') {
if (s[2].unicode() == 't') {
if (s[3].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -165,7 +168,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'h') {
if (s[2].unicode() == 'a') {
if (s[3].unicode() == 'r') {
- return qmlMode ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -181,7 +184,16 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'n') {
if (s[2].unicode() == 'u') {
if (s[3].unicode() == 'm') {
- return qmlMode ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
+ }
+ }
+ }
+ }
+ else if (s[0].unicode() == 'f') {
+ if (s[1].unicode() == 'r') {
+ if (s[2].unicode() == 'o') {
+ if (s[3].unicode() == 'm') {
+ return int(Lexer::T_FROM);
}
}
}
@@ -190,7 +202,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 't') {
if (s[3].unicode() == 'o') {
- return qmlMode ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -199,7 +211,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 'g') {
- return qmlMode ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -250,7 +262,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify5(const QChar *s, bool qmlMode) {
+static inline int classify5(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'e') {
@@ -305,7 +317,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 'a') {
if (s[4].unicode() == 'l') {
- return qmlMode ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -314,7 +326,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'a') {
if (s[4].unicode() == 't') {
- return qmlMode ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -325,7 +337,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'r') {
if (s[4].unicode() == 't') {
- return qmlMode ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -334,7 +346,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'p') {
if (s[3].unicode() == 'e') {
if (s[4].unicode() == 'r') {
- return qmlMode ? int(Lexer::T_SUPER) : int(Lexer::T_RESERVED_WORD);
+ return int(Lexer::T_SUPER);
}
}
}
@@ -362,10 +374,21 @@ static inline int classify5(const QChar *s, bool qmlMode) {
}
}
}
+ else if (s[0].unicode() == 'y') {
+ if (s[1].unicode() == 'i') {
+ if (s[2].unicode() == 'e') {
+ if (s[3].unicode() == 'l') {
+ if (s[4].unicode() == 'd') {
+ return (parseModeFlags & Lexer::YieldIsKeyword) ? Lexer::T_YIELD : Lexer::T_IDENTIFIER;
+ }
+ }
+ }
+ }
+ }
return Lexer::T_IDENTIFIER;
}
-static inline int classify6(const QChar *s, bool qmlMode) {
+static inline int classify6(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'd') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'l') {
@@ -383,7 +406,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'b') {
if (s[4].unicode() == 'l') {
if (s[5].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -409,7 +432,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'o') {
if (s[4].unicode() == 'r') {
if (s[5].unicode() == 't') {
- return qmlMode ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD);
}
}
}
@@ -422,7 +445,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'i') {
if (s[4].unicode() == 'v') {
if (s[5].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -435,7 +458,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'l') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'c') {
- return qmlMode ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER;
+ return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER;
}
}
}
@@ -446,7 +469,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'g') {
if (s[4].unicode() == 'm') {
if (s[5].unicode() == 'a') {
- return qmlMode ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER;
+ return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER;
}
}
}
@@ -467,7 +490,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
}
}
else if (s[0].unicode() == 's') {
- if (qmlMode && s[1].unicode() == 'i') {
+ if ((parseModeFlags & Lexer::QmlMode) && s[1].unicode() == 'i') {
if (s[2].unicode() == 'g') {
if (s[3].unicode() == 'n') {
if (s[4].unicode() == 'a') {
@@ -483,7 +506,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 't') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'c') {
- return qmlMode ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::StaticIsKeyword) ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -507,7 +530,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'o') {
if (s[4].unicode() == 'w') {
if (s[5].unicode() == 's') {
- return qmlMode ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -528,7 +551,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify7(const QChar *s, bool qmlMode) {
+static inline int classify7(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'o') {
@@ -536,7 +559,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'e') {
if (s[5].unicode() == 'a') {
if (s[6].unicode() == 'n') {
- return qmlMode ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -596,7 +619,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'a') {
if (s[5].unicode() == 'g') {
if (s[6].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -609,7 +632,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'a') {
if (s[5].unicode() == 't') {
if (s[6].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -620,7 +643,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify8(const QChar *s, bool qmlMode) {
+static inline int classify8(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'a') {
if (s[1].unicode() == 'b') {
if (s[2].unicode() == 's') {
@@ -629,7 +652,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
if (s[5].unicode() == 'a') {
if (s[6].unicode() == 'c') {
if (s[7].unicode() == 't') {
- return qmlMode ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -689,7 +712,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
}
}
}
- else if (qmlMode && s[0].unicode() == 'p') {
+ else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'p') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'p') {
@@ -706,7 +729,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
}
}
}
- else if (qmlMode && s[0].unicode() == 'r') {
+ else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'r') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'a') {
if (s[3].unicode() == 'd') {
@@ -731,7 +754,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
if (s[5].unicode() == 'i') {
if (s[6].unicode() == 'l') {
if (s[7].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -743,7 +766,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify9(const QChar *s, bool qmlMode) {
+static inline int classify9(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'n') {
if (s[2].unicode() == 't') {
@@ -753,7 +776,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 'a') {
if (s[7].unicode() == 'c') {
if (s[8].unicode() == 'e') {
- return qmlMode ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -772,7 +795,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 't') {
if (s[7].unicode() == 'e') {
if (s[8].unicode() == 'd') {
- return qmlMode ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -791,7 +814,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 'e') {
if (s[7].unicode() == 'n') {
if (s[8].unicode() == 't') {
- return qmlMode ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -804,7 +827,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify10(const QChar *s, bool qmlMode) {
+static inline int classify10(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'm') {
if (s[2].unicode() == 'p') {
@@ -815,7 +838,7 @@ static inline int classify10(const QChar *s, bool qmlMode) {
if (s[7].unicode() == 'n') {
if (s[8].unicode() == 't') {
if (s[9].unicode() == 's') {
- return qmlMode ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -848,7 +871,7 @@ static inline int classify10(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-static inline int classify12(const QChar *s, bool qmlMode) {
+static inline int classify12(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 's') {
if (s[1].unicode() == 'y') {
if (s[2].unicode() == 'n') {
@@ -861,7 +884,7 @@ static inline int classify12(const QChar *s, bool qmlMode) {
if (s[9].unicode() == 'z') {
if (s[10].unicode() == 'e') {
if (s[11].unicode() == 'd') {
- return qmlMode ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER);
+ return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER);
}
}
}
@@ -877,18 +900,18 @@ static inline int classify12(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
-int Lexer::classify(const QChar *s, int n, bool qmlMode) {
+int Lexer::classify(const QChar *s, int n, int parseModeFlags) {
switch (n) {
- case 2: return classify2(s, qmlMode);
- case 3: return classify3(s, qmlMode);
- case 4: return classify4(s, qmlMode);
- case 5: return classify5(s, qmlMode);
- case 6: return classify6(s, qmlMode);
- case 7: return classify7(s, qmlMode);
- case 8: return classify8(s, qmlMode);
- case 9: return classify9(s, qmlMode);
- case 10: return classify10(s, qmlMode);
- case 12: return classify12(s, qmlMode);
+ case 2: return classify2(s, parseModeFlags);
+ case 3: return classify3(s, parseModeFlags);
+ case 4: return classify4(s, parseModeFlags);
+ case 5: return classify5(s, parseModeFlags);
+ case 6: return classify6(s, parseModeFlags);
+ case 7: return classify7(s, parseModeFlags);
+ case 8: return classify8(s, parseModeFlags);
+ case 9: return classify9(s, parseModeFlags);
+ case 10: return classify10(s, parseModeFlags);
+ case 12: return classify12(s, parseModeFlags);
default: return Lexer::T_IDENTIFIER;
} // switch
}
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index aab9025a08..ae016076b8 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -77,22 +77,15 @@ static inline QChar convertHex(QChar c1, QChar c2)
return QChar((convertHex(c1.unicode()) << 4) + convertHex(c2.unicode()));
}
-static inline QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4)
-{
- return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()),
- (convertHex(c1.unicode()) << 4) + convertHex(c2.unicode()));
-}
-
Lexer::Lexer(Engine *engine)
: _engine(engine)
, _codePtr(nullptr)
, _endPtr(nullptr)
- , _lastLinePtr(nullptr)
- , _tokenLinePtr(nullptr)
, _tokenStartPtr(nullptr)
, _char(QLatin1Char('\n'))
, _errorCode(NoError)
, _currentLineNumber(0)
+ , _currentColumnNumber(0)
, _tokenValue(0)
, _parenthesesState(IgnoreParentheses)
, _parenthesesCount(0)
@@ -101,6 +94,7 @@ Lexer::Lexer(Engine *engine)
, _tokenKind(0)
, _tokenLength(0)
, _tokenLine(0)
+ , _tokenColumn(0)
, _validTokenText(false)
, _prohibitAutomaticSemicolon(false)
, _restrictedKeyword(false)
@@ -137,14 +131,13 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_codePtr = code.unicode();
_endPtr = _codePtr + code.length();
- _lastLinePtr = _codePtr;
- _tokenLinePtr = _codePtr;
_tokenStartPtr = _codePtr;
_char = QLatin1Char('\n');
_errorCode = NoError;
_currentLineNumber = lineno;
+ _currentColumnNumber = 0;
_tokenValue = 0;
// parentheses state
@@ -156,6 +149,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_patternFlags = 0;
_tokenLength = 0;
_tokenLine = lineno;
+ _tokenColumn = 0;
_validTokenText = false;
_prohibitAutomaticSemicolon = false;
@@ -172,9 +166,10 @@ void Lexer::scanChar()
if (sequenceLength == 2)
_char = *_codePtr++;
- if (unsigned sequenceLength = isLineTerminatorSequence()) {
- _lastLinePtr = _codePtr + sequenceLength - 1; // points to the first character after the newline
+ ++_currentColumnNumber;
+ if (isLineTerminator()) {
++_currentLineNumber;
+ _currentColumnNumber = 0;
}
}
@@ -222,12 +217,32 @@ inline bool isBinop(int tok)
return false;
}
}
+
+int hexDigit(QChar c)
+{
+ if (c >= QLatin1Char('0') && c <= QLatin1Char('9'))
+ return c.unicode() - '0';
+ if (c >= QLatin1Char('a') && c <= QLatin1Char('f'))
+ return c.unicode() - 'a' + 10;
+ if (c >= QLatin1Char('A') && c <= QLatin1Char('F'))
+ return c.unicode() - 'A' + 10;
+ return -1;
+}
+
+int octalDigit(QChar c)
+{
+ if (c >= QLatin1Char('0') && c <= QLatin1Char('7'))
+ return c.unicode() - '0';
+ return -1;
+}
+
} // anonymous namespace
int Lexer::lex()
{
const int previousTokenKind = _tokenKind;
+ again:
_tokenSpell = QStringRef();
_tokenKind = scanToken();
_tokenLength = _codePtr - _tokenStartPtr - 1;
@@ -239,6 +254,9 @@ int Lexer::lex()
// update the flags
switch (_tokenKind) {
case T_LBRACE:
+ if (_bracesCount > 0)
+ ++_bracesCount;
+ Q_FALLTHROUGH();
case T_SEMICOLON:
case T_QUESTION:
case T_COLON:
@@ -266,9 +284,15 @@ int Lexer::lex()
case T_CONTINUE:
case T_BREAK:
case T_RETURN:
+ case T_YIELD:
case T_THROW:
_restrictedKeyword = true;
break;
+ case T_RBRACE:
+ if (_bracesCount > 0)
+ --_bracesCount;
+ if (_bracesCount == 0)
+ goto again;
} // switch
// update the parentheses state
@@ -295,39 +319,57 @@ int Lexer::lex()
return _tokenKind;
}
-bool Lexer::isUnicodeEscapeSequence(const QChar *chars)
-{
- if (isHexDigit(chars[0]) && isHexDigit(chars[1]) && isHexDigit(chars[2]) && isHexDigit(chars[3]))
- return true;
-
- return false;
-}
-
-QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok)
+uint Lexer::decodeUnicodeEscapeCharacter(bool *ok)
{
- if (_char == QLatin1Char('u') && isUnicodeEscapeSequence(&_codePtr[0])) {
- scanChar(); // skip u
+ Q_ASSERT(_char == QLatin1Char('u'));
+ scanChar(); // skip u
+ if (_codePtr + 4 <= _endPtr && isHexDigit(_char)) {
+ uint codePoint = 0;
+ for (int i = 0; i < 4; ++i) {
+ int digit = hexDigit(_char);
+ if (digit < 0)
+ goto error;
+ codePoint *= 16;
+ codePoint += digit;
+ scanChar();
+ }
- const QChar c1 = _char;
- scanChar();
+ *ok = true;
+ return codePoint;
+ } else if (_codePtr < _endPtr && _char == QLatin1Char('{')) {
+ scanChar(); // skip '{'
+ uint codePoint = 0;
+ if (!isHexDigit(_char))
+ // need at least one hex digit
+ goto error;
- const QChar c2 = _char;
- scanChar();
+ while (_codePtr <= _endPtr) {
+ int digit = hexDigit(_char);
+ if (digit < 0)
+ break;
+ codePoint *= 16;
+ codePoint += digit;
+ if (codePoint > 0x10ffff)
+ goto error;
+ scanChar();
+ }
- const QChar c3 = _char;
- scanChar();
+ if (_char != QLatin1Char('}'))
+ goto error;
- const QChar c4 = _char;
- scanChar();
+ scanChar(); // skip '}'
- if (ok)
- *ok = true;
- return convertUnicode(c1, c2, c3, c4);
+ *ok = true;
+ return codePoint;
}
+ error:
+ _errorCode = IllegalUnicodeEscapeSequence;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence");
+
*ok = false;
- return QChar();
+ return 0;
}
QChar Lexer::decodeHexEscapeCharacter(bool *ok)
@@ -351,15 +393,15 @@ QChar Lexer::decodeHexEscapeCharacter(bool *ok)
return QChar();
}
-static inline bool isIdentifierStart(QChar ch)
+static inline bool isIdentifierStart(uint ch)
{
// fast path for ascii
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
- (ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
+ if ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
ch == '$' || ch == '_')
return true;
- switch (ch.category()) {
+ switch (QChar::category(ch)) {
case QChar::Number_Letter:
case QChar::Letter_Uppercase:
case QChar::Letter_Lowercase:
@@ -373,17 +415,17 @@ static inline bool isIdentifierStart(QChar ch)
return false;
}
-static bool isIdentifierPart(QChar ch)
+static bool isIdentifierPart(uint ch)
{
// fast path for ascii
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
- (ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
- (ch.unicode() >= '0' && ch.unicode() <= '9') ||
+ if ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
ch == '$' || ch == '_' ||
- ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */)
+ ch == 0x200c /* ZWNJ */ || ch == 0x200d /* ZWJ */)
return true;
- switch (ch.category()) {
+ switch (QChar::category(ch)) {
case QChar::Mark_NonSpacing:
case QChar::Mark_SpacingCombining:
@@ -412,19 +454,23 @@ int Lexer::scanToken()
return tk;
}
+ if (_bracesCount == 0) {
+ // we're inside a Template string
+ return scanString(TemplateContinuation);
+ }
+
+
_terminator = false;
again:
_validTokenText = false;
- _tokenLinePtr = _lastLinePtr;
while (_char.isSpace()) {
- if (unsigned sequenceLength = isLineTerminatorSequence()) {
- _tokenLinePtr = _codePtr + sequenceLength - 1;
-
+ if (isLineTerminator()) {
if (_restrictedKeyword) {
// automatic semicolon insertion
_tokenLine = _currentLineNumber;
+ _tokenColumn = _currentColumnNumber;
_tokenStartPtr = _codePtr - 1;
return T_SEMICOLON;
} else {
@@ -438,6 +484,7 @@ again:
_tokenStartPtr = _codePtr - 1;
_tokenLine = _currentLineNumber;
+ _tokenColumn = _currentColumnNumber;
if (_codePtr > _endPtr)
return EOF_SYMBOL;
@@ -501,6 +548,9 @@ again:
return T_EQ_EQ_EQ;
}
return T_EQ_EQ;
+ } else if (_char == QLatin1Char('>')) {
+ scanChar();
+ return T_ARROW;
}
return T_EQ;
@@ -557,50 +607,18 @@ again:
return T_DIVIDE_;
case '.':
- if (_char.isDigit()) {
- QVarLengthArray<char,32> chars;
-
- chars.append(ch.unicode()); // append the `.'
-
- while (_char.isDigit()) {
- chars.append(_char.unicode());
+ if (isDecimalDigit(_char.unicode()))
+ return scanNumber(ch);
+ if (_char == QLatin1Char('.')) {
+ scanChar();
+ if (_char == QLatin1Char('.')) {
scanChar();
- }
-
- if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
- if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
- _codePtr[1].isDigit())) {
-
- chars.append(_char.unicode());
- scanChar(); // consume `e'
-
- if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
- chars.append(_char.unicode());
- scanChar(); // consume the sign
- }
-
- while (_char.isDigit()) {
- chars.append(_char.unicode());
- scanChar();
- }
- }
- }
-
- chars.append('\0');
-
- const char *begin = chars.constData();
- const char *end = nullptr;
- bool ok = false;
-
- _tokenValue = qstrtod(begin, &end, &ok);
-
- if (end - begin != chars.size() - 1) {
- _errorCode = IllegalExponentIndicator;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal syntax for exponential number");
+ return T_ELLIPSIS;
+ } else {
+ _errorCode = IllegalCharacter;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Unexpected token '.'");
return T_ERROR;
}
-
- return T_NUMERIC_LITERAL;
}
return T_DOT;
@@ -611,7 +629,7 @@ again:
} else if (_char == QLatin1Char('-')) {
scanChar();
- if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) {
+ if (_terminator && !_delimited && !_prohibitAutomaticSemicolon && _tokenKind != T_LPAREN) {
_stackToken = T_MINUS_MINUS;
return T_SEMICOLON;
}
@@ -629,7 +647,7 @@ again:
} else if (_char == QLatin1Char('+')) {
scanChar();
- if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) {
+ if (_terminator && !_delimited && !_prohibitAutomaticSemicolon && _tokenKind != T_LPAREN) {
_stackToken = T_PLUS_PLUS;
return T_SEMICOLON;
}
@@ -642,6 +660,13 @@ again:
if (_char == QLatin1Char('=')) {
scanChar();
return T_STAR_EQ;
+ } else if (_char == QLatin1Char('*')) {
+ scanChar();
+ if (_char == QLatin1Char('=')) {
+ scanChar();
+ return T_STAR_STAR_EQ;
+ }
+ return T_STAR_STAR;
}
return T_STAR;
@@ -676,141 +701,12 @@ again:
}
return T_NOT;
+ case '`':
+ _outerTemplateBraceCount.push(_bracesCount);
+ Q_FALLTHROUGH();
case '\'':
- case '"': {
- const QChar quote = ch;
- bool multilineStringLiteral = false;
-
- const QChar *startCode = _codePtr;
-
- if (_engine) {
- while (_codePtr <= _endPtr) {
- if (isLineTerminator()) {
- if (qmlMode())
- break;
- _errorCode = IllegalCharacter;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Stray newline in string literal");
- return T_ERROR;
- } else if (_char == QLatin1Char('\\')) {
- break;
- } else if (_char == quote) {
- _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode);
- scanChar();
-
- return T_STRING_LITERAL;
- }
- scanChar();
- }
- }
-
- _validTokenText = true;
- _tokenText.resize(0);
- startCode--;
- while (startCode != _codePtr - 1)
- _tokenText += *startCode++;
-
- while (_codePtr <= _endPtr) {
- if (unsigned sequenceLength = isLineTerminatorSequence()) {
- multilineStringLiteral = true;
- _tokenText += _char;
- if (sequenceLength == 2)
- _tokenText += *_codePtr;
- scanChar();
- } else if (_char == quote) {
- scanChar();
-
- if (_engine)
- _tokenSpell = _engine->newStringRef(_tokenText);
-
- return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL;
- } else if (_char == QLatin1Char('\\')) {
- scanChar();
- if (_codePtr > _endPtr) {
- _errorCode = IllegalEscapeSequence;
- _errorMessage = QCoreApplication::translate("QQmlParser", "End of file reached at escape sequence");
- return T_ERROR;
- }
-
- QChar u;
-
- switch (_char.unicode()) {
- // unicode escape sequence
- case 'u': {
- bool ok = false;
- u = decodeUnicodeEscapeCharacter(&ok);
- if (! ok) {
- _errorCode = IllegalUnicodeEscapeSequence;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence");
- return T_ERROR;
- }
- } break;
-
- // hex escape sequence
- case 'x': {
- bool ok = false;
- u = decodeHexEscapeCharacter(&ok);
- if (!ok) {
- _errorCode = IllegalHexadecimalEscapeSequence;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal hexadecimal escape sequence");
- return T_ERROR;
- }
- } break;
-
- // single character escape sequence
- case '\\': u = QLatin1Char('\\'); scanChar(); break;
- case '\'': u = QLatin1Char('\''); scanChar(); break;
- case '\"': u = QLatin1Char('\"'); scanChar(); break;
- case 'b': u = QLatin1Char('\b'); scanChar(); break;
- case 'f': u = QLatin1Char('\f'); scanChar(); break;
- case 'n': u = QLatin1Char('\n'); scanChar(); break;
- case 'r': u = QLatin1Char('\r'); scanChar(); break;
- case 't': u = QLatin1Char('\t'); scanChar(); break;
- case 'v': u = QLatin1Char('\v'); scanChar(); break;
-
- case '0':
- if (! _codePtr->isDigit()) {
- scanChar();
- u = QLatin1Char('\0');
- break;
- }
- Q_FALLTHROUGH();
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- _errorCode = IllegalEscapeSequence;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Octal escape sequences are not allowed");
- return T_ERROR;
-
- case '\r':
- case '\n':
- case 0x2028u:
- case 0x2029u:
- scanChar();
- continue;
-
- default:
- // non escape character
- u = _char;
- scanChar();
- }
-
- _tokenText += u;
- } else {
- _tokenText += _char;
- scanChar();
- }
- }
-
- _errorCode = UnclosedStringLiteral;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Unclosed string at end of line");
- return T_ERROR;
- }
+ case '"':
+ return scanString(ScanStringMode(ch.unicode()));
case '0':
case '1':
case '2':
@@ -824,28 +720,36 @@ again:
return scanNumber(ch);
default: {
- QChar c = ch;
+ uint c = ch.unicode();
bool identifierWithEscapeChars = false;
- if (c == QLatin1Char('\\') && _char == QLatin1Char('u')) {
+ if (QChar::isHighSurrogate(c) && QChar::isLowSurrogate(_char.unicode())) {
+ c = QChar::surrogateToUcs4(ushort(c), _char.unicode());
+ scanChar();
+ } else if (c == '\\' && _char == QLatin1Char('u')) {
identifierWithEscapeChars = true;
bool ok = false;
c = decodeUnicodeEscapeCharacter(&ok);
- if (! ok) {
- _errorCode = IllegalUnicodeEscapeSequence;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence");
+ if (!ok)
return T_ERROR;
- }
}
if (isIdentifierStart(c)) {
if (identifierWithEscapeChars) {
_tokenText.resize(0);
- _tokenText += c;
+ if (QChar::requiresSurrogates(c)) {
+ _tokenText += QChar(QChar::highSurrogate(c));
+ _tokenText += QChar(QChar::lowSurrogate(c));
+ } else {
+ _tokenText += QChar(c);
+ }
_validTokenText = true;
}
- while (true) {
- c = _char;
- if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) {
- if (! identifierWithEscapeChars) {
+ while (_codePtr <= _endPtr) {
+ c = _char.unicode();
+ if (QChar::isHighSurrogate(c) && QChar::isLowSurrogate(_codePtr->unicode())) {
+ scanChar();
+ c = QChar::surrogateToUcs4(ushort(c), _char.unicode());
+ } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) {
+ if (!identifierWithEscapeChars) {
identifierWithEscapeChars = true;
_tokenText.resize(0);
_tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1);
@@ -855,38 +759,52 @@ again:
scanChar(); // skip '\\'
bool ok = false;
c = decodeUnicodeEscapeCharacter(&ok);
- if (! ok) {
- _errorCode = IllegalUnicodeEscapeSequence;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence");
+ if (!ok)
return T_ERROR;
- }
- if (isIdentifierPart(c))
- _tokenText += c;
- continue;
- } else if (isIdentifierPart(c)) {
- if (identifierWithEscapeChars)
- _tokenText += c;
- scanChar();
+ if (!isIdentifierPart(c))
+ break;
+
+ if (identifierWithEscapeChars) {
+ if (QChar::requiresSurrogates(c)) {
+ _tokenText += QChar(QChar::highSurrogate(c));
+ _tokenText += QChar(QChar::lowSurrogate(c));
+ } else {
+ _tokenText += QChar(c);
+ }
+ }
continue;
}
- _tokenLength = _codePtr - _tokenStartPtr - 1;
+ if (!isIdentifierPart(c))
+ break;
- int kind = T_IDENTIFIER;
+ if (identifierWithEscapeChars) {
+ if (QChar::requiresSurrogates(c)) {
+ _tokenText += QChar(QChar::highSurrogate(c));
+ _tokenText += QChar(QChar::lowSurrogate(c));
+ } else {
+ _tokenText += QChar(c);
+ }
+ }
+ scanChar();
+ }
+
+ _tokenLength = _codePtr - _tokenStartPtr - 1;
- if (! identifierWithEscapeChars)
- kind = classify(_tokenStartPtr, _tokenLength, _qmlMode);
+ int kind = T_IDENTIFIER;
- if (_engine) {
- if (kind == T_IDENTIFIER && identifierWithEscapeChars)
- _tokenSpell = _engine->newStringRef(_tokenText);
- else
- _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength);
- }
+ if (!identifierWithEscapeChars)
+ kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags());
- return kind;
+ if (_engine) {
+ if (kind == T_IDENTIFIER && identifierWithEscapeChars)
+ _tokenSpell = _engine->newStringRef(_tokenText);
+ else
+ _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength);
}
+
+ return kind;
}
}
@@ -896,93 +814,278 @@ again:
return T_ERROR;
}
-int Lexer::scanNumber(QChar ch)
+int Lexer::scanString(ScanStringMode mode)
{
- if (ch != QLatin1Char('0')) {
- QVarLengthArray<char, 64> buf;
- buf += ch.toLatin1();
-
- QChar n = _char;
- const QChar *code = _codePtr;
- while (n.isDigit()) {
- buf += n.toLatin1();
- n = *code++;
- }
+ QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
+ bool multilineStringLiteral = false;
- if (n != QLatin1Char('.') && n != QLatin1Char('e') && n != QLatin1Char('E')) {
- if (code != _codePtr) {
- _codePtr = code - 1;
+ const QChar *startCode = _codePtr;
+
+ if (_engine) {
+ while (_codePtr <= _endPtr) {
+ if (isLineTerminator() && quote != QLatin1Char('`')) {
+ if (qmlMode())
+ break;
+ _errorCode = IllegalCharacter;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Stray newline in string literal");
+ return T_ERROR;
+ } else if (_char == QLatin1Char('\\')) {
+ break;
+ } else if (_char == '$' && quote == QLatin1Char('`')) {
+ break;
+ } else if (_char == quote) {
+ _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode);
scanChar();
+
+ if (quote == QLatin1Char('`'))
+ _bracesCount = _outerTemplateBraceCount.pop();
+
+ if (mode == TemplateHead)
+ return T_NO_SUBSTITUTION_TEMPLATE;
+ else if (mode == TemplateContinuation)
+ return T_TEMPLATE_TAIL;
+ else
+ return T_STRING_LITERAL;
}
- buf.append('\0');
- _tokenValue = strtod(buf.constData(), nullptr);
- return T_NUMERIC_LITERAL;
+ scanChar();
}
- } else if (_char.isDigit() && !qmlMode()) {
- _errorCode = IllegalCharacter;
- _errorMessage = QCoreApplication::translate("QQmlParser", "Decimal numbers can't start with '0'");
- return T_ERROR;
}
- QVarLengthArray<char,32> chars;
- chars.append(ch.unicode());
+ _validTokenText = true;
+ _tokenText.resize(0);
+ startCode--;
+ while (startCode != _codePtr - 1)
+ _tokenText += *startCode++;
+
+ while (_codePtr <= _endPtr) {
+ if (unsigned sequenceLength = isLineTerminatorSequence()) {
+ multilineStringLiteral = true;
+ _tokenText += _char;
+ if (sequenceLength == 2)
+ _tokenText += *_codePtr;
+ scanChar();
+ } else if (_char == mode) {
+ scanChar();
- if (ch == QLatin1Char('0') && (_char == QLatin1Char('x') || _char == QLatin1Char('X'))) {
- ch = _char; // remember the x or X to use it in the error message below.
+ if (_engine)
+ _tokenSpell = _engine->newStringRef(_tokenText);
- // parse hex integer literal
- chars.append(_char.unicode());
- scanChar(); // consume `x'
+ if (quote == QLatin1Char('`'))
+ _bracesCount = _outerTemplateBraceCount.pop();
- while (isHexDigit(_char)) {
- chars.append(_char.unicode());
+ if (mode == TemplateContinuation)
+ return T_TEMPLATE_TAIL;
+ else if (mode == TemplateHead)
+ return T_NO_SUBSTITUTION_TEMPLATE;
+
+ return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL;
+ } else if (quote == QLatin1Char('`') && _char == QLatin1Char('$') && *_codePtr == '{') {
+ scanChar();
+ scanChar();
+ _bracesCount = 1;
+ if (_engine)
+ _tokenSpell = _engine->newStringRef(_tokenText);
+
+ return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE);
+ } else if (_char == QLatin1Char('\\')) {
+ scanChar();
+ if (_codePtr > _endPtr) {
+ _errorCode = IllegalEscapeSequence;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "End of file reached at escape sequence");
+ return T_ERROR;
+ }
+
+ QChar u;
+
+ switch (_char.unicode()) {
+ // unicode escape sequence
+ case 'u': {
+ bool ok = false;
+ uint codePoint = decodeUnicodeEscapeCharacter(&ok);
+ if (!ok)
+ return T_ERROR;
+ if (QChar::requiresSurrogates(codePoint)) {
+ // need to use a surrogate pair
+ _tokenText += QChar(QChar::highSurrogate(codePoint));
+ u = QChar::lowSurrogate(codePoint);
+ } else {
+ u = codePoint;
+ }
+ } break;
+
+ // hex escape sequence
+ case 'x': {
+ bool ok = false;
+ u = decodeHexEscapeCharacter(&ok);
+ if (!ok) {
+ _errorCode = IllegalHexadecimalEscapeSequence;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal hexadecimal escape sequence");
+ return T_ERROR;
+ }
+ } break;
+
+ // single character escape sequence
+ case '\\': u = QLatin1Char('\\'); scanChar(); break;
+ case '\'': u = QLatin1Char('\''); scanChar(); break;
+ case '\"': u = QLatin1Char('\"'); scanChar(); break;
+ case 'b': u = QLatin1Char('\b'); scanChar(); break;
+ case 'f': u = QLatin1Char('\f'); scanChar(); break;
+ case 'n': u = QLatin1Char('\n'); scanChar(); break;
+ case 'r': u = QLatin1Char('\r'); scanChar(); break;
+ case 't': u = QLatin1Char('\t'); scanChar(); break;
+ case 'v': u = QLatin1Char('\v'); scanChar(); break;
+
+ case '0':
+ if (! _codePtr->isDigit()) {
+ scanChar();
+ u = QLatin1Char('\0');
+ break;
+ }
+ Q_FALLTHROUGH();
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ _errorCode = IllegalEscapeSequence;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Octal escape sequences are not allowed");
+ return T_ERROR;
+
+ case '\r':
+ case '\n':
+ case 0x2028u:
+ case 0x2029u:
+ scanChar();
+ continue;
+
+ default:
+ // non escape character
+ u = _char;
+ scanChar();
+ }
+
+ _tokenText += u;
+ } else {
+ _tokenText += _char;
scanChar();
}
+ }
- if (chars.size() < 3) {
- _errorCode = IllegalHexNumber;
- _errorMessage = QCoreApplication::translate("QQmlParser", "At least one hexadecimal digit is required after '0%1'").arg(ch);
+ _errorCode = UnclosedStringLiteral;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Unclosed string at end of line");
+ return T_ERROR;
+}
+
+int Lexer::scanNumber(QChar ch)
+{
+ if (ch == QLatin1Char('0')) {
+ if (_char == QLatin1Char('x') || _char == QLatin1Char('X')) {
+ ch = _char; // remember the x or X to use it in the error message below.
+
+ // parse hex integer literal
+ scanChar(); // consume 'x'
+
+ if (!isHexDigit(_char)) {
+ _errorCode = IllegalNumber;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "At least one hexadecimal digit is required after '0%1'").arg(ch);
+ return T_ERROR;
+ }
+
+ double d = 0.;
+ while (1) {
+ int digit = ::hexDigit(_char);
+ if (digit < 0)
+ break;
+ d *= 16;
+ d += digit;
+ scanChar();
+ }
+
+ _tokenValue = d;
+ return T_NUMERIC_LITERAL;
+ } else if (_char == QLatin1Char('o') || _char == QLatin1Char('O')) {
+ ch = _char; // remember the o or O to use it in the error message below.
+
+ // parse octal integer literal
+ scanChar(); // consume 'o'
+
+ if (!isOctalDigit(_char.unicode())) {
+ _errorCode = IllegalNumber;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "At least one octal digit is required after '0%1'").arg(ch);
+ return T_ERROR;
+ }
+
+ double d = 0.;
+ while (1) {
+ int digit = ::octalDigit(_char);
+ if (digit < 0)
+ break;
+ d *= 8;
+ d += digit;
+ scanChar();
+ }
+
+ _tokenValue = d;
+ return T_NUMERIC_LITERAL;
+ } else if (_char == QLatin1Char('b') || _char == QLatin1Char('B')) {
+ ch = _char; // remember the b or B to use it in the error message below.
+
+ // parse binary integer literal
+ scanChar(); // consume 'b'
+
+ if (_char.unicode() != '0' && _char.unicode() != '1') {
+ _errorCode = IllegalNumber;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "At least one binary digit is required after '0%1'").arg(ch);
+ return T_ERROR;
+ }
+
+ double d = 0.;
+ while (1) {
+ int digit = 0;
+ if (_char.unicode() == '1')
+ digit = 1;
+ else if (_char.unicode() != '0')
+ break;
+ d *= 2;
+ d += digit;
+ scanChar();
+ }
+
+ _tokenValue = d;
+ return T_NUMERIC_LITERAL;
+ } else if (_char.isDigit() && !qmlMode()) {
+ _errorCode = IllegalCharacter;
+ _errorMessage = QCoreApplication::translate("QQmlParser", "Decimal numbers can't start with '0'");
return T_ERROR;
}
-
- _tokenValue = integerFromString(chars.constData(), chars.size(), 16);
- return T_NUMERIC_LITERAL;
}
// decimal integer literal
- while (_char.isDigit()) {
- chars.append(_char.unicode());
- scanChar(); // consume the digit
- }
-
- if (_char == QLatin1Char('.')) {
- chars.append(_char.unicode());
- scanChar(); // consume `.'
+ QVarLengthArray<char,32> chars;
+ chars.append(ch.unicode());
+ if (ch != QLatin1Char('.')) {
while (_char.isDigit()) {
chars.append(_char.unicode());
- scanChar();
+ scanChar(); // consume the digit
}
- if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
- if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
- _codePtr[1].isDigit())) {
-
- chars.append(_char.unicode());
- scanChar(); // consume `e'
+ if (_char == QLatin1Char('.')) {
+ chars.append(_char.unicode());
+ scanChar(); // consume `.'
+ }
+ }
- if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) {
- chars.append(_char.unicode());
- scanChar(); // consume the sign
- }
+ while (_char.isDigit()) {
+ chars.append(_char.unicode());
+ scanChar();
+ }
- while (_char.isDigit()) {
- chars.append(_char.unicode());
- scanChar();
- }
- }
- }
- } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
+ if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) {
if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) &&
_codePtr[1].isDigit())) {
@@ -1001,12 +1104,6 @@ int Lexer::scanNumber(QChar ch)
}
}
- if (chars.length() == 1) {
- // if we ended up with a single digit, then it was a '0'
- _tokenValue = 0;
- return T_NUMERIC_LITERAL;
- }
-
chars.append('\0');
const char *begin = chars.constData();
@@ -1174,16 +1271,6 @@ bool Lexer::isOctalDigit(ushort c)
return (c >= '0' && c <= '7');
}
-int Lexer::tokenEndLine() const
-{
- return _currentLineNumber;
-}
-
-int Lexer::tokenEndColumn() const
-{
- return _codePtr - _lastLinePtr;
-}
-
QString Lexer::tokenText() const
{
if (_validTokenText)
@@ -1256,6 +1343,7 @@ static const int uriTokens[] = {
QQmlJSGrammar::T_FUNCTION,
QQmlJSGrammar::T_IF,
QQmlJSGrammar::T_IN,
+ QQmlJSGrammar::T_OF,
QQmlJSGrammar::T_INSTANCEOF,
QQmlJSGrammar::T_NEW,
QQmlJSGrammar::T_NULL,
diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h
index 11d8081713..a6ac8cb354 100644
--- a/src/qml/parser/qqmljslexer_p.h
+++ b/src/qml/parser/qqmljslexer_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include "qqmljsglobal_p.h"
-#include "qqmljsgrammar_p.h"
+#include <private/qqmljsglobal_p.h>
+#include <private/qqmljsgrammar_p.h>
#include <QtCore/qstring.h>
+#include <QtCore/qstack.h>
QT_QML_BEGIN_NAMESPACE
@@ -62,32 +63,7 @@ namespace QQmlJS {
class Engine;
class DiagnosticMessage;
-
-class QML_PARSER_EXPORT Directives {
-public:
- virtual ~Directives() {}
-
- virtual void pragmaLibrary()
- {
- }
-
- virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
- {
- Q_UNUSED(jsfile);
- Q_UNUSED(module);
- Q_UNUSED(line);
- Q_UNUSED(column);
- }
-
- virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column)
- {
- Q_UNUSED(uri);
- Q_UNUSED(version);
- Q_UNUSED(module);
- Q_UNUSED(line);
- Q_UNUSED(column);
- }
-};
+class Directives;
class QML_PARSER_EXPORT Lexer: public QQmlJSGrammar
{
@@ -97,10 +73,7 @@ public:
T_BOOLEAN = T_RESERVED_WORD,
T_BYTE = T_RESERVED_WORD,
T_CHAR = T_RESERVED_WORD,
- T_CLASS = T_RESERVED_WORD,
T_DOUBLE = T_RESERVED_WORD,
- T_EXPORT = T_RESERVED_WORD,
- T_EXTENDS = T_RESERVED_WORD,
T_FINAL = T_RESERVED_WORD,
T_FLOAT = T_RESERVED_WORD,
T_GOTO = T_RESERVED_WORD,
@@ -113,8 +86,6 @@ public:
T_PRIVATE = T_RESERVED_WORD,
T_PROTECTED = T_RESERVED_WORD,
T_SHORT = T_RESERVED_WORD,
- T_STATIC = T_RESERVED_WORD,
- T_SUPER = T_RESERVED_WORD,
T_SYNCHRONIZED = T_RESERVED_WORD,
T_THROWS = T_RESERVED_WORD,
T_TRANSIENT = T_RESERVED_WORD,
@@ -124,7 +95,7 @@ public:
enum Error {
NoError,
IllegalCharacter,
- IllegalHexNumber,
+ IllegalNumber,
UnclosedStringLiteral,
IllegalEscapeSequence,
IllegalUnicodeEscapeSequence,
@@ -145,10 +116,29 @@ public:
RegExp_Multiline = 0x04
};
+ enum ParseModeFlags {
+ QmlMode = 0x1,
+ YieldIsKeyword = 0x2,
+ StaticIsKeyword = 0x4
+ };
+
public:
Lexer(Engine *engine);
+ int parseModeFlags() const {
+ int flags = 0;
+ if (qmlMode())
+ flags |= QmlMode|StaticIsKeyword;
+ if (yieldIsKeyWord())
+ flags |= YieldIsKeyword;
+ if (_staticIsKeyword)
+ flags |= StaticIsKeyword;
+ return flags;
+ }
+
bool qmlMode() const;
+ bool yieldIsKeyWord() const { return _generatorLevel != 0; }
+ void setStaticIsKeyword(bool b) { _staticIsKeyword = b; }
QString code() const;
void setCode(const QString &code, int lineno, bool qmlMode = true);
@@ -166,10 +156,7 @@ public:
int tokenLength() const { return _tokenLength; }
int tokenStartLine() const { return _tokenLine; }
- int tokenStartColumn() const { return _tokenStartPtr - _tokenLinePtr + 1; }
-
- int tokenEndLine() const;
- int tokenEndColumn() const;
+ int tokenStartColumn() const { return _tokenColumn; }
inline QStringRef tokenSpell() const { return _tokenSpell; }
double tokenValue() const { return _tokenValue; }
@@ -188,13 +175,23 @@ public:
BalancedParentheses
};
+ void enterGeneratorBody() { ++_generatorLevel; }
+ void leaveGeneratorBody() { --_generatorLevel; }
+
protected:
- int classify(const QChar *s, int n, bool qmlMode);
+ static int classify(const QChar *s, int n, int parseModeFlags);
private:
inline void scanChar();
int scanToken();
int scanNumber(QChar ch);
+ enum ScanStringMode {
+ SingleQuote = '\'',
+ DoubleQuote = '"',
+ TemplateHead = '`',
+ TemplateContinuation = 0
+ };
+ int scanString(ScanStringMode mode);
bool isLineTerminator() const;
unsigned isLineTerminatorSequence() const;
@@ -202,10 +199,9 @@ private:
static bool isDecimalDigit(ushort c);
static bool isHexDigit(QChar c);
static bool isOctalDigit(ushort c);
- static bool isUnicodeEscapeSequence(const QChar *chars);
void syncProhibitAutomaticSemicolon();
- QChar decodeUnicodeEscapeCharacter(bool *ok);
+ uint decodeUnicodeEscapeCharacter(bool *ok);
QChar decodeHexEscapeCharacter(bool *ok);
private:
@@ -218,26 +214,30 @@ private:
const QChar *_codePtr;
const QChar *_endPtr;
- const QChar *_lastLinePtr;
- const QChar *_tokenLinePtr;
const QChar *_tokenStartPtr;
QChar _char;
Error _errorCode;
int _currentLineNumber;
+ int _currentColumnNumber;
double _tokenValue;
// parentheses state
ParenthesesState _parenthesesState;
int _parenthesesCount;
+ // template string stack
+ QStack<int> _outerTemplateBraceCount;
+ int _bracesCount = -1;
+
int _stackToken;
int _patternFlags;
int _tokenKind;
int _tokenLength;
int _tokenLine;
+ int _tokenColumn;
bool _validTokenText;
bool _prohibitAutomaticSemicolon;
@@ -246,6 +246,8 @@ private:
bool _followsClosingBrace;
bool _delimited;
bool _qmlMode;
+ int _generatorLevel = 0;
+ bool _staticIsKeyword = false;
};
} // end of namespace QQmlJS
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index ef443d96bc..9a480f1224 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -83,6 +83,7 @@ public:
free(_blocks);
}
+ qDeleteAll(strings);
}
inline void *allocate(size_t size)
@@ -104,6 +105,11 @@ public:
template <typename Tp> Tp *New() { return new (this->allocate(sizeof(Tp))) Tp(); }
+ QStringRef newString(const QString &string) {
+ strings.append(new QString(string));
+ return QStringRef(strings.last());
+ }
+
private:
Q_NEVER_INLINE void *allocate_helper(size_t size)
{
@@ -143,6 +149,7 @@ private:
int _blockCount = -1;
char *_ptr = nullptr;
char *_end = nullptr;
+ QVector<QString*> strings;
enum
{
@@ -153,12 +160,10 @@ private:
class QML_PARSER_EXPORT Managed
{
- Managed(const Managed &other);
- void operator = (const Managed &other);
-
+ Q_DISABLE_COPY(Managed)
public:
- Managed() {}
- ~Managed() {}
+ Managed() = default;
+ ~Managed() = default;
void *operator new(size_t size, MemoryPool *pool) { return pool->allocate(size); }
void operator delete(void *) {}
diff --git a/src/qml/parser/qqmljsparser.cpp b/src/qml/parser/qqmljsparser.cpp
deleted file mode 100644
index 24b04b02f9..0000000000
--- a/src/qml/parser/qqmljsparser.cpp
+++ /dev/null
@@ -1,2010 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmljsengine_p.h"
-#include "qqmljslexer_p.h"
-#include "qqmljsast_p.h"
-#include "qqmljsmemorypool_p.h"
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qcoreapplication.h>
-
-#include <string.h>
-
-
-
-#include "qqmljsparser_p.h"
-
-#include <QtCore/qvarlengtharray.h>
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is automatically generated from qqmljs.g.
-// Changes should be made to that file, not here. Any change to this file will
-// be lost!
-//
-// To regenerate this file, run:
-// qlalr --no-debug --no-lines --qt qqmljs.g
-//
-
-using namespace QQmlJS;
-
-QT_QML_BEGIN_NAMESPACE
-
-void Parser::reallocateStack()
-{
- if (! stack_size)
- stack_size = 128;
- else
- stack_size <<= 1;
-
- sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value)));
- state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int)));
- location_stack = reinterpret_cast<AST::SourceLocation*> (realloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
- string_stack = reinterpret_cast<QStringRef*> (realloc(static_cast<void *>(string_stack), stack_size * sizeof(QStringRef)));
-}
-
-Parser::Parser(Engine *engine):
- driver(engine),
- pool(engine->pool()),
- tos(0),
- stack_size(0),
- sym_stack(nullptr),
- state_stack(nullptr),
- location_stack(nullptr),
- string_stack(nullptr),
- program(nullptr),
- yylval(0),
- first_token(nullptr),
- last_token(nullptr)
-{
-}
-
-Parser::~Parser()
-{
- if (stack_size) {
- free(sym_stack);
- free(state_stack);
- free(location_stack);
- free(string_stack);
- }
-}
-
-static inline AST::SourceLocation location(Lexer *lexer)
-{
- AST::SourceLocation loc;
- loc.offset = lexer->tokenOffset();
- loc.length = lexer->tokenLength();
- loc.startLine = lexer->tokenStartLine();
- loc.startColumn = lexer->tokenStartColumn();
- return loc;
-}
-
-AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
-{
- QVarLengthArray<QStringRef, 4> nameIds;
- QVarLengthArray<AST::SourceLocation, 4> locations;
-
- AST::ExpressionNode *it = expr;
- while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
- nameIds.append(m->name);
- locations.append(m->identifierToken);
- it = m->base;
- }
-
- if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
- AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name);
- q->identifierToken = idExpr->identifierToken;
-
- AST::UiQualifiedId *currentId = q;
- for (int i = nameIds.size() - 1; i != -1; --i) {
- currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]);
- currentId->identifierToken = locations[i];
- }
-
- return currentId->finish();
- }
-
- return nullptr;
-}
-
-AST::UiQualifiedPragmaId *Parser::reparseAsQualifiedPragmaId(AST::ExpressionNode *expr)
-{
- if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) {
- AST::UiQualifiedPragmaId *q = new (pool) AST::UiQualifiedPragmaId(idExpr->name);
- q->identifierToken = idExpr->identifierToken;
-
- return q->finish();
- }
-
- return nullptr;
-}
-
-
-bool Parser::parse(int startToken)
-{
- Lexer *lexer = driver->lexer();
- bool hadErrors = false;
- int yytoken = -1;
- int action = 0;
-
- token_buffer[0].token = startToken;
- first_token = &token_buffer[0];
- if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) {
- Directives ignoreDirectives;
- Directives *directives = driver->directives();
- if (!directives)
- directives = &ignoreDirectives;
- DiagnosticMessage error;
- if (!lexer->scanDirectives(directives, &error)) {
- diagnostic_messages.append(error);
- return false;
- }
- token_buffer[1].token = lexer->tokenKind();
- token_buffer[1].dval = lexer->tokenValue();
- token_buffer[1].loc = location(lexer);
- token_buffer[1].spell = lexer->tokenSpell();
- last_token = &token_buffer[2];
- } else {
- last_token = &token_buffer[1];
- }
-
- tos = -1;
- program = nullptr;
-
- do {
- if (++tos == stack_size)
- reallocateStack();
-
- state_stack[tos] = action;
-
- _Lcheck_token:
- if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
- yyprevlloc = yylloc;
-
- if (first_token == last_token) {
- yytoken = lexer->lex();
- yylval = lexer->tokenValue();
- yytokenspell = lexer->tokenSpell();
- yylloc = location(lexer);
- } else {
- yytoken = first_token->token;
- yylval = first_token->dval;
- yytokenspell = first_token->spell;
- yylloc = first_token->loc;
- ++first_token;
- }
- }
-
- action = t_action(action, yytoken);
- if (action > 0) {
- if (action != ACCEPT_STATE) {
- yytoken = -1;
- sym(1).dval = yylval;
- stringRef(1) = yytokenspell;
- loc(1) = yylloc;
- } else {
- --tos;
- return ! hadErrors;
- }
- } else if (action < 0) {
- const int r = -action - 1;
- tos -= rhs[r];
-
- switch (r) {
-
-case 0: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
-
-case 1: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
-
-case 2: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
-
-case 3: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
-
-case 4: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
-
-case 5: {
- sym(1).Node = sym(2).Node;
- program = sym(1).Node;
-} break;
-
-case 6: {
- sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiHeaderItemList,
- sym(2).UiObjectMemberList->finish());
-} break;
-
-case 8: {
- sym(1).Node = sym(1).UiHeaderItemList->finish();
-} break;
-
-case 9: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiPragma);
-} break;
-
-case 10: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiImport);
-} break;
-
-case 11: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiPragma);
-} break;
-
-case 12: {
- sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiImport);
-} break;
-
-case 16: {
- sym(1).UiPragma->semicolonToken = loc(2);
-} break;
-
-case 18: {
- sym(1).UiImport->semicolonToken = loc(2);
-} break;
-
-case 20: {
- sym(1).UiImport->versionToken = loc(2);
- sym(1).UiImport->semicolonToken = loc(3);
-} break;
-
-case 22: {
- sym(1).UiImport->versionToken = loc(2);
- sym(1).UiImport->asToken = loc(3);
- sym(1).UiImport->importIdToken = loc(4);
- sym(1).UiImport->importId = stringRef(4);
- sym(1).UiImport->semicolonToken = loc(5);
-} break;
-
-case 24: {
- sym(1).UiImport->asToken = loc(2);
- sym(1).UiImport->importIdToken = loc(3);
- sym(1).UiImport->importId = stringRef(3);
- sym(1).UiImport->semicolonToken = loc(4);
-} break;
-
-case 25: {
- AST::UiPragma *node = nullptr;
-
- if (AST::UiQualifiedPragmaId *qualifiedId = reparseAsQualifiedPragmaId(sym(2).Expression)) {
- node = new (pool) AST::UiPragma(qualifiedId);
- }
-
- sym(1).Node = node;
-
- if (node) {
- node->pragmaToken = loc(1);
- } else {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
- QLatin1String("Expected a qualified name id")));
-
- return false; // ### remove me
- }
-} break;
-
-case 26: {
- AST::UiImport *node = nullptr;
-
- if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
- node = new (pool) AST::UiImport(importIdLiteral->value);
- node->fileNameToken = loc(2);
- } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
- node = new (pool) AST::UiImport(qualifiedId);
- node->fileNameToken = loc(2);
- }
-
- sym(1).Node = node;
-
- if (node) {
- node->importToken = loc(1);
- } else {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
- QLatin1String("Expected a qualified name id or a string literal")));
-
- return false; // ### remove me
- }
-} break;
-
-case 27: {
- sym(1).Node = nullptr;
-} break;
-
-case 28: {
- sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
-} break;
-
-case 29: {
- sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
-} break;
-
-case 30: {
- AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList(
- sym(1).UiObjectMemberList, sym(2).UiObjectMember);
- sym(1).Node = node;
-} break;
-
-case 31: {
- sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember);
-} break;
-
-case 32: {
- AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList(
- sym(1).UiArrayMemberList, sym(3).UiObjectMember);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 33: {
- AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)nullptr);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 34: {
- AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish());
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 35: {
- AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId,
- sym(2).UiObjectInitializer);
- sym(1).Node = node;
-} break;
-
-case 37: {
- AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding(
- sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
- node->colonToken = loc(2);
- node->lbracketToken = loc(3);
- node->rbracketToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 38: {
- AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding(
- sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 39: {
- AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding(
- sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer);
- node->colonToken = loc(2);
- node->hasOnToken = true;
- sym(1).Node = node;
-} break;
-
-case 47:
-{
- AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding(
- sym(1).UiQualifiedId, sym(3).Statement);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 48: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 49: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 50: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 51: {
- AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(sym(1).UiQualifiedId, stringRef(3));
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 52: {
- sym(1).Node = nullptr;
-} break;
-
-case 53: {
- sym(1).Node = sym(1).UiParameterList->finish ();
-} break;
-
-case 54: {
- AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiQualifiedId->finish(), stringRef(2));
- node->propertyTypeToken = loc(1);
- node->identifierToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 55: {
- AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(3).UiQualifiedId->finish(), stringRef(4));
- node->propertyTypeToken = loc(3);
- node->commaToken = loc(2);
- node->identifierToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 57: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2));
- node->type = AST::UiPublicMember::Signal;
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(2);
- node->parameters = sym(4).UiParameterList;
- node->semicolonToken = loc(6);
- sym(1).Node = node;
-} break;
-
-case 59: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2));
- node->type = AST::UiPublicMember::Signal;
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(2);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 61: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
- node->typeModifier = stringRef(2);
- node->propertyToken = loc(1);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(6);
- node->semicolonToken = loc(7);
- sym(1).Node = node;
-} break;
-
-case 63: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(3);
- node->semicolonToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 65: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
- node->isDefaultMember = true;
- node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 67: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7));
- node->isDefaultMember = true;
- node->defaultToken = loc(1);
- node->typeModifier = stringRef(3);
- node->propertyToken = loc(2);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(7);
- node->semicolonToken = loc(8);
- sym(1).Node = node;
-} break;
-
-case 68: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3),
- sym(5).Statement);
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(3);
- node->colonToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 69: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4),
- sym(6).Statement);
- node->isReadonlyMember = true;
- node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 70: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4),
- sym(6).Statement);
- node->isDefaultMember = true;
- node->defaultToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->colonToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 71: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6));
- node->typeModifier = stringRef(2);
- node->propertyToken = loc(1);
- node->typeModifierToken = loc(2);
- node->typeToken = loc(4);
- node->identifierToken = loc(6);
- node->semicolonToken = loc(7); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6));
- propertyName->identifierToken = loc(6);
- propertyName->next = nullptr;
-
- AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(
- propertyName, sym(9).UiArrayMemberList->finish());
- binding->colonToken = loc(7);
- binding->lbracketToken = loc(8);
- binding->rbracketToken = loc(10);
-
- node->binding = binding;
-
- sym(1).Node = node;
-} break;
-
-case 72: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3));
- node->propertyToken = loc(1);
- node->typeToken = loc(2);
- node->identifierToken = loc(3);
- node->semicolonToken = loc(4); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3));
- propertyName->identifierToken = loc(3);
- propertyName->next = nullptr;
-
- AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
- propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer);
- binding->colonToken = loc(4);
-
- node->binding = binding;
-
- sym(1).Node = node;
-} break;
-
-case 73: {
- AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4));
- node->isReadonlyMember = true;
- node->readonlyToken = loc(1);
- node->propertyToken = loc(2);
- node->typeToken = loc(3);
- node->identifierToken = loc(4);
- node->semicolonToken = loc(5); // insert a fake ';' before ':'
-
- AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4));
- propertyName->identifierToken = loc(4);
- propertyName->next = nullptr;
-
- AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding(
- propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer);
- binding->colonToken = loc(5);
-
- node->binding = binding;
-
- sym(1).Node = node;
-} break;
-
-case 74: {
- sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
-} break;
-
-case 75: {
- sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
-} break;
-
-case 76: {
- AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish());
- enumDeclaration->enumToken = loc(1);
- enumDeclaration->rbraceToken = loc(5);
- sym(1).Node = enumDeclaration;
- break;
-}
-
-case 77: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1));
- node->memberToken = loc(1);
- sym(1).Node = node;
- break;
-}
-
-case 78: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1), sym(3).dval);
- node->memberToken = loc(1);
- node->valueToken = loc(3);
- sym(1).Node = node;
- break;
-}
-
-case 79: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3));
- node->memberToken = loc(3);
- sym(1).Node = node;
- break;
-}
-
-case 80: {
- AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3), sym(5).dval);
- node->memberToken = loc(3);
- node->valueToken = loc(5);
- sym(1).Node = node;
- break;
-}
-
-case 88: {
- AST::ThisExpression *node = new (pool) AST::ThisExpression();
- node->thisToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 89: {
- AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 90: {
- AST::NullExpression *node = new (pool) AST::NullExpression();
- node->nullToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 91: {
- AST::TrueLiteral *node = new (pool) AST::TrueLiteral();
- node->trueToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 92: {
- AST::FalseLiteral *node = new (pool) AST::FalseLiteral();
- node->falseToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 93: {
- AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval);
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
-case 94:
-case 95: {
- AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1));
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 96: {
- bool rx = lexer->scanRegExp(Lexer::NoPrefix);
- if (!rx) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
- return false; // ### remove me
- }
-
- loc(1).length = lexer->tokenLength();
- yylloc = loc(1); // adjust the location of the current token
-
- AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral(
- driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 97: {
- bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
- if (!rx) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
- return false;
- }
-
- loc(1).length = lexer->tokenLength();
- yylloc = loc(1); // adjust the location of the current token
-
- AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral(
- driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
- node->literalToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 98: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) nullptr);
- node->lbracketToken = loc(1);
- node->rbracketToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 99: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish());
- node->lbracketToken = loc(1);
- node->rbracketToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 100: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ());
- node->lbracketToken = loc(1);
- node->rbracketToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 101: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
- (AST::Elision *) nullptr);
- node->lbracketToken = loc(1);
- node->commaToken = loc(3);
- node->rbracketToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 102: {
- AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
- sym(4).Elision->finish());
- node->lbracketToken = loc(1);
- node->commaToken = loc(3);
- node->rbracketToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 103: {
- AST::ObjectLiteral *node = nullptr;
- if (sym(2).Node)
- node = new (pool) AST::ObjectLiteral(
- sym(2).PropertyAssignmentList->finish ());
- else
- node = new (pool) AST::ObjectLiteral();
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 104: {
- AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral(
- sym(2).PropertyAssignmentList->finish ());
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 105: {
- AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression);
- node->lparenToken = loc(1);
- node->rparenToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 106: {
- if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
- QLatin1String("Ignored annotation")));
-
- sym(1).Expression = mem->base;
- }
-
- if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
- sym(1).UiQualifiedId = qualifiedId;
- } else {
- sym(1).UiQualifiedId = nullptr;
-
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
- QLatin1String("Expected a qualified name id")));
-
- return false; // ### recover
- }
-} break;
-
-case 107: {
- sym(1).Node = new (pool) AST::ElementList((AST::Elision *) nullptr, sym(1).Expression);
-} break;
-
-case 108: {
- sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression);
-} break;
-
-case 109: {
- AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList,
- (AST::Elision *) nullptr, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 110: {
- AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(),
- sym(4).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 111: {
- AST::Elision *node = new (pool) AST::Elision();
- node->commaToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 112: {
- AST::Elision *node = new (pool) AST::Elision(sym(1).Elision);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 113: {
- AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue(
- sym(1).PropertyName, sym(3).Expression);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 114: {
- AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(
- sym(2).PropertyName, sym(6).FunctionBody);
- node->getSetToken = loc(1);
- node->lparenToken = loc(3);
- node->rparenToken = loc(4);
- node->lbraceToken = loc(5);
- node->rbraceToken = loc(7);
- sym(1).Node = node;
-} break;
-
-case 115: {
- AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(
- sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody);
- node->getSetToken = loc(1);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
- sym(1).Node = node;
-} break;
-
-case 116: {
- sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment);
-} break;
-
-case 117: {
- AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList(
- sym(1).PropertyAssignmentList, sym(3).PropertyAssignment);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 118: {
- AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 119: {
- AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1));
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 120: {
- AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval);
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 121: {
- AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1));
- node->propertyNameToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 159: {
- AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
- node->lbracketToken = loc(2);
- node->rbracketToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 160: {
- AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
- node->dotToken = loc(2);
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 161: {
- AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList);
- node->newToken = loc(1);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 163: {
- AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression);
- node->newToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 164: {
- AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 165: {
- AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 166: {
- AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
- node->lbracketToken = loc(2);
- node->rbracketToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 167: {
- AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
- node->dotToken = loc(2);
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 168: {
- sym(1).Node = nullptr;
-} break;
-
-case 169: {
- sym(1).Node = sym(1).ArgumentList->finish();
-} break;
-
-case 170: {
- sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression);
-} break;
-
-case 171: {
- AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 175: {
- AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression);
- node->incrementToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 176: {
- AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression);
- node->decrementToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 178: {
- AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression);
- node->deleteToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 179: {
- AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression);
- node->voidToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 180: {
- AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression);
- node->typeofToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 181: {
- AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression);
- node->incrementToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 182: {
- AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression);
- node->decrementToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 183: {
- AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression);
- node->plusToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 184: {
- AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression);
- node->minusToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 185: {
- AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression);
- node->tildeToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 186: {
- AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression);
- node->notToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 188: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Mul, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 189: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Div, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 190: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Mod, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 192: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Add, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 193: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Sub, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 195: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::LShift, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 196: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::RShift, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 197: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::URShift, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 199: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Lt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 200: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Gt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 201: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Le, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 202: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Ge, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 203: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::InstanceOf, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 204: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::In, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 206: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Lt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 207: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Gt, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 208: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Le, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 209: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Ge, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 210: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::InstanceOf, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 212: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Equal, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 213: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::NotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 214: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 215: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictNotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 217: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Equal, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 218: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::NotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 219: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 220: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::StrictNotEqual, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 222: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitAnd, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 224: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitAnd, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 226: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitXor, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 228: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitXor, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 230: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitOr, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 232: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::BitOr, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 234: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::And, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 236: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::And, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 238: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Or, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 240: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- QSOperator::Or, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 242: {
- AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression,
- sym(3).Expression, sym(5).Expression);
- node->questionToken = loc(2);
- node->colonToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 244: {
- AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression,
- sym(3).Expression, sym(5).Expression);
- node->questionToken = loc(2);
- node->colonToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 246: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- sym(2).ival, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 248: {
- AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression,
- sym(2).ival, sym(3).Expression);
- node->operatorToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 249: {
- sym(1).ival = QSOperator::Assign;
-} break;
-
-case 250: {
- sym(1).ival = QSOperator::InplaceMul;
-} break;
-
-case 251: {
- sym(1).ival = QSOperator::InplaceDiv;
-} break;
-
-case 252: {
- sym(1).ival = QSOperator::InplaceMod;
-} break;
-
-case 253: {
- sym(1).ival = QSOperator::InplaceAdd;
-} break;
-
-case 254: {
- sym(1).ival = QSOperator::InplaceSub;
-} break;
-
-case 255: {
- sym(1).ival = QSOperator::InplaceLeftShift;
-} break;
-
-case 256: {
- sym(1).ival = QSOperator::InplaceRightShift;
-} break;
-
-case 257: {
- sym(1).ival = QSOperator::InplaceURightShift;
-} break;
-
-case 258: {
- sym(1).ival = QSOperator::InplaceAnd;
-} break;
-
-case 259: {
- sym(1).ival = QSOperator::InplaceXor;
-} break;
-
-case 260: {
- sym(1).ival = QSOperator::InplaceOr;
-} break;
-
-case 262: {
- AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 263: {
- sym(1).Node = nullptr;
-} break;
-
-case 266: {
- AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 267: {
- sym(1).Node = nullptr;
-} break;
-
-case 284: {
- AST::Block *node = new (pool) AST::Block(sym(2).StatementList);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 285: {
- sym(1).Node = new (pool) AST::StatementList(sym(1).Statement);
-} break;
-
-case 286: {
- sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement);
-} break;
-
-case 287: {
- sym(1).Node = nullptr;
-} break;
-
-case 288: {
- sym(1).Node = sym(1).StatementList->finish ();
-} break;
-
-case 290: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- if (sym(1).ival == T_LET)
- s = AST::VariableDeclaration::BlockScope;
- else if (sym(1).ival == T_CONST)
- s = AST::VariableDeclaration::ReadOnlyBlockScope;
-
- AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s));
- node->declarationKindToken = loc(1);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 291: {
- sym(1).ival = T_LET;
-} break;
-
-case 292: {
- sym(1).ival = T_CONST;
-} break;
-
-case 293: {
- sym(1).ival = T_VAR;
-} break;
-
-case 294: {
- sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
-} break;
-
-case 295: {
- AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList(
- sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
- node->commaToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 296: {
- sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
-} break;
-
-case 297: {
- sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
-} break;
-
-case 298: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 299: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s);
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 300: {
- // ### TODO: AST for initializer
- sym(1) = sym(2);
-} break;
-
-case 301: {
- sym(1).Node = nullptr;
-} break;
-
-case 303: {
- // ### TODO: AST for initializer
- sym(1) = sym(2);
-} break;
-
-case 304: {
- sym(1).Node = nullptr;
-} break;
-
-case 306: {
- AST::EmptyStatement *node = new (pool) AST::EmptyStatement();
- node->semicolonToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 308: {
- AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 309: {
- AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement);
- node->ifToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- node->elseToken = loc(6);
- sym(1).Node = node;
-} break;
-
-case 310: {
- AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement);
- node->ifToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 313: {
- AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression);
- node->doToken = loc(1);
- node->whileToken = loc(3);
- node->lparenToken = loc(4);
- node->rparenToken = loc(6);
- node->semicolonToken = loc(7);
- sym(1).Node = node;
-} break;
-
-case 314: {
- AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement);
- node->whileToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 315: {
- AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression,
- sym(5).Expression, sym(7).Expression, sym(9).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->firstSemicolonToken = loc(4);
- node->secondSemicolonToken = loc(6);
- node->rparenToken = loc(8);
- sym(1).Node = node;
-} break;
-
-case 316: {
- AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope;
- AST::LocalForStatement *node = new (pool) AST::LocalForStatement(
- sym(4).VariableDeclarationList->finish(s), sym(6).Expression,
- sym(8).Expression, sym(10).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->varToken = loc(3);
- node->firstSemicolonToken = loc(5);
- node->secondSemicolonToken = loc(7);
- node->rparenToken = loc(9);
- sym(1).Node = node;
-} break;
-
-case 317: {
- AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression,
- sym(5).Expression, sym(7).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->inToken = loc(4);
- node->rparenToken = loc(6);
- sym(1).Node = node;
-} break;
-
-case 318: {
- AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement(
- sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
- node->forToken = loc(1);
- node->lparenToken = loc(2);
- node->varToken = loc(3);
- node->inToken = loc(5);
- node->rparenToken = loc(7);
- sym(1).Node = node;
-} break;
-
-case 320: {
- AST::ContinueStatement *node = new (pool) AST::ContinueStatement();
- node->continueToken = loc(1);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 322: {
- AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2));
- node->continueToken = loc(1);
- node->identifierToken = loc(2);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 324: {
- AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef());
- node->breakToken = loc(1);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 326: {
- AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2));
- node->breakToken = loc(1);
- node->identifierToken = loc(2);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 328: {
- AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression);
- node->returnToken = loc(1);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 329: {
- AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement);
- node->withToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 330: {
- AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock);
- node->switchToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 331: {
- AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 332: {
- AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
- node->lbraceToken = loc(1);
- node->rbraceToken = loc(5);
- sym(1).Node = node;
-} break;
-
-case 333: {
- sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause);
-} break;
-
-case 334: {
- sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause);
-} break;
-
-case 335: {
- sym(1).Node = nullptr;
-} break;
-
-case 336: {
- sym(1).Node = sym(1).CaseClauses->finish ();
-} break;
-
-case 337: {
- AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList);
- node->caseToken = loc(1);
- node->colonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 338: {
- AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList);
- node->defaultToken = loc(1);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 339: {
- AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement);
- node->identifierToken = loc(1);
- node->colonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 341: {
- AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression);
- node->throwToken = loc(1);
- node->semicolonToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 342: {
- AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch);
- node->tryToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 343: {
- AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally);
- node->tryToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 344: {
- AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally);
- node->tryToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 345: {
- AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block);
- node->catchToken = loc(1);
- node->lparenToken = loc(2);
- node->identifierToken = loc(3);
- node->rparenToken = loc(4);
- sym(1).Node = node;
-} break;
-
-case 346: {
- AST::Finally *node = new (pool) AST::Finally(sym(2).Block);
- node->finallyToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 348: {
- AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement();
- node->debuggerToken = loc(1);
- node->semicolonToken = loc(2);
- sym(1).Node = node;
-} break;
-
-case 350: {
- AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
- node->functionToken = loc(1);
- node->identifierToken = loc(2);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
- sym(1).Node = node;
-} break;
-
-case 351: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
- node->functionToken = loc(1);
- if (! stringRef(2).isNull())
- node->identifierToken = loc(2);
- node->lparenToken = loc(3);
- node->rparenToken = loc(5);
- node->lbraceToken = loc(6);
- node->rbraceToken = loc(8);
- sym(1).Node = node;
-} break;
-
-case 352: {
- AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody);
- node->functionToken = loc(1);
- node->lparenToken = loc(2);
- node->rparenToken = loc(4);
- node->lbraceToken = loc(5);
- node->rbraceToken = loc(7);
- sym(1).Node = node;
-} break;
-
-case 353: {
- AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1));
- node->identifierToken = loc(1);
- sym(1).Node = node;
-} break;
-
-case 354: {
- AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3));
- node->commaToken = loc(2);
- node->identifierToken = loc(3);
- sym(1).Node = node;
-} break;
-
-case 355: {
- sym(1).Node = nullptr;
-} break;
-
-case 356: {
- sym(1).Node = sym(1).FormalParameterList->finish ();
-} break;
-
-case 357: {
- sym(1).Node = nullptr;
-} break;
-
-case 359: {
- sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ());
-} break;
-
-case 361: {
- sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ());
-} break;
-
-case 362: {
- sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement);
-} break;
-
-case 363: {
- sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement);
-} break;
-
-case 364: {
- sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement);
-} break;
-
-case 365: {
- sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration);
-} break;
-
-case 366: {
- sym(1).Node = nullptr;
-} break;
-
- } // switch
- action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
- } // if
- } while (action != 0);
-
- if (first_token == last_token) {
- const int errorState = state_stack[tos];
-
- // automatic insertion of `;'
- if (yytoken != -1 && ((t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken))
- || t_action(errorState, T_COMPATIBILITY_SEMICOLON))) {
- SavedToken &tk = token_buffer[0];
- tk.token = yytoken;
- tk.dval = yylval;
- tk.spell = yytokenspell;
- tk.loc = yylloc;
-
- yylloc = yyprevlloc;
- yylloc.offset += yylloc.length;
- yylloc.startColumn += yylloc.length;
- yylloc.length = 0;
-
- //const QString msg = QCoreApplication::translate("QQmlParser", "Missing `;'");
- //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
-
- first_token = &token_buffer[0];
- last_token = &token_buffer[1];
-
- yytoken = T_SEMICOLON;
- yylval = 0;
-
- action = errorState;
-
- goto _Lcheck_token;
- }
-
- hadErrors = true;
-
- token_buffer[0].token = yytoken;
- token_buffer[0].dval = yylval;
- token_buffer[0].spell = yytokenspell;
- token_buffer[0].loc = yylloc;
-
- token_buffer[1].token = yytoken = lexer->lex();
- token_buffer[1].dval = yylval = lexer->tokenValue();
- token_buffer[1].spell = yytokenspell = lexer->tokenSpell();
- token_buffer[1].loc = yylloc = location(lexer);
-
- if (t_action(errorState, yytoken)) {
- QString msg;
- int token = token_buffer[0].token;
- if (token < 0 || token >= TERMINAL_COUNT)
- msg = QCoreApplication::translate("QQmlParser", "Syntax error");
- else
- msg = QCoreApplication::translate("QQmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
-
- action = errorState;
- goto _Lcheck_token;
- }
-
- static int tokens[] = {
- T_PLUS,
- T_EQ,
-
- T_COMMA,
- T_COLON,
- T_SEMICOLON,
-
- T_RPAREN, T_RBRACKET, T_RBRACE,
-
- T_NUMERIC_LITERAL,
- T_IDENTIFIER,
-
- T_LPAREN, T_LBRACKET, T_LBRACE,
-
- EOF_SYMBOL
- };
-
- for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
- int a = t_action(errorState, *tk);
- if (a > 0 && t_action(a, yytoken)) {
- const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
-
- yytoken = *tk;
- yylval = 0;
- yylloc = token_buffer[0].loc;
- yylloc.length = 0;
-
- first_token = &token_buffer[0];
- last_token = &token_buffer[2];
-
- action = errorState;
- goto _Lcheck_token;
- }
- }
-
- for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
- if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM ||
- tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION ||
- tk == T_FEED_JS_SOURCE_ELEMENT)
- continue;
-
- int a = t_action(errorState, tk);
- if (a > 0 && t_action(a, yytoken)) {
- const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
-
- yytoken = tk;
- yylval = 0;
- yylloc = token_buffer[0].loc;
- yylloc.length = 0;
-
- action = errorState;
- goto _Lcheck_token;
- }
- }
-
- const QString msg = QCoreApplication::translate("QQmlParser", "Syntax error");
- diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
- }
-
- return false;
-}
-
-QT_QML_END_NAMESPACE
-
-
diff --git a/src/qml/parser/qqmljsparser_p.h b/src/qml/parser/qqmljsparser_p.h
deleted file mode 100644
index b4aecd2f08..0000000000
--- a/src/qml/parser/qqmljsparser_p.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-//
-// 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.
-//
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is automatically generated from qqmljs.g.
-// Changes should be made to that file, not here. Any change to this file will
-// be lost!
-//
-// To regenerate this file, run:
-// qlalr --no-debug --no-lines --qt qqmljs.g
-//
-
-#ifndef QQMLJSPARSER_P_H
-#define QQMLJSPARSER_P_H
-
-#include "qqmljsglobal_p.h"
-#include "qqmljsgrammar_p.h"
-#include "qqmljsast_p.h"
-#include "qqmljsengine_p.h"
-
-#include <QtCore/qlist.h>
-#include <QtCore/qstring.h>
-
-QT_QML_BEGIN_NAMESPACE
-
-namespace QQmlJS {
-
-class Engine;
-
-class QML_PARSER_EXPORT Parser: protected QQmlJSGrammar
-{
-public:
- union Value {
- int ival;
- double dval;
- AST::ArgumentList *ArgumentList;
- AST::CaseBlock *CaseBlock;
- AST::CaseClause *CaseClause;
- AST::CaseClauses *CaseClauses;
- AST::Catch *Catch;
- AST::DefaultClause *DefaultClause;
- AST::ElementList *ElementList;
- AST::Elision *Elision;
- AST::ExpressionNode *Expression;
- AST::Finally *Finally;
- AST::FormalParameterList *FormalParameterList;
- AST::FunctionBody *FunctionBody;
- AST::FunctionDeclaration *FunctionDeclaration;
- AST::Node *Node;
- AST::PropertyName *PropertyName;
- AST::PropertyAssignment *PropertyAssignment;
- AST::PropertyAssignmentList *PropertyAssignmentList;
- AST::SourceElement *SourceElement;
- AST::SourceElements *SourceElements;
- AST::Statement *Statement;
- AST::StatementList *StatementList;
- AST::Block *Block;
- AST::VariableDeclaration *VariableDeclaration;
- AST::VariableDeclarationList *VariableDeclarationList;
-
- AST::UiProgram *UiProgram;
- AST::UiHeaderItemList *UiHeaderItemList;
- AST::UiPragma *UiPragma;
- AST::UiImport *UiImport;
- AST::UiParameterList *UiParameterList;
- AST::UiPublicMember *UiPublicMember;
- AST::UiObjectDefinition *UiObjectDefinition;
- AST::UiObjectInitializer *UiObjectInitializer;
- AST::UiObjectBinding *UiObjectBinding;
- AST::UiScriptBinding *UiScriptBinding;
- AST::UiArrayBinding *UiArrayBinding;
- AST::UiObjectMember *UiObjectMember;
- AST::UiObjectMemberList *UiObjectMemberList;
- AST::UiArrayMemberList *UiArrayMemberList;
- AST::UiQualifiedId *UiQualifiedId;
- AST::UiQualifiedPragmaId *UiQualifiedPragmaId;
- AST::UiEnumMemberList *UiEnumMemberList;
- };
-
-public:
- Parser(Engine *engine);
- ~Parser();
-
- // parse a UI program
- bool parse() { return parse(T_FEED_UI_PROGRAM); }
- bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
- bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
- bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); }
- bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
- bool parseProgram() { return parse(T_FEED_JS_PROGRAM); }
-
- AST::UiProgram *ast() const
- { return AST::cast<AST::UiProgram *>(program); }
-
- AST::Statement *statement() const
- {
- if (! program)
- return nullptr;
-
- return program->statementCast();
- }
-
- AST::ExpressionNode *expression() const
- {
- if (! program)
- return nullptr;
-
- return program->expressionCast();
- }
-
- AST::UiObjectMember *uiObjectMember() const
- {
- if (! program)
- return nullptr;
-
- return program->uiObjectMemberCast();
- }
-
- AST::Node *rootNode() const
- { return program; }
-
- QList<DiagnosticMessage> diagnosticMessages() const
- { return diagnostic_messages; }
-
- inline DiagnosticMessage diagnosticMessage() const
- {
- for (const DiagnosticMessage &d : diagnostic_messages) {
- if (d.kind != DiagnosticMessage::Warning)
- return d;
- }
-
- return DiagnosticMessage();
- }
-
- inline QString errorMessage() const
- { return diagnosticMessage().message; }
-
- inline int errorLineNumber() const
- { return diagnosticMessage().loc.startLine; }
-
- inline int errorColumnNumber() const
- { return diagnosticMessage().loc.startColumn; }
-
-protected:
- bool parse(int startToken);
-
- void reallocateStack();
-
- inline Value &sym(int index)
- { return sym_stack [tos + index - 1]; }
-
- inline QStringRef &stringRef(int index)
- { return string_stack [tos + index - 1]; }
-
- inline AST::SourceLocation &loc(int index)
- { return location_stack [tos + index - 1]; }
-
- AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
- AST::UiQualifiedPragmaId *reparseAsQualifiedPragmaId(AST::ExpressionNode *expr);
-
-protected:
- Engine *driver;
- MemoryPool *pool;
- int tos;
- int stack_size;
- Value *sym_stack;
- int *state_stack;
- AST::SourceLocation *location_stack;
- QStringRef *string_stack;
-
- AST::Node *program;
-
- // error recovery
- enum { TOKEN_BUFFER_SIZE = 3 };
-
- struct SavedToken {
- int token;
- double dval;
- AST::SourceLocation loc;
- QStringRef spell;
- };
-
- double yylval;
- QStringRef yytokenspell;
- AST::SourceLocation yylloc;
- AST::SourceLocation yyprevlloc;
-
- SavedToken token_buffer[TOKEN_BUFFER_SIZE];
- SavedToken *first_token;
- SavedToken *last_token;
-
- QList<DiagnosticMessage> diagnostic_messages;
-};
-
-} // end of namespace QQmlJS
-
-
-
-#define J_SCRIPT_REGEXPLITERAL_RULE1 96
-
-#define J_SCRIPT_REGEXPLITERAL_RULE2 97
-
-QT_QML_END_NAMESPACE
-
-
-
-#endif // QQMLJSPARSER_P_H
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 2137877427..a76a87b153 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -31,7 +31,7 @@ DEFINES += QT_NO_FOREACH
!equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") {
QML_COMPILE_HASH = $$tag
} else:exists($$PWD/../../.git) {
- commit = $$system(git describe --tags --always --long --dirty)
+ commit = $$system(git rev-parse HEAD)
QML_COMPILE_HASH = $$commit
}
compile_hash_contents = \
@@ -73,7 +73,7 @@ include(jsruntime/jsruntime.pri)
include(jit/jit.pri)
include(qml/qml.pri)
include(debugger/debugger.pri)
-qtConfig(animation) {
+qtConfig(qml-animation) {
include(animations/animations.pri)
}
include(types/types.pri)
diff --git a/src/qml/qml/ftw/qflagpointer_p.h b/src/qml/qml/ftw/qflagpointer_p.h
index 91ce74bec9..71b41cd30b 100644
--- a/src/qml/qml/ftw/qflagpointer_p.h
+++ b/src/qml/qml/ftw/qflagpointer_p.h
@@ -82,6 +82,8 @@ public:
inline T *data() const;
+ inline explicit operator bool() const;
+
private:
quintptr ptr_value = 0;
@@ -230,6 +232,12 @@ T *QFlagPointer<T>::data() const
return (T *)(ptr_value & ~FlagsMask);
}
+template<typename T>
+QFlagPointer<T>::operator bool() const
+{
+ return data() != nullptr;
+}
+
template<typename T, typename T2>
QBiPointer<T, T2>::QBiPointer()
{
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 3cfb345b30..d32a08e0f5 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -85,19 +85,23 @@ public:
inline QQmlRefPointer();
inline QQmlRefPointer(T *, Mode m = AddRef);
inline QQmlRefPointer(const QQmlRefPointer<T> &);
+ inline QQmlRefPointer(QQmlRefPointer<T> &&);
inline ~QQmlRefPointer();
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
+ inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o);
inline bool isNull() const { return !o; }
inline T* operator->() const { return o; }
inline T& operator*() const { return *o; }
- inline operator T*() const { return o; }
+ explicit inline operator bool() const { return o != nullptr; }
inline T* data() const { return o; }
inline QQmlRefPointer<T> &adopt(T *);
+ inline T* take() { T *res = o; o = nullptr; return res; }
+
private:
T *o;
};
@@ -156,6 +160,12 @@ QQmlRefPointer<T>::QQmlRefPointer(const QQmlRefPointer<T> &other)
if (o) o->addref();
}
+template <class T>
+QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other)
+ : o(other.take())
+{
+}
+
template<class T>
QQmlRefPointer<T>::~QQmlRefPointer()
{
@@ -171,6 +181,14 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other)
return *this;
}
+template <class T>
+QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other)
+{
+ QQmlRefPointer<T> m(std::move(other));
+ qSwap(o, m.o);
+ return *this;
+}
+
/*!
Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
of the callers reference of other.
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 412dc6cba2..6d69294c17 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -20,7 +20,6 @@ SOURCES += \
$$PWD/qqmlinfo.cpp \
$$PWD/qqmlerror.cpp \
$$PWD/qqmlvaluetype.cpp \
- $$PWD/qqmlxmlhttprequest.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
$$PWD/qqmlnotifier.cpp \
@@ -31,7 +30,6 @@ SOURCES += \
$$PWD/qqmlextensionplugin.cpp \
$$PWD/qqmlimport.cpp \
$$PWD/qqmllist.cpp \
- $$PWD/qqmllocale.cpp \
$$PWD/qqmljavascriptexpression.cpp \
$$PWD/qqmlabstractbinding.cpp \
$$PWD/qqmlvaluetypeproxybinding.cpp \
@@ -85,7 +83,6 @@ HEADERS += \
$$PWD/qqmldata_p.h \
$$PWD/qqmlerror.h \
$$PWD/qqmlvaluetype_p.h \
- $$PWD/qqmlxmlhttprequest_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
$$PWD/qqmlpropertyindex_p.h \
@@ -99,7 +96,6 @@ HEADERS += \
$$PWD/qqmlimport_p.h \
$$PWD/qqmlextensionplugin.h \
$$PWD/qqmlscriptstring_p.h \
- $$PWD/qqmllocale_p.h \
$$PWD/qqmlcomponentattached_p.h \
$$PWD/qqmljavascriptexpression_p.h \
$$PWD/qqmlabstractbinding_p.h \
@@ -120,5 +116,22 @@ HEADERS += \
$$PWD/qqmldelayedcallqueue_p.h \
$$PWD/qqmlloggingcategory_p.h
+qtConfig(qml-xml-http-request) {
+ HEADERS += \
+ $$PWD/qqmlxmlhttprequest_p.h
+
+ SOURCES += \
+ $$PWD/qqmlxmlhttprequest.cpp
+
+}
+
+qtConfig(qml-locale) {
+ HEADERS += \
+ $$PWD/qqmllocale_p.h
+
+ SOURCES += \
+ $$PWD/qqmllocale.cpp
+}
+
include(ftw/ftw.pri)
include(v8/v8.pri)
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 213f23cd98..2a8e236905 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -645,6 +645,8 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i
return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type);
}
+int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QObject)
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 30a18440a8..a4b3f1f4e4 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -337,7 +337,7 @@ protected:
class QQmlTranslationBinding : public GenericBinding<QMetaType::QString> {
public:
- QQmlTranslationBinding(QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Binding *binding)
+ QQmlTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
setCompilationUnit(compilationUnit);
m_binding = binding;
@@ -374,11 +374,13 @@ public:
}
}
+ bool hasDependencies() const override final { return true; }
+
private:
const QV4::CompiledData::Binding *m_binding;
};
-QQmlBinding *QQmlBinding::createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
{
QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
@@ -663,6 +665,11 @@ QVector<QQmlProperty> QQmlBinding::dependencies() const
return dependencies;
}
+bool QQmlBinding::hasDependencies() const
+{
+ return !permanentGuards.isEmpty() || !activeGuards.isEmpty() || translationsCaptured();
+}
+
class QObjectPointerBinding: public QQmlNonbindingBinding
{
QQmlMetaObject targetMetaObject;
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index a1295bd0ac..f192de4342 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -79,7 +79,7 @@ public:
const QString &url = QString(), quint16 lineNumber = 0);
static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
- static QQmlBinding *createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding,
+ static QQmlBinding *createTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, const QV4::CompiledData::Binding *binding,
QObject *obj, QQmlContextData *ctxt);
~QQmlBinding() override;
@@ -118,6 +118,7 @@ public:
* Call this method from the UI thread.
*/
QVector<QQmlProperty> dependencies() const;
+ virtual bool hasDependencies() const;
protected:
virtual void doUpdate(const DeleteWatcher &watcher,
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 8885e69161..9b43ea0531 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -334,7 +334,7 @@ void QQmlComponentPrivate::typeDataProgress(QQmlTypeData *, qreal p)
emit q->progressChanged(p);
}
-void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data)
+void QQmlComponentPrivate::fromTypeData(const QQmlRefPointer<QQmlTypeData> &data)
{
url = data->finalUrl();
compilationUnit = data->compilationUnit();
@@ -343,15 +343,12 @@ void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data)
Q_ASSERT(data->isError());
state.errors = data->errors();
}
-
- data->release();
}
void QQmlComponentPrivate::clear()
{
if (typeData) {
typeData->unregisterCallback(this);
- typeData->release();
typeData = nullptr;
}
@@ -387,7 +384,7 @@ QQmlComponent::~QQmlComponent()
if (d->typeData) {
d->typeData->unregisterCallback(d);
- d->typeData->release();
+ d->typeData = nullptr;
}
}
@@ -580,7 +577,7 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url)
d->url = url;
- QQmlTypeData *typeData = QQmlEnginePrivate::get(d->engine)->typeLoader.getType(data, url);
+ QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(d->engine)->typeLoader.getType(data, url);
if (typeData->isCompleteOrError()) {
d->fromTypeData(typeData);
@@ -667,7 +664,7 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio
? QQmlTypeLoader::Asynchronous
: QQmlTypeLoader::PreferSynchronous;
- QQmlTypeData *data = QQmlEnginePrivate::get(engine)->typeLoader.getType(url, loaderMode);
+ QQmlRefPointer<QQmlTypeData> data = QQmlEnginePrivate::get(engine)->typeLoader.getType(url, loaderMode);
if (data->isCompleteOrError()) {
fromTypeData(data);
@@ -848,13 +845,10 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
// Do not create infinite recursion in object creation
static const int maxCreationDepth = 10;
- if (++creationDepth.localData() >= maxCreationDepth) {
+ if (creationDepth.localData() >= maxCreationDepth) {
qWarning("QQmlComponent: Component creation is recursing - aborting");
- --creationDepth.localData();
return nullptr;
}
- Q_ASSERT(creationDepth.localData() >= 1);
- depthIncreased = true;
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
@@ -878,10 +872,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
ddata->rootObjectInCreation = false;
- } else {
- Q_ASSERT(creationDepth.localData() >= 1);
- --creationDepth.localData();
- depthIncreased = false;
}
return rv;
@@ -955,14 +945,10 @@ void QQmlComponent::completeCreate()
void QQmlComponentPrivate::completeCreate()
{
if (state.completePending) {
+ ++creationDepth.localData();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
complete(ep, &state);
- }
-
- if (depthIncreased) {
- Q_ASSERT(creationDepth.localData() >= 1);
--creationDepth.localData();
- depthIncreased = false;
}
}
@@ -1421,9 +1407,9 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QQmlComponentExtension *e = componentExtension(args->v4engine());
- QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocObject<QV4::QmlIncubatorObject>(mode));
+ QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocate<QV4::QmlIncubatorObject>(mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
- r->setPrototype(p);
+ r->setPrototypeOf(p);
if (!valuemap->isUndefined())
r->d()->valuemap.set(scope.engine, valuemap);
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 2a8d36f317..9b2db4bccf 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -79,7 +79,7 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public
public:
QQmlComponentPrivate()
- : typeData(nullptr), progress(0.), start(-1), engine(nullptr), creationContext(nullptr), depthIncreased(false) {}
+ : progress(0.), start(-1), engine(nullptr), creationContext(nullptr) {}
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
@@ -95,11 +95,11 @@ public:
QQmlContextData *context,
QQmlContextData *forContext);
- QQmlTypeData *typeData;
+ QQmlRefPointer<QQmlTypeData> typeData;
void typeDataReady(QQmlTypeData *) override;
void typeDataProgress(QQmlTypeData *, qreal) override;
- void fromTypeData(QQmlTypeData *data);
+ void fromTypeData(const QQmlRefPointer<QQmlTypeData> &data);
QUrl url;
qreal progress;
@@ -136,7 +136,6 @@ public:
QQmlEngine *engine;
QQmlGuardedContextData creationContext;
- bool depthIncreased;
void clear();
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 59fefde893..2468de6857 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -232,7 +232,7 @@ public:
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QVector<DeferredData *> deferredData;
- void deferData(int objectIndex, QV4::CompiledData::CompilationUnit *, QQmlContextData *);
+ void deferData(int objectIndex, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, QQmlContextData *);
void releaseDeferredData();
QV4::WeakValue jsWrapper;
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 5bcf5cd586..61cb0a9065 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -71,7 +71,7 @@ void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *en
*jsCallData->thisObject = QV4::Encode::undefined();
for (int i = 0; i < argCount; i++) {
- jsCallData->args[i] = array->getIndexed(i);
+ jsCallData->args[i] = array->get(i);
}
callback->call(jsCallData);
@@ -186,7 +186,7 @@ void QQmlDelayedCallQueue::storeAnyArguments(DelayedFunctionCall &dfc, const QV4
QV4::ScopedArrayObject array(scope, engine->newArrayObject(length));
uint i = 0;
for (int j = offset, ej = argc; j < ej; ++i, ++j)
- array->putIndexed(i, argv[j]);
+ array->put(i, argv[j]);
dfc.m_args.set(engine, array);
}
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 4cca8a4d58..8c89cf0e61 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -107,6 +107,7 @@ bool QQmlDirParser::parse(const QString &source)
_components.clear();
_scripts.clear();
_designerSupported = false;
+ _className.clear();
quint16 lineNumber = 0;
bool firstLine = true;
@@ -196,7 +197,8 @@ bool QQmlDirParser::parse(const QString &source)
continue;
}
- // Ignore these. qmlimportscanner uses them.
+ _className = sections[1];
+
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
@@ -377,6 +379,11 @@ bool QQmlDirParser::designerSupported() const
return _designerSupported;
}
+QString QQmlDirParser::className() const
+{
+ return _className;
+}
+
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
const QString output = QStringLiteral("{%1 %2.%3}").
diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h
index 820c40238d..d7e29813d1 100644
--- a/src/qml/qml/qqmldirparser_p.h
+++ b/src/qml/qml/qqmldirparser_p.h
@@ -135,6 +135,8 @@ public:
QList<TypeInfo> typeInfos() const;
#endif
+ QString className() const;
+
private:
bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true);
void reportError(quint16 line, quint16 column, const QString &message);
@@ -150,6 +152,7 @@ private:
#ifdef QT_CREATOR
QList<TypeInfo> _typeInfos;
#endif
+ QString _className;
};
typedef QHash<QString,QQmlDirParser::Component> QQmlDirComponents;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index c6b39581a7..119120572c 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -48,7 +48,6 @@
#include "qqmlcomponent.h"
#include "qqmlvme_p.h"
#include "qqmlstringconverters_p.h"
-#include "qqmlxmlhttprequest_p.h"
#include "qqmlscriptstring.h"
#include "qqmlglobal_p.h"
#include "qqmlcomponent_p.h"
@@ -79,13 +78,17 @@
#include <private/qobject_p.h>
#include <private/qmetaobject_p.h>
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <private/qqmlbind_p.h>
#include <private/qqmlconnections_p.h>
-#if QT_CONFIG(animation)
+#if QT_CONFIG(qml_animation)
#include <private/qqmltimer_p.h>
#endif
+#if QT_CONFIG(qml_list_model)
#include <private/qqmllistmodel_p.h>
+#endif
#include <private/qqmlplatform_p.h>
#include <private/qquickpackage_p.h>
#if QT_CONFIG(qml_delegate_model)
@@ -219,21 +222,25 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8
qmlRegisterType<QQmlConnections,1>(uri, versionMajor, (versionMinor < 3 ? 3 : versionMinor), "Connections"); //Only available in >=2.3
qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
-#if QT_CONFIG(animation)
+#if QT_CONFIG(qml_animation)
qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
#endif
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
qmlRegisterType<QQmlInstanceModel>();
- qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "LoggingCategory"); //Only available in >=2.8
+
+ qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, 8, "LoggingCategory"); //Only available in >=2.8
+ qmlRegisterType<QQmlLoggingCategory,1>(uri, versionMajor, 12, "LoggingCategory"); //Only available in >=2.12
}
// These QtQuick types' implementation resides in the QtQml module
void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
{
+#if QT_CONFIG(qml_list_model)
qmlRegisterType<QQmlListElement>(uri, versionMajor, versionMinor, "ListElement"); // Now in QtQml.Models, here for compatibility
qmlRegisterCustomType<QQmlListModel>(uri, versionMajor, versionMinor, "ListModel", new QQmlListModelParser); // Now in QtQml.Models, here for compatibility
+#endif
qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
qmlRegisterType<QQuickPackage>(uri, versionMajor, versionMinor, "Package");
#if QT_CONFIG(qml_delegate_model)
@@ -250,7 +257,9 @@ void QQmlEnginePrivate::defineQtQuick2Module()
// register the QtQuick2 types which are implemented in the QtQml module.
registerQtQuick2Types("QtQuick",2,0);
+#if QT_CONFIG(qml_locale)
qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+#endif
// Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward
qmlRegisterModule("QtQuick", 2, QT_VERSION_MINOR);
@@ -951,7 +960,9 @@ void QQmlEnginePrivate::init()
if (baseModulesUninitialized) {
qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
+#if QT_CONFIG(qml_locale)
qmlRegisterUncreatableType<QQmlLocale>("QtQml", 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+#endif
// Auto-increment the import to stay in sync with ALL future QtQml minor versions from 5.11 onward
qmlRegisterModule("QtQml", 2, QT_VERSION_MINOR);
@@ -1365,6 +1376,71 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
}
/*!
+ \fn template<typename T> T QQmlEngine::singletonInstance(int qmlTypeId)
+
+ Returns the instance of a singleton type that was registered under \a qmlTypeId.
+
+ The template argument \e T may be either QJSValue or a pointer to a QObject-derived
+ type and depends on how the singleton was registered. If no instance of \e T has been
+ created yet, it is created now. If \a qmlTypeId does not represent a valid singleton
+ type, either a default constructed QJSValue or a \c nullptr is returned.
+
+ QObject* example:
+ \code
+ class MySingleton : public QObject {
+ Q_OBJECT
+ static int typeId;
+ // ...
+ };
+
+ // Register with QObject* callback
+ MySingleton::typeId = qmlRegisterSingletonType<MySingleton>(...);
+
+ // Retrieve as QObject*
+ QQmlEngine engine;
+ MySingleton* instance = engine.singletonInstance<MySingleton*>(MySingleton::typeId);
+ \endcode
+
+ QJSValue example:
+ \code
+ // Register with QJSValue callback
+ int typeId = qmlRegisterSingletonType(...);
+
+ // Retrieve as QJSValue
+ QQmlEngine engine;
+ QJSValue instance = engine.singletonInstance<QJSValue>(typeId);
+ \endcode
+
+ It is recommended to store the QML type id during registration, e.g. as a static member
+ in the singleton class. Otherwise, a costly lookup via qmlTypeId() has to be performed
+ at run-time.
+
+ \sa qmlRegisterSingletonType(), qmlTypeId()
+ \since 5.12
+*/
+template<>
+QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId)
+{
+ QQmlType type = QQmlMetaType::qmlType(qmlTypeId, QQmlMetaType::TypeIdCategory::QmlType);
+
+ if (!type.isValid() || !type.isSingleton())
+ return QJSValue();
+
+ QQmlType::SingletonInstanceInfo* info = type.singletonInstanceInfo();
+ info->init(this);
+
+ if (QObject* o = info->qobjectApi(this))
+ return this->newQObject(o);
+ else {
+ QJSValue value = info->scriptApi(this);
+ if (!value.isUndefined())
+ return value;
+ }
+
+ return QJSValue();
+}
+
+/*!
Refreshes all binding expressions that use strings marked for translation.
Call this function after you have installed a new translator with
@@ -1699,7 +1775,7 @@ void QQmlData::NotifyList::layout()
todo = nullptr;
}
-void QQmlData::deferData(int objectIndex, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *context)
+void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *context)
{
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = objectIndex;
@@ -2266,7 +2342,7 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->rootPropertyCache());
+ return QQmlMetaObject((*iter)->rootPropertyCache().data());
} else {
QQmlType type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type.baseMetaObject());
@@ -2278,7 +2354,7 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->rootPropertyCache());
+ return QQmlMetaObject((*iter)->rootPropertyCache().data());
} else {
QQmlType type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type.metaObject());
@@ -2290,7 +2366,7 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->rootPropertyCache();
+ return (*iter)->rootPropertyCache().data();
} else {
QQmlType type = QQmlMetaType::qmlType(t);
locker.unlock();
@@ -2303,7 +2379,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVe
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->rootPropertyCache();
+ return (*iter)->rootPropertyCache().data();
} else {
QQmlType type = QQmlMetaType::qmlType(t);
locker.unlock();
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 73ad2754c8..871e6bd9b4 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -143,6 +143,9 @@ public:
bool outputWarningsToStandardError() const;
void setOutputWarningsToStandardError(bool);
+ template<typename T>
+ T singletonInstance(int qmlTypeId);
+
public Q_SLOTS:
void retranslate();
@@ -167,6 +170,19 @@ private:
Q_DECLARE_PRIVATE(QQmlEngine)
};
+template<>
+Q_QML_EXPORT QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId);
+
+template<typename T>
+T QQmlEngine::singletonInstance(int qmlTypeId) {
+ QJSValue instance = singletonInstance<QJSValue>(qmlTypeId);
+ if (!instance.isQObject())
+ return nullptr;
+
+ QObject *object = instance.toQObject();
+ return qobject_cast<T>(object);
+}
+
QT_END_NAMESPACE
#endif // QQMLENGINE_H
diff --git a/src/qml/qml/qqmlguard_p.h b/src/qml/qml/qqmlguard_p.h
index 808bf4c709..3ac63926a0 100644
--- a/src/qml/qml/qqmlguard_p.h
+++ b/src/qml/qml/qqmlguard_p.h
@@ -106,6 +106,34 @@ protected:
virtual void objectDestroyed(T *) {}
};
+template <typename T>
+class QQmlStrongJSQObjectReference : public QQmlGuard<T>
+{
+public:
+ void setObject(T *o, QObject *parent) {
+ T *old = this->object();
+ if (o == old)
+ return;
+
+ if (m_jsOwnership && old && old->parent() == parent)
+ QQml_setParent_noEvent(old, nullptr);
+
+ this->QQmlGuard<T>::operator=(o);
+
+ if (o && !o->parent() && !QQmlData::keepAliveDuringGarbageCollection(o)) {
+ m_jsOwnership = true;
+ QQml_setParent_noEvent(o, parent);
+ } else {
+ m_jsOwnership = false;
+ }
+ }
+
+private:
+ using QQmlGuard<T>::setObject;
+ using QQmlGuard<T>::operator=;
+ bool m_jsOwnership = false;
+};
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QQmlGuard<QObject>)
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 80ebab5ca3..1c37894751 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -737,7 +737,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
int *vmajor, int *vminor, QQmlType *type_return, QString *base,
bool *typeRecursionDetected,
QQmlType::RegistrationType registrationType,
- QQmlImport::RecursionRestriction recursionRestriction) const
+ QQmlImport::RecursionRestriction recursionRestriction,
+ QList<QQmlError> *errors) const
{
if (majversion >= 0 && minversion >= 0) {
QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
@@ -820,8 +821,19 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
};
for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) {
const QString url = urlsToTry[i];
- exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(url)).isEmpty();
+ const QString localPath = QQmlFile::urlToLocalFileOrQrc(url);
+ exists = !typeLoader->absoluteFilePath(localPath).isEmpty();
if (exists) {
+ // don't let function.qml confuse the use of "new Function(...)" for example.
+ if (!QQml_isFileCaseCorrect(localPath)) {
+ exists = false;
+ if (errors) {
+ QQmlError caseError;
+ caseError.setDescription(QLatin1String("File name case mismatch"));
+ errors->append(caseError);
+ }
+ break;
+ }
qmlUrl = url;
break;
}
@@ -908,7 +920,7 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS
for (int i=0; i<imports.count(); ++i) {
const QQmlImportInstance *import = imports.at(i);
if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base,
- &typeRecursionDetected, registrationType, recursionRestriction)) {
+ &typeRecursionDetected, registrationType, recursionRestriction, errors)) {
if (qmlCheckTypes()) {
// check for type clashes
for (int j = i+1; j<imports.count(); ++j) {
@@ -2050,7 +2062,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
if (QQmlExtensionPlugin *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
// basepath should point to the directory of the module, not the plugin file itself:
- QQmlExtensionPluginPrivate::get(plugin)->baseUrl = QUrl::fromLocalFile(basePath);
+ QQmlExtensionPluginPrivate::get(plugin)->baseUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
}
iface->registerTypes(moduleId);
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 2437979ef8..283bd40660 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -94,7 +94,8 @@ struct QQmlImportInstance
int *vmajor, int *vminor, QQmlType* type_return,
QString *base = nullptr, bool *typeRecursionDetected = nullptr,
QQmlType::RegistrationType = QQmlType::AnyRegistrationType,
- QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion,
+ QList<QQmlError> *errors = nullptr) const;
};
class QQmlImportNamespace
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 93ec9421ed..9f2a96d5d9 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -93,8 +93,7 @@ void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine)
QQmlJavaScriptExpression::QQmlJavaScriptExpression()
- : m_error(nullptr),
- m_context(nullptr),
+ : m_context(nullptr),
m_prevExpression(nullptr),
m_nextExpression(nullptr),
m_v4Function(nullptr)
@@ -247,6 +246,9 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
g->Delete();
+ if (!watcher.wasDeleted())
+ setTranslationsCaptured(capture.translationCaptured);
+
ep->propertyCapture = lastPropertyCapture;
return result->asReturnedValue();
@@ -392,7 +394,7 @@ QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
{
if (!m_error)
m_error = new QQmlDelayedError;
- return m_error;
+ return m_error.data();
}
QV4::ReturnedValue
@@ -458,7 +460,7 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext,
setCompilationUnit(m_v4Function->compilationUnit);
}
-void QQmlJavaScriptExpression::setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit)
+void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
{
m_compilationUnit = compilationUnit;
}
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 01af3b89ca..de3fba0774 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -162,7 +162,7 @@ protected:
}
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
- void setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit);
+ void setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
@@ -171,13 +171,17 @@ protected:
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> permanentGuards;
+ void setTranslationsCaptured(bool captured) { m_error.setFlagValue(captured); }
+ bool translationsCaptured() const { return m_error.flag(); }
+
private:
friend class QQmlContextData;
friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlTranslationBinding;
- QQmlDelayedError *m_error;
+ // m_error:flag1 translationsCapturedDuringEvaluation
+ QFlagPointer<QQmlDelayedError> m_error;
QQmlContextData *m_context;
QQmlJavaScriptExpression **m_prevExpression;
@@ -208,12 +212,14 @@ public:
static void registerQmlDependencies(QV4::Heap::QmlContext *context, const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
void captureProperty(QQmlNotifier *, Duration duration = OnlyOnce);
void captureProperty(QObject *, int, int, Duration duration = OnlyOnce, bool doNotify = true);
+ void captureTranslation() { translationCaptured = true; }
QQmlEngine *engine;
QQmlJavaScriptExpression *expression;
QQmlJavaScriptExpression::DeleteWatcher *watcher;
QFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
QStringList *errorString;
+ bool translationCaptured = false;
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
@@ -260,18 +266,17 @@ void QQmlJavaScriptExpression::setScopeObject(QObject *v)
bool QQmlJavaScriptExpression::hasError() const
{
- return m_error && m_error->isValid();
+ return !m_error.isNull() && m_error->isValid();
}
bool QQmlJavaScriptExpression::hasDelayedError() const
{
- return m_error;
+ return !m_error.isNull();
}
inline void QQmlJavaScriptExpression::clearError()
{
- if (m_error)
- delete m_error;
+ delete m_error.data();
m_error = nullptr;
}
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 3fbe3df2ab..7c35f73e6c 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -74,7 +74,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
r->d()->object = object;
r->d()->propertyType = propType;
void *args[] = { &r->d()->property(), nullptr };
@@ -86,7 +86,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp
{
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
r->d()->object = prop.object;
r->d()->property() = prop;
r->d()->propertyType = propType;
@@ -102,54 +102,45 @@ QVariant QmlListWrapper::toVariant() const
}
-ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlListWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<QmlListWrapper>());
const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
- if (name->equals(v4->id_length()) && !w->d()->object.isNull()) {
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
- return Primitive::fromUInt32(count).asReturnedValue();
- }
-
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return getIndexed(m, idx, hasProperty);
-
- return Object::get(m, name, hasProperty);
-}
-
-ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
-{
- Q_UNUSED(hasProperty);
+ if (index < count && w->d()->property().at) {
+ if (hasProperty)
+ *hasProperty = true;
+ return QV4::QObjectWrapper::wrap(v4, w->d()->property().at(&w->d()->property(), index));
+ }
- Q_ASSERT(m->as<QmlListWrapper>());
- const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
- QV4::ExecutionEngine *v4 = w->engine();
-
- quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
- if (index < count && w->d()->property().at) {
if (hasProperty)
- *hasProperty = true;
- return QV4::QObjectWrapper::wrap(v4, w->d()->property().at(&w->d()->property(), index));
+ *hasProperty = false;
+ return Primitive::undefinedValue().asReturnedValue();
+ } else if (id.isString()) {
+ if (id == v4->id_length()->propertyKey() && !w->d()->object.isNull()) {
+ quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
+ return Primitive::fromUInt32(count).asReturnedValue();
+ }
}
- if (hasProperty)
- *hasProperty = false;
- return Primitive::undefinedValue().asReturnedValue();
+ return Object::virtualGet(m, id, receiver, hasProperty);
}
-bool QmlListWrapper::put(Managed *m, String *name, const Value &value)
+bool QmlListWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
// doesn't do anything. Should we throw?
Q_UNUSED(m);
- Q_UNUSED(name);
+ Q_UNUSED(id);
Q_UNUSED(value);
+ Q_UNUSED(receiver);
return false;
}
-void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
+void QmlListWrapper::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
name->setM(nullptr);
*index = UINT_MAX;
@@ -163,7 +154,7 @@ void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name
p->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property().at(&w->d()->property(), *index));
return;
}
- return QV4::Object::advanceIterator(m, it, name, index, p, attrs);
+ return QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attrs);
}
void PropertyListPrototype::init(ExecutionEngine *)
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index e02831c8d1..2d6a0880e3 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -93,10 +93,9 @@ struct Q_QML_EXPORT QmlListWrapper : Object
QVariant toVariant() const;
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
struct PropertyListPrototype : Object
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index b4f7092a22..42c72e0447 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -350,7 +350,7 @@ ReturnedValue QQmlDateExtension::method_timeZoneUpdated(const QV4::FunctionObjec
if (argc != 0)
THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
- QV4::DatePrototype::timezoneUpdated();
+ QV4::DatePrototype::timezoneUpdated(scope.engine);
RETURN_UNDEFINED();
}
@@ -825,10 +825,10 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
{
QV4::Scope scope(v4);
QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
- QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>());
+ QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocate<QQmlLocaleData>());
*wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
- wrapper->setPrototype(p);
+ wrapper->setPrototypeOf(p);
return wrapper.asReturnedValue();
}
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 8341b1f555..859c36e11b 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -58,6 +58,8 @@
#include <private/qqmlglobal_p.h>
#include <private/qv4object_p.h>
+QT_REQUIRE_CONFIG(qml_locale);
+
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp
index 597fe458fa..b59a26e17e 100644
--- a/src/qml/qml/qqmlloggingcategory.cpp
+++ b/src/qml/qml/qqmlloggingcategory.cpp
@@ -59,6 +59,7 @@
LoggingCategory {
id: category
name: "com.qt.category"
+ defaultLogLevel: LoggingCategory.Warning
}
Component.onCompleted: {
@@ -84,6 +85,17 @@
\sa QLoggingCategory::categoryName()
*/
+/*!
+ \qmlproperty enumeration QtQml::LoggingCategory::defaultLogLevel
+ \since 5.12
+
+ Holds the default log level of the logging category. By default it is
+ created with the LoggingCategory.Debug log level.
+
+ \note This property needs to be set when declaring the LoggingCategory
+ and cannot be changed later.
+*/
+
QQmlLoggingCategory::QQmlLoggingCategory(QObject *parent)
: QObject(parent)
, m_initialized(false)
@@ -99,6 +111,11 @@ QString QQmlLoggingCategory::name() const
return QString::fromUtf8(m_name);
}
+QQmlLoggingCategory::DefaultLogLevel QQmlLoggingCategory::defaultLogLevel() const
+{
+ return m_defaultLogLevel;
+}
+
QLoggingCategory *QQmlLoggingCategory::category() const
{
return m_category.data();
@@ -111,10 +128,25 @@ void QQmlLoggingCategory::classBegin()
void QQmlLoggingCategory::componentComplete()
{
m_initialized = true;
- if (m_name.isNull())
+ if (m_name.isNull()) {
qmlWarning(this) << QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !");
+ } else {
+ QScopedPointer<QLoggingCategory> category(new QLoggingCategory(m_name.constData(), QtMsgType(m_defaultLogLevel)));
+ m_category.swap(category);
+ }
}
+void QQmlLoggingCategory::setDefaultLogLevel(DefaultLogLevel defaultLogLevel)
+{
+ if (m_initialized) {
+ qmlWarning(this) << QLatin1String("The defaultLogLevel of a LoggingCategory cannot be changed after the Item is created");
+ return;
+ }
+
+ m_defaultLogLevel = defaultLogLevel;
+}
+
+
void QQmlLoggingCategory::setName(const QString &name)
{
if (m_initialized) {
@@ -123,8 +155,6 @@ void QQmlLoggingCategory::setName(const QString &name)
}
m_name = name.toUtf8();
- QScopedPointer<QLoggingCategory> category(new QLoggingCategory(m_name.constData()));
- m_category.swap(category);
}
#include "moc_qqmlloggingcategory_p.cpp"
diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h
index 544db1fe33..ece06e04b4 100644
--- a/src/qml/qml/qqmlloggingcategory_p.h
+++ b/src/qml/qml/qqmlloggingcategory_p.h
@@ -65,11 +65,23 @@ class QQmlLoggingCategory : public QObject, public QQmlParserStatus
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION 1)
public:
+ enum DefaultLogLevel {
+ Debug = QtDebugMsg,
+ Info = QtInfoMsg,
+ Warning = QtWarningMsg,
+ Critical = QtCriticalMsg,
+ Fatal = QtFatalMsg
+ };
+ Q_ENUM(DefaultLogLevel);
+
QQmlLoggingCategory(QObject *parent = nullptr);
virtual ~QQmlLoggingCategory();
+ DefaultLogLevel defaultLogLevel() const;
+ void setDefaultLogLevel(DefaultLogLevel defaultLogLevel);
QString name() const;
void setName(const QString &name);
@@ -81,6 +93,7 @@ public:
private:
QByteArray m_name;
QScopedPointer<QLoggingCategory> m_category;
+ DefaultLogLevel m_defaultLogLevel = Debug;
bool m_initialized;
};
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 2705321e77..b31058ece5 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -288,7 +288,14 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
{
if (scriptCallback && scriptApi(e).isUndefined()) {
- setScriptApi(e, scriptCallback(e, e));
+ QJSValue value = scriptCallback(e, e);
+ if (value.isQObject()) {
+ QObject *o = value.toQObject();
+ // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
+ // should behave identically to QML singleton types.
+ e->setContextForObject(o, new QQmlContext(e->rootContext(), e));
+ }
+ setScriptApi(e, value);
} else if (qobjectCallback && !qobjectApi(e)) {
QObject *o = qobjectCallback(e, e);
setQObjectApi(e, o);
@@ -297,6 +304,9 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
}
// if this object can use a property cache, create it now
QQmlData::ensurePropertyCache(e, o);
+ // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
+ // should behave identically to QML singleton types.
+ e->setContextForObject(o, new QQmlContext(e->rootContext(), e));
} else if (!url.isEmpty() && !qobjectApi(e)) {
QQmlComponent component(e, url, QQmlComponent::PreferSynchronous);
QObject *o = component.beginCreate(e->rootContext());
@@ -600,7 +610,7 @@ QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
Q_ASSERT(isComposite());
if (!engine || !d)
return QQmlType();
- QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return QQmlType();
QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
@@ -614,11 +624,11 @@ QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) c
Q_ASSERT(isComposite());
if (!engine)
return nullptr;
- QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return nullptr;
QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
- return compilationUnit->rootPropertyCache();
+ return compilationUnit->rootPropertyCache().data();
}
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
@@ -865,7 +875,7 @@ QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersio
{
for (int i = 0; i < propertyCaches.count(); ++i)
if (propertyCaches.at(i).minorVersion == minorVersion)
- return propertyCaches.at(i).cache;
+ return propertyCaches.at(i).cache.data();
return nullptr;
}
@@ -1877,6 +1887,23 @@ void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
p->maxMinorVersion = qMax(p->maxMinorVersion, versionMinor);
}
+//From qqml.h
+int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+{
+ QMutexLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+
+ QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
+ if (!module)
+ return -1;
+
+ QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), versionMinor);
+ if (!type.isValid())
+ return -1;
+
+ return type.index();
+}
+
bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorVersion)
{
const QQmlMetaTypeData *data = metaTypeData();
@@ -2248,19 +2275,25 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStrin
}
/*!
- Returns the type (if any) that corresponds to the QVariant::Type \a userType.
- Returns null if no type is registered.
+ Returns the type (if any) that corresponds to \a typeId. Depending on \a category, the
+ \a typeId is interpreted either as QVariant::Type or as QML type id returned by one of the
+ qml type registration functions. Returns null if no type is registered.
*/
-QQmlType QQmlMetaType::qmlType(int userType)
+QQmlType QQmlMetaType::qmlType(int typeId, TypeIdCategory category)
{
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- QQmlTypePrivate *type = data->idToType.value(userType);
- if (type && type->typeId == userType)
- return QQmlType(type);
- else
- return QQmlType();
+ if (category == TypeIdCategory::MetaType) {
+ QQmlTypePrivate *type = data->idToType.value(typeId);
+ if (type && type->typeId == typeId)
+ return QQmlType(type);
+ } else if (category == TypeIdCategory::QmlType) {
+ QQmlType type = data->types.value(typeId);
+ if (type.isValid())
+ return type;
+ }
+ return QQmlType();
}
/*!
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index bcaf62d6ba..4a5e4ba266 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -91,11 +91,16 @@ public:
static QList<QQmlType> qmlSingletonTypes();
static QList<QQmlType> qmlAllTypes();
+ enum class TypeIdCategory {
+ MetaType,
+ QmlType
+ };
+
static QQmlType qmlType(const QString &qualifiedName, int, int);
static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);
static QQmlType qmlType(const QMetaObject *);
static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor);
- static QQmlType qmlType(int);
+ static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType);
static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false);
static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 5aaf79c9e5..fb05201010 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -71,7 +71,7 @@ struct ActiveOCRestorer
};
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *creationContext,
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *creationContext,
QQmlIncubatorPrivate *incubator)
: phase(Startup)
, compilationUnit(compilationUnit)
@@ -99,7 +99,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::Compil
}
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compilationUnit(compilationUnit)
, resolvedTypes(compilationUnit->resolvedTypes)
@@ -193,8 +193,8 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context->importedScripts.set(v4, scripts);
QV4::ScopedValue v(scope);
for (int i = 0; i < compilationUnit->dependentScripts.count(); ++i) {
- QQmlScriptData *s = compilationUnit->dependentScripts.at(i);
- scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
+ QQmlRefPointer<QQmlScriptData> s = compilationUnit->dependentScripts.at(i);
+ scripts->put(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
context->importedScripts = sharedState->creationContext->importedScripts;
@@ -252,7 +252,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::
Q_ASSERT(!sharedState->allJavaScriptObjects);
sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
- QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
qSwap(_qmlContext, qmlContext);
@@ -312,7 +312,7 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty,
if (!sharedState->allJavaScriptObjects)
sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
- QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
qSwap(_qmlContext, qmlContext);
@@ -876,7 +876,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
&& !_valueTypeProperty)
QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()));
- if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->containsTranslations()) {
+ if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
@@ -898,7 +898,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
targetProperty = _valueTypeProperty;
subprop = bindingProperty;
}
- if (binding->containsTranslations()) {
+ if (binding->isTranslationBinding()) {
qmlBinding = QQmlBinding::createTranslationBinding(compilationUnit, binding, _scopeObject, context);
} else {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
@@ -1144,9 +1144,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
isComponent = true;
- QQmlComponent *component = new QQmlComponent(engine, compilationUnit, index, parent);
+ QQmlComponent *component = new QQmlComponent(engine, compilationUnit.data(), index, parent);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit, obj, QStringLiteral("<component>"), context->url()));
+ compilationUnit.data(), obj, QStringLiteral("<component>"), context->url()));
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
@@ -1157,7 +1157,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QQmlType type = typeRef->type;
if (type.isValid()) {
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit, obj, type.qmlTypeName(), context->url()));
+ compilationUnit.data(), obj, type.qmlTypeName(), context->url()));
void *ddataMemory = nullptr;
type.create(&instance, &ddataMemory, sizeof(QQmlData));
@@ -1190,8 +1190,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
} else {
Q_ASSERT(typeRef->compilationUnit);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit, obj, typeRef->compilationUnit->fileName(),
- context->url()));
+ compilationUnit.data(), obj, typeRef->compilationUnit->fileName(),
+ context->url()));
if (typeRef->compilationUnit->data->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1254,7 +1254,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
customParser->engine = QQmlEnginePrivate::get(engine);
- customParser->imports = compilationUnit->typeNameCache;
+ customParser->imports = compilationUnit->typeNameCache.data();
QList<const QV4::CompiledData::Binding *> bindings;
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
@@ -1264,7 +1264,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
bindings << binding;
}
}
- customParser->applyBindings(instance, compilationUnit, bindings);
+ customParser->applyBindings(instance, compilationUnit.data(), bindings);
customParser->engine = nullptr;
customParser->imports = (QQmlTypeNameCache*)nullptr;
@@ -1280,7 +1280,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (installPropertyCache) {
if (ddata->propertyCache)
ddata->propertyCache->release();;
- ddata->propertyCache = cache;
+ ddata->propertyCache = cache.data();
ddata->propertyCache->addref();
}
@@ -1292,7 +1292,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
++sharedState->allJavaScriptObjects;
QV4::Scope valueScope(v4);
- QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
qSwap(_qmlContext, qmlContext);
@@ -1344,6 +1344,11 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
b->setEnabled(true, QQmlPropertyData::BypassInterceptor |
QQmlPropertyData::DontRemoveBinding);
+ if (!b->isValueTypeProxy()) {
+ QQmlBinding *binding = static_cast<QQmlBinding*>(b.data());
+ if (!binding->hasError() && !binding->hasDependencies())
+ b->removeFromObject();
+ }
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return nullptr;
@@ -1436,7 +1441,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
vmeMetaObject = new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
if (_ddata->propertyCache)
_ddata->propertyCache->release();
- _ddata->propertyCache = cache;
+ _ddata->propertyCache = cache.data();
_ddata->propertyCache->addref();
scopeObjectProtector = _ddata->jsWrapper.value();
} else {
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 67a5bdd827..435b213341 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -85,7 +85,7 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
+ QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
~QQmlObjectCreator();
QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr);
@@ -104,7 +104,7 @@ public:
QFiniteStack<QPointer<QObject> > &allCreatedObjects() const { return sharedState->allCreatedObjects; }
private:
- QQmlObjectCreator(QQmlContextData *contextData, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
+ QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
void init(QQmlContextData *parentContext);
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 1b44bbdda3..fc798a2c23 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -181,46 +181,75 @@ void QQmlOpenMetaObjectTypePrivate::init(const QMetaObject *metaObj)
class QQmlOpenMetaObjectPrivate
{
public:
- QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q)
- : q(_q), parent(nullptr), type(nullptr), cacheProperties(false) {}
+ QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q, bool _autoCreate, QObject *obj)
+ : q(_q), object(obj), autoCreate(_autoCreate) {}
+
+ struct Property {
+ private:
+ QVariant m_value;
+ QPointer<QObject> qobjectTracker;
+ public:
+ bool valueSet = false;
+
+ QVariant value() const {
+ if (QMetaType::typeFlags(m_value.userType()) & QMetaType::PointerToQObject
+ && qobjectTracker.isNull())
+ return QVariant::fromValue<QObject*>(nullptr);
+ return m_value;
+ }
+ QVariant &valueRef() { return m_value; }
+ void setValue(const QVariant &v) {
+ m_value = v;
+ valueSet = true;
+ if (QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject)
+ qobjectTracker = m_value.value<QObject*>();
+ }
+ };
- inline QPair<QVariant, bool> &getDataRef(int idx) {
- while (data.count() <= idx)
- data << QPair<QVariant, bool>(QVariant(), false);
- return data[idx];
+ inline void setPropertyValue(int idx, const QVariant &value) {
+ if (data.count() <= idx)
+ data.resize(idx + 1);
+ data[idx].setValue(value);
}
- inline QVariant &getData(int idx) {
- QPair<QVariant, bool> &prop = getDataRef(idx);
- if (!prop.second) {
- prop.first = q->initialValue(idx);
- prop.second = true;
- }
- return prop.first;
+ inline Property &propertyRef(int idx) {
+ if (data.count() <= idx)
+ data.resize(idx + 1);
+ Property &prop = data[idx];
+ if (!prop.valueSet)
+ prop.setValue(q->initialValue(idx));
+ return prop;
+ }
+
+ inline QVariant propertyValue(int idx) {
+ auto &prop = propertyRef(idx);
+ return prop.value();
+ }
+
+ inline QVariant &propertyValueRef(int idx) {
+ auto &prop = propertyRef(idx);
+ return prop.valueRef();
}
- inline bool hasData(int idx) const {
+ inline bool hasProperty(int idx) const {
if (idx >= data.count())
return false;
- return data[idx].second;
+ return data[idx].valueSet;
}
- bool autoCreate;
QQmlOpenMetaObject *q;
- QAbstractDynamicMetaObject *parent;
- QList<QPair<QVariant, bool> > data;
+ QAbstractDynamicMetaObject *parent = nullptr;
+ QVector<Property> data;
QObject *object;
- QQmlOpenMetaObjectType *type;
- bool cacheProperties;
+ QQmlRefPointer<QQmlOpenMetaObjectType> type;
+ bool autoCreate;
+ bool cacheProperties = false;
};
QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bool automatic)
-: d(new QQmlOpenMetaObjectPrivate(this))
+: d(new QQmlOpenMetaObjectPrivate(this, automatic, obj))
{
- d->autoCreate = automatic;
- d->object = obj;
-
- d->type = new QQmlOpenMetaObjectType(base ? base : obj->metaObject(), nullptr);
+ d->type.adopt(new QQmlOpenMetaObjectType(base ? base : obj->metaObject(), nullptr));
d->type->d->referers.insert(this);
QObjectPrivate *op = QObjectPrivate::get(obj);
@@ -230,13 +259,9 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bo
}
QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *type, bool automatic)
-: d(new QQmlOpenMetaObjectPrivate(this))
+: d(new QQmlOpenMetaObjectPrivate(this, automatic, obj))
{
- d->autoCreate = automatic;
- d->object = obj;
-
d->type = type;
- d->type->addref();
d->type->d->referers.insert(this);
QObjectPrivate *op = QObjectPrivate::get(obj);
@@ -250,13 +275,12 @@ QQmlOpenMetaObject::~QQmlOpenMetaObject()
if (d->parent)
delete d->parent;
d->type->d->referers.remove(this);
- d->type->release();
delete d;
}
QQmlOpenMetaObjectType *QQmlOpenMetaObject::type() const
{
- return d->type;
+ return d->type.data();
}
void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName)
@@ -276,13 +300,11 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
int propId = id - d->type->d->propertyOffset;
if (c == QMetaObject::ReadProperty) {
propertyRead(propId);
- *reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = d->propertyValue(propId);
} else if (c == QMetaObject::WriteProperty) {
- if (propId >= d->data.count() || d->data.at(propId).first != *reinterpret_cast<QVariant *>(a[0])) {
+ if (propId >= d->data.count() || d->data.at(propId).value() != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
- QPair<QVariant, bool> &prop = d->getDataRef(propId);
- prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
- prop.second = true;
+ d->setPropertyValue(propId, propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0])));
propertyWritten(propId);
activate(o, d->type->d->signalOffset + propId, nullptr);
}
@@ -303,14 +325,12 @@ QAbstractDynamicMetaObject *QQmlOpenMetaObject::parent() const
QVariant QQmlOpenMetaObject::value(int id) const
{
- return d->getData(id);
+ return d->propertyValue(id);
}
void QQmlOpenMetaObject::setValue(int id, const QVariant &value)
{
- QPair<QVariant, bool> &prop = d->getDataRef(id);
- prop.first = propertyWriteValue(id, value);
- prop.second = true;
+ d->setPropertyValue(id, propertyWriteValue(id, value));
activate(d->object, id + d->type->d->signalOffset, nullptr);
}
@@ -320,23 +340,18 @@ QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
if (iter == d->type->d->names.cend())
return QVariant();
- return d->getData(*iter);
+ return d->propertyValue(*iter);
}
-QVariant &QQmlOpenMetaObject::operator[](const QByteArray &name)
+QVariant &QQmlOpenMetaObject::valueRef(const QByteArray &name)
{
QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
Q_ASSERT(iter != d->type->d->names.cend());
- return d->getData(*iter);
-}
-
-QVariant &QQmlOpenMetaObject::operator[](int id)
-{
- return d->getData(id);
+ return d->propertyValueRef(*iter);
}
-bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
+bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val, bool force)
{
QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
@@ -348,11 +363,10 @@ bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
}
if (id >= 0) {
- QVariant &dataVal = d->getData(id);
- if (dataVal == val)
+ if (!force && d->propertyValue(id) == val)
return false;
- dataVal = val;
+ d->setPropertyValue(id, val);
activate(d->object, id + d->type->d->signalOffset, nullptr);
return true;
}
@@ -363,7 +377,7 @@ bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
// returns true if this value has been initialized by a call to either value() or setValue()
bool QQmlOpenMetaObject::hasValue(int id) const
{
- return d->hasData(id);
+ return d->hasProperty(id);
}
void QQmlOpenMetaObject::setCached(bool c)
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index 4905190b75..168a2a6f7f 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -100,11 +100,10 @@ public:
~QQmlOpenMetaObject() override;
QVariant value(const QByteArray &) const;
- bool setValue(const QByteArray &, const QVariant &);
+ bool setValue(const QByteArray &, const QVariant &, bool force = false);
QVariant value(int) const;
void setValue(int, const QVariant &);
- QVariant &operator[](const QByteArray &);
- QVariant &operator[](int);
+ QVariant &valueRef(const QByteArray &);
bool hasValue(int) const;
int count() const;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index c4487f91a3..bc0124eeab 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -255,7 +255,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
{
if (!obj) return;
- QQmlTypeNameCache *typeNameCache = context?context->imports:nullptr;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context?context->imports:nullptr;
QObject *currentObject = obj;
QVector<QStringRef> path;
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index b78a2ddd20..0785910cec 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -979,13 +979,13 @@ public:
void append(QQmlPropertyCache *cache) { cache->addref(); data.append(cache); }
QQmlPropertyCache *at(int index) const { return data.at(index).data(); }
- void set(int index, QQmlPropertyCache *replacement) {
+ void set(int index, const QQmlRefPointer<QQmlPropertyCache> &replacement) {
if (QQmlPropertyCache *oldCache = data.at(index).data()) {
- if (replacement == oldCache)
+ if (replacement.data() == oldCache)
return;
oldCache->release();
}
- data[index] = replacement;
+ data[index] = replacement.data();
replacement->addref();
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index c656fac4ff..85167848fb 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -504,11 +504,12 @@ void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
if (!blob ||
blob->status() == Error || blob->status() == Complete ||
- status() == Error || status() == Complete || m_isDone ||
- m_waitingFor.contains(blob))
+ status() == Error || status() == Complete || m_isDone)
return;
- blob->addref();
+ for (auto existingDep: qAsConst(m_waitingFor))
+ if (existingDep.data() == blob)
+ return;
m_data.setStatus(WaitingForDependencies);
@@ -691,13 +692,11 @@ void QQmlDataBlob::tryDone()
void QQmlDataBlob::cancelAllWaitingFor()
{
while (m_waitingFor.count()) {
- QQmlDataBlob *blob = m_waitingFor.takeLast();
+ QQmlRefPointer<QQmlDataBlob> blob = m_waitingFor.takeLast();
Q_ASSERT(blob->m_waitingOnMe.contains(this));
blob->m_waitingOnMe.removeOne(this);
-
- blob->release();
}
}
@@ -706,7 +705,8 @@ void QQmlDataBlob::notifyAllWaitingOnMe()
while (m_waitingOnMe.count()) {
QQmlDataBlob *blob = m_waitingOnMe.takeLast();
- Q_ASSERT(blob->m_waitingFor.contains(this));
+ Q_ASSERT(std::any_of(blob->m_waitingFor.constBegin(), blob->m_waitingFor.constEnd(),
+ [this](const QQmlRefPointer<QQmlDataBlob> &waiting) { return waiting.data() == this; }));
blob->notifyComplete(this);
}
@@ -714,13 +714,19 @@ void QQmlDataBlob::notifyAllWaitingOnMe()
void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
{
- Q_ASSERT(m_waitingFor.contains(blob));
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
QQmlCompilingProfiler prof(typeLoader()->profiler(), blob);
m_inCallback = true;
- m_waitingFor.removeOne(blob);
+ QQmlRefPointer<QQmlDataBlob> blobRef;
+ for (int i = 0; i < m_waitingFor.count(); ++i) {
+ if (m_waitingFor.at(i).data() == blob) {
+ blobRef = m_waitingFor.takeAt(i);
+ break;
+ }
+ }
+ Q_ASSERT(blobRef);
if (blob->status() == Error) {
dependencyError(blob);
@@ -728,8 +734,6 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
dependencyComplete(blob);
}
- blob->release();
-
if (!isError() && m_waitingFor.isEmpty())
allDependenciesDone();
@@ -1327,20 +1331,17 @@ QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoa
QQmlTypeLoader::Blob::~Blob()
{
- for (int ii = 0; ii < m_qmldirs.count(); ++ii)
- m_qmldirs.at(ii)->release();
}
bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors)
{
- QQmlQmldirData *data = typeLoader()->getQmldir(url);
+ QQmlRefPointer<QQmlQmldirData> data = typeLoader()->getQmldir(url);
data->setImport(this, import);
data->setPriority(this, priority);
if (data->status() == Error) {
// This qmldir must not exist - which is not an error
- data->release();
return true;
} else if (data->status() == Complete) {
// This data is already available
@@ -1348,11 +1349,11 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData:
}
// Wait for this data to become available
- addDependency(data);
+ addDependency(data.data());
return true;
}
-bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
+bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
{
QString qmldirIdentifier = data->urlString();
QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1);
@@ -1378,8 +1379,8 @@ bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::Compile
const auto qmldirScripts = qmldir.scripts();
for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
- QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob.data());
scriptImported(blob, import->location, script.nameSpace, importQualifier);
}
@@ -1398,8 +1399,8 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
const QString &importQualifier = stringAt(import->qualifierIndex);
if (import->type == QV4::CompiledData::Import::ImportScript) {
QUrl scriptUrl = finalUrl().resolved(QUrl(importUri));
- QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob.data());
scriptImported(blob, import->location, importQualifier, QString());
} else if (import->type == QV4::CompiledData::Import::ImportLibrary) {
@@ -1426,8 +1427,8 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
const auto qmldirScripts = qmldir.scripts();
for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
- QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob.data());
scriptImported(blob, import->location, script.nameSpace, importQualifier);
}
@@ -1499,14 +1500,6 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
return true;
}
-void QQmlTypeLoader::Blob::dependencyError(QQmlDataBlob *blob)
-{
- if (blob->type() == QQmlDataBlob::QmldirFile) {
- QQmlQmldirData *data = static_cast<QQmlQmldirData *>(blob);
- data->release();
- }
-}
-
void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob)
{
if (blob->type() == QQmlDataBlob::QmldirFile) {
@@ -1532,7 +1525,7 @@ bool QQmlTypeLoader::Blob::isDebugging() const
return typeLoader()->engine()->handle()->debugger() != nullptr;
}
-bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlError> *errors)
+bool QQmlTypeLoader::Blob::qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &data, QList<QQmlError> *errors)
{
bool resolve = true;
@@ -1552,7 +1545,6 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlE
if (resolve) {
// This is the (current) best resolution for this import
if (!updateQmldir(data, import, errors)) {
- data->release();
return false;
}
@@ -1562,7 +1554,6 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlE
}
}
- data->release();
return true;
}
@@ -1664,7 +1655,7 @@ QUrl QQmlTypeLoader::normalize(const QUrl &unNormalizedUrl)
/*!
Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached.
*/
-QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
+QQmlRefPointer<QQmlTypeData> QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
{
Q_ASSERT(!unNormalizedUrl.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() ||
@@ -1707,8 +1698,6 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
}
}
- typeData->addref();
-
return typeData;
}
@@ -1716,20 +1705,20 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
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, Mode mode)
+QQmlRefPointer<QQmlTypeData> QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, Mode mode)
{
LockHolder<QQmlTypeLoader> holder(this);
QQmlTypeData *typeData = new QQmlTypeData(url, this);
QQmlTypeLoader::loadWithStaticData(typeData, data, mode);
- return typeData;
+ return QQmlRefPointer<QQmlTypeData>(typeData, QQmlRefPointer<QQmlTypeData>::Adopt);
}
/*!
Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached.
*/
-QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl)
+QQmlRefPointer<QQmlScriptBlob> QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl)
{
Q_ASSERT(!unNormalizedUrl.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() ||
@@ -1754,15 +1743,13 @@ QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl)
}
}
- scriptBlob->addref();
-
return scriptBlob;
}
/*!
Returns a QQmlQmldirData for \a url. The QQmlQmldirData may be cached.
*/
-QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
+QQmlRefPointer<QQmlQmldirData> QQmlTypeLoader::getQmldir(const QUrl &url)
{
Q_ASSERT(!url.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
@@ -1778,8 +1765,6 @@ QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
QQmlTypeLoader::load(qmldirData);
}
- qmldirData->addref();
-
return qmldirData;
}
@@ -2073,17 +2058,9 @@ QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager)
QQmlTypeData::~QQmlTypeData()
{
- for (int ii = 0; ii < m_scripts.count(); ++ii)
- m_scripts.at(ii).script->release();
- for (int ii = 0; ii < m_compositeSingletons.count(); ++ii) {
- if (QQmlTypeData *tdata = m_compositeSingletons.at(ii).typeData)
- tdata->release();
- }
- for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
- it != end; ++it) {
- if (QQmlTypeData *tdata = it->typeData)
- tdata->release();
- }
+ m_scripts.clear();
+ m_compositeSingletons.clear();
+ m_resolvedTypes.clear();
}
const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
@@ -2201,7 +2178,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
{
QQmlPropertyCacheCreator<QV4::CompiledData::CompilationUnit> propertyCacheCreator(&m_compiledData->propertyCaches,
&pendingGroupPropertyBindings,
- engine, m_compiledData, &m_importCache);
+ engine, m_compiledData.data(), &m_importCache);
QQmlCompileError error = propertyCacheCreator.buildMetaObjects();
if (error.isSet()) {
setError(error);
@@ -2209,7 +2186,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
}
}
- QQmlPropertyCacheAliasCreator<QV4::CompiledData::CompilationUnit> aliasCreator(&m_compiledData->propertyCaches, m_compiledData);
+ QQmlPropertyCacheAliasCreator<QV4::CompiledData::CompilationUnit> aliasCreator(&m_compiledData->propertyCaches, m_compiledData.data());
aliasCreator.appendAliasPropertiesToMetaObjects();
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
@@ -2393,8 +2370,7 @@ void QQmlTypeData::done()
}
m_compiledData->typeNameCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
- QQmlScriptData *scriptData = script.script->scriptData();
- scriptData->addref();
+ QQmlRefPointer<QQmlScriptData> scriptData = script.script->scriptData();
m_compiledData->dependentScripts << scriptData;
}
}
@@ -2637,8 +2613,8 @@ void QQmlTypeData::resolveTypes()
// Add any imported scripts to our resolved set
const auto resolvedScripts = m_importCache.resolvedScripts();
for (const QQmlImports::ScriptReference &script : resolvedScripts) {
- QQmlScriptBlob *blob = typeLoader()->getScript(script.location);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(script.location);
+ addDependency(blob.data());
ScriptReference ref;
//ref.location = ...
@@ -2681,7 +2657,7 @@ void QQmlTypeData::resolveTypes()
// TODO: give an error message? If so, we should record and show the path of the cycle.
continue;
}
- addDependency(ref.typeData);
+ addDependency(ref.typeData.data());
ref.prefix = csRef.prefix;
m_compositeSingletons << ref;
@@ -2711,7 +2687,7 @@ void QQmlTypeData::resolveTypes()
if (ref.type.isComposite()) {
ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
- addDependency(ref.typeData);
+ addDependency(ref.typeData.data());
}
ref.majorVersion = majorVersion;
ref.minorVersion = minorVersion;
@@ -2743,7 +2719,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons)
(*typeNameCache)->add(singleton.type.qmlTypeName(), singleton.type.sourceUrl(), singleton.prefix);
- m_importCache.populateCache(*typeNameCache);
+ m_importCache.populateCache(typeNameCache->data());
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
@@ -2833,7 +2809,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
return true;
}
-void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
+void QQmlTypeData::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
{
ScriptReference ref;
ref.script = blob;
@@ -2921,7 +2897,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
}
QV4::ScopedValue v(scope);
for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->putIndexed(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)));
+ scriptsArray->put(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)));
if (!hasEngine())
initialize(parentCtxt->engine);
@@ -2959,8 +2935,6 @@ void QQmlScriptData::clear()
typeNameCache = nullptr;
}
- for (int ii = 0; ii < scripts.count(); ++ii)
- scripts.at(ii)->release();
scripts.clear();
// An addref() was made when the QQmlCleanup was added to the engine.
@@ -2968,19 +2942,15 @@ void QQmlScriptData::clear()
}
QQmlScriptBlob::QQmlScriptBlob(const QUrl &url, QQmlTypeLoader *loader)
-: QQmlTypeLoader::Blob(url, JavaScriptFile, loader), m_scriptData(nullptr)
+: QQmlTypeLoader::Blob(url, JavaScriptFile, loader)
{
}
QQmlScriptBlob::~QQmlScriptBlob()
{
- if (m_scriptData) {
- m_scriptData->release();
- m_scriptData = nullptr;
- }
}
-QQmlScriptData *QQmlScriptBlob::scriptData() const
+QQmlRefPointer<QQmlScriptData> QQmlScriptBlob::scriptData() const
{
return m_scriptData;
}
@@ -3017,11 +2987,12 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
}
QmlIR::ScriptDirectivesCollector collector(&irUnit);
+ irUnit.jsParserEngine.setDirectives(&collector);
QList<QQmlError> errors;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(
- &irUnit.jsModule, &irUnit.jsGenerator, urlString(), finalUrlString(),
- source, &errors, &collector);
+ &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(),
+ source, &errors);
// No need to addref on unit, it's initial refcount is 1
source.clear();
if (!errors.isEmpty()) {
@@ -3095,6 +3066,7 @@ void QQmlScriptBlob::done()
}
m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace);
}
+ m_scripts.clear();
m_importCache.populateCache(m_scriptData->typeNameCache);
}
@@ -3104,7 +3076,7 @@ QString QQmlScriptBlob::stringAt(int index) const
return m_scriptData->m_precompiledScript->data->stringAt(index);
}
-void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace)
+void QQmlScriptBlob::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace)
{
ScriptReference ref;
ref.script = blob;
@@ -3118,7 +3090,7 @@ void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledDat
void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit)
{
Q_ASSERT(!m_scriptData);
- m_scriptData = new QQmlScriptData();
+ m_scriptData.adopt(new QQmlScriptData());
m_scriptData->url = finalUrl();
m_scriptData->urlString = finalUrlString();
m_scriptData->m_precompiledScript = unit;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index e75719866d..98ac4b1bc1 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -217,7 +217,7 @@ private:
QList<QQmlDataBlob *> m_waitingOnMe;
// List of QQmlDataBlob's that I am waiting for to complete.
- QList<QQmlDataBlob *> m_waitingFor;
+ QVector<QQmlRefPointer<QQmlDataBlob>> m_waitingFor;
int m_redirectCount:30;
bool m_inCallback:1;
@@ -279,14 +279,13 @@ public:
bool addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
bool fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors);
- bool updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
+ bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
private:
- virtual bool qmldirDataAvailable(QQmlQmldirData *, QList<QQmlError> *);
+ virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *);
- virtual void scriptImported(QQmlScriptBlob *, const QV4::CompiledData::Location &, const QString &, const QString &) {}
+ virtual void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &, const QV4::CompiledData::Location &, const QString &, const QString &) {}
- void dependencyError(QQmlDataBlob *) override;
void dependencyComplete(QQmlDataBlob *) override;
protected:
@@ -296,7 +295,7 @@ public:
QQmlImports m_importCache;
QHash<const QV4::CompiledData::Import*, int> m_unresolvedImports;
- QList<QQmlQmldirData *> m_qmldirs;
+ QVector<QQmlRefPointer<QQmlQmldirData>> m_qmldirs;
QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError;
};
@@ -307,11 +306,11 @@ public:
static QUrl normalize(const QUrl &unNormalizedUrl);
- QQmlTypeData *getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
- QQmlTypeData *getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
+ QQmlRefPointer<QQmlTypeData> getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
+ QQmlRefPointer<QQmlTypeData> getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
- QQmlScriptBlob *getScript(const QUrl &unNormalizedUrl);
- QQmlQmldirData *getQmldir(const QUrl &);
+ QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl);
+ QQmlRefPointer<QQmlQmldirData> getQmldir(const QUrl &);
QString absoluteFilePath(const QString &path);
bool directoryExists(const QString &path);
@@ -424,13 +423,13 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
public:
struct TypeReference
{
- TypeReference() : majorVersion(0), minorVersion(0), typeData(nullptr), needsCreation(true) {}
+ TypeReference() : majorVersion(0), minorVersion(0), needsCreation(true) {}
QV4::CompiledData::Location location;
QQmlType type;
int majorVersion;
int minorVersion;
- QQmlTypeData *typeData;
+ QQmlRefPointer<QQmlTypeData> typeData;
QString prefix; // used by CompositeSingleton types
QString qualifiedName() const;
bool needsCreation;
@@ -438,11 +437,9 @@ public:
struct ScriptReference
{
- ScriptReference() : script(nullptr) {}
-
QV4::CompiledData::Location location;
QString qualifier;
- QQmlScriptBlob *script;
+ QQmlRefPointer<QQmlScriptBlob> script;
};
private:
@@ -495,7 +492,7 @@ private:
bool reportErrors = true,
QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType);
- void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
+ void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
SourceCodeData m_backupSourceCode; // used when cache verification fails.
@@ -541,7 +538,7 @@ public:
QUrl url;
QString urlString;
QQmlTypeNameCache *typeNameCache;
- QList<QQmlScriptBlob *> scripts;
+ QVector<QQmlRefPointer<QQmlScriptBlob>> scripts;
QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
@@ -571,15 +568,13 @@ public:
struct ScriptReference
{
- ScriptReference() : script(nullptr) {}
-
QV4::CompiledData::Location location;
QString qualifier;
QString nameSpace;
- QQmlScriptBlob *script;
+ QQmlRefPointer<QQmlScriptBlob> script;
};
- QQmlScriptData *scriptData() const;
+ QQmlRefPointer<QQmlScriptData> scriptData() const;
protected:
void dataReceived(const SourceCodeData &) override;
@@ -589,11 +584,11 @@ protected:
QString stringAt(int index) const override;
private:
- void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
+ void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
void initializeFromCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit);
QList<ScriptReference> m_scripts;
- QQmlScriptData *m_scriptData;
+ QQmlRefPointer<QQmlScriptData> m_scriptData;
};
class Q_AUTOTEST_EXPORT QQmlQmldirData : public QQmlTypeLoader::Blob
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index ce35e966aa..c6affcb79c 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -95,12 +95,17 @@ QObject* QQmlTypeWrapper::singletonObject() const
QVariant QQmlTypeWrapper::toVariant() const
{
- QObject *qobjectSingleton = singletonObject();
- if (qobjectSingleton)
+ // Only Singleton type wrappers can be converted to a variant.
+ if (!isSingleton())
+ return QVariant();
+
+ QQmlEngine *e = engine()->qmlEngine();
+ QQmlType::SingletonInstanceInfo *siinfo = d()->type().singletonInstanceInfo();
+ siinfo->init(e);
+ if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
return QVariant::fromValue<QObject*>(qobjectSingleton);
- // only QObject Singleton Type can be converted to a variant.
- return QVariant();
+ return QVariant::fromValue<QJSValue>(siinfo->scriptApi(e));
}
@@ -111,7 +116,7 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o,
Q_ASSERT(t.isValid());
Scope scope(engine);
- Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>());
+ Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocate<QQmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o;
w->d()->typePrivate = t.priv();
QQmlType::refHandle(w->d()->typePrivate);
@@ -120,15 +125,15 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o,
// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a
// namespace.
-ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *importNamespace,
+ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlRefPointer<QQmlTypeNameCache> &t, const QQmlImportRef *importNamespace,
Heap::QQmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t);
Q_ASSERT(importNamespace);
Scope scope(engine);
- Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>());
- w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
+ Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocate<QQmlTypeWrapper>());
+ w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t.data(); w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
}
@@ -162,12 +167,16 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n
return v4->throwTypeError(message);
}
-ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlTypeWrapper>());
+ if (!id.isString())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
QV4::ExecutionEngine *v4 = static_cast<const QQmlTypeWrapper *>(m)->engine();
QV4::Scope scope(v4);
+ ScopedString name(scope, id.asStringOrSymbol());
Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(m));
@@ -232,7 +241,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
if (ok) {
- Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>());
+ Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocate<QQmlScopedEnumWrapper>());
enumWrapper->d()->typePrivate = type.priv();
QQmlType::refHandle(enumWrapper->d()->typePrivate);
enumWrapper->d()->scopeEnumIndex = value;
@@ -263,7 +272,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
return create(scope.engine, object, r.type, w->d()->mode);
} else if (r.scriptIndex != -1) {
QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
- return scripts->getIndexed(r.scriptIndex);
+ return scripts->get(r.scriptIndex);
} else if (r.importNamespace) {
return create(scope.engine, object, context->imports, r.importNamespace);
}
@@ -279,7 +288,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
}
bool ok = false;
- const ReturnedValue result = Object::get(m, name, &ok);
+ const ReturnedValue result = Object::virtualGet(m, id, receiver, &ok);
if (hasProperty)
*hasProperty = ok;
@@ -295,16 +304,20 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
}
-bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
+ if (!id.isString())
+ return Object::virtualPut(m, id, value, receiver);
+
+
Q_ASSERT(m->as<QQmlTypeWrapper>());
QQmlTypeWrapper *w = static_cast<QQmlTypeWrapper *>(m);
- QV4::ExecutionEngine *v4 = w->engine();
- if (v4->hasException)
+ QV4::Scope scope(w);
+ if (scope.engine->hasException)
return false;
- QV4::Scope scope(v4);
- QQmlContextData *context = v4->callingQmlContext();
+ ScopedString name(scope, id.asStringOrSymbol());
+ QQmlContextData *context = scope.engine->callingQmlContext();
QQmlType type = w->d()->type();
if (type.isValid() && !type.isSingleton() && w->d()->object) {
@@ -312,7 +325,7 @@ bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
QQmlEngine *e = scope.engine->qmlEngine();
QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(e)), object);
if (ao)
- return QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ return QV4::QObjectWrapper::setQmlProperty(scope.engine, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
return false;
} else if (type.isSingleton()) {
QQmlEngine *e = scope.engine->qmlEngine();
@@ -321,12 +334,12 @@ bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
QObject *qobjectSingleton = siinfo->qobjectApi(e);
if (qobjectSingleton) {
- return QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ return QV4::QObjectWrapper::setQmlProperty(scope.engine, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (!siinfo->scriptApi(e).isUndefined()) {
- QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
+ QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(scope.engine, siinfo->scriptApi(e)));
if (!apiprivate) {
QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
- v4->throwError(error);
+ scope.engine->throwError(error);
return false;
} else {
return apiprivate->put(name, value);
@@ -337,15 +350,21 @@ bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
return false;
}
-PropertyAttributes QQmlTypeWrapper::query(const Managed *m, String *name)
+PropertyAttributes QQmlTypeWrapper::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
{
- // ### Implement more efficiently.
- bool hasProperty = false;
- static_cast<Object *>(const_cast<Managed*>(m))->get(name, &hasProperty);
- return hasProperty ? Attr_Data : Attr_Invalid;
+ if (id.isString()) {
+ Scope scope(m);
+ ScopedString n(scope, id.asStringOrSymbol());
+ // ### Implement more efficiently.
+ bool hasProperty = false;
+ static_cast<Object *>(m)->get(n, &hasProperty);
+ return hasProperty ? Attr_Data : Attr_Invalid;
+ }
+
+ return QV4::Object::virtualGetOwnProperty(m, id, p);
}
-bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
+bool QQmlTypeWrapper::virtualIsEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QQmlTypeWrapper>());
QV4::QQmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QQmlTypeWrapper *>(a);
@@ -357,7 +376,7 @@ bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
return false;
}
-ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value &var)
+ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const Value &var)
{
Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
const QV4::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::QQmlTypeWrapper *>(typeObject);
@@ -385,10 +404,9 @@ ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value
if (!theirDData->compilationUnit)
return Encode(false);
- QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
+ QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
CompiledData::CompilationUnit *cu = td->compilationUnit();
myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
- td->release();
} else {
myQmlType = qenginepriv->metaObjectForType(myTypeId);
}
@@ -410,12 +428,16 @@ QQmlType Heap::QQmlScopedEnumWrapper::type() const
return QQmlType(typePrivate);
}
-ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlScopedEnumWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlScopedEnumWrapper>());
+ if (!id.isString())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
const QQmlScopedEnumWrapper *resource = static_cast<const QQmlScopedEnumWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
+ ScopedString name(scope, id.asStringOrSymbol());
QQmlType type = resource->d()->type();
int index = resource->d()->scopeEnumIndex;
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 25ff7ba7c8..c0eb534d36 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -108,15 +108,15 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object
static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlType &,
Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
- static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const QQmlImportRef *,
+ static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlRefPointer<QQmlTypeNameCache> &, const QQmlImportRef *,
Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
-
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
- static PropertyAttributes query(const Managed *, String *name);
- static bool isEqualTo(Managed *that, Managed *o);
- static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
+protected:
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static bool virtualIsEqualTo(Managed *that, Managed *o);
+ static ReturnedValue virtualInstanceOf(const Object *typeObject, const Value &var);
};
struct Q_QML_EXPORT QQmlScopedEnumWrapper : Object
@@ -124,7 +124,7 @@ struct Q_QML_EXPORT QQmlScopedEnumWrapper : Object
V4_OBJECT2(QQmlScopedEnumWrapper, Object)
V4_NEEDS_DESTROY
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
};
}
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index ba0d305bd9..35b54c339b 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -55,7 +55,7 @@
QT_BEGIN_NAMESPACE
-class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
+class Q_AUTOTEST_EXPORT QQmlValueTypeProxyBinding : public QQmlAbstractBinding
{
public:
QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex coreIndex);
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 6196a09d94..1fde5945ba 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -39,7 +39,6 @@
#include "qqmlvaluetypewrapper_p.h"
#include <private/qv8engine_p.h>
-
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlglobal_p.h>
@@ -49,6 +48,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4alloca_p.h>
+#include <private/qv4stackframe_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <QtCore/qloggingcategory.h>
@@ -186,7 +186,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>());
+ Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocate<QQmlValueTypeReference>());
r->d()->object = object;
r->d()->property = property;
r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
@@ -200,7 +200,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>());
+ Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocate<QQmlValueTypeWrapper>());
r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = nullptr;
@@ -227,7 +227,7 @@ bool QQmlValueTypeWrapper::toGadget(void *data) const
return true;
}
-bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
+bool QQmlValueTypeWrapper::virtualIsEqualTo(Managed *m, Managed *other)
{
Q_ASSERT(m && m->as<QQmlValueTypeWrapper>() && other);
QV4::QQmlValueTypeWrapper *lv = static_cast<QQmlValueTypeWrapper *>(m);
@@ -241,16 +241,20 @@ bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
return false;
}
-PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name)
+PropertyAttributes QQmlValueTypeWrapper::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
{
- Q_ASSERT(m->as<const QQmlValueTypeWrapper>());
- const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+ if (id.isString()) {
+ Scope scope(m);
+ ScopedString n(scope, id.asStringOrSymbol());
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(n.getPointer(), nullptr, nullptr);
+ return result ? Attr_Data : Attr_Invalid;
+ }
- QQmlPropertyData *result = r->d()->propertyCache()->property(name, nullptr, nullptr);
- return result ? Attr_Data : Attr_Invalid;
+ return QV4::Object::virtualGetOwnProperty(m, id, p);
}
-void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+void QQmlValueTypeWrapper::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
name->setM(nullptr);
*index = UINT_MAX;
@@ -275,7 +279,7 @@ void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value
return;
}
}
- QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+ QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
bool QQmlValueTypeWrapper::isEqual(const QVariant& value) const
@@ -355,11 +359,17 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(const FunctionObject *b, con
return Encode(b->engine()->newString(result));
}
-ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlValueTypeWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
+
+ if (!id.isString())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = r->engine();
+ Scope scope(v4);
+ ScopedString name(scope, id.asStringOrSymbol());
// Note: readReferenceValue() can change the reference->type.
if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
@@ -367,9 +377,9 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
return Primitive::undefinedValue().asReturnedValue();
}
- QQmlPropertyData *result = r->d()->propertyCache()->property(name, nullptr, nullptr);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(name.getPointer(), nullptr, nullptr);
if (!result)
- return Object::get(m, name, hasProperty);
+ return Object::virtualGet(m, id, receiver, hasProperty);
if (hasProperty)
*hasProperty = true;
@@ -413,8 +423,11 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
#undef VALUE_TYPE_ACCESSOR
}
-bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
+ if (!id.isString())
+ return Object::virtualPut(m, id, value, receiver);
+
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
ExecutionEngine *v4 = static_cast<QQmlValueTypeWrapper *>(m)->engine();
Scope scope(v4);
@@ -435,8 +448,10 @@ bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
writeBackPropertyType = writebackProperty.userType();
}
+ ScopedString name(scope, id.asStringOrSymbol());
+
const QMetaObject *metaObject = r->d()->propertyCache()->metaObject();
- const QQmlPropertyData *pd = r->d()->propertyCache()->property(name, nullptr, nullptr);
+ const QQmlPropertyData *pd = r->d()->propertyCache()->property(name.getPointer(), nullptr, nullptr);
if (!pd)
return false;
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index f99d207d68..ff8ab98bb6 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -106,11 +106,11 @@ public:
int typeId() const;
bool write(QObject *target, int propertyIndex) const;
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
- static bool isEqualTo(Managed *m, Managed *other);
- static PropertyAttributes query(const Managed *, String *name);
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static bool virtualIsEqualTo(Managed *m, Managed *other);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_toString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 9a94ac6258..13c5524d96 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -124,6 +124,10 @@ private:
// Used to check that a QQmlVME that is interrupted mid-execution
// is still valid. Checks all the objects and contexts have not been
// deleted.
+//
+// VME stands for Virtual Machine Execution. QML files used to
+// be compiled to a byte code data structure that a virtual machine executed
+// (for constructing the tree of QObjects and setting properties).
class QQmlVMEGuard
{
public:
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index c1d3980b58..6bc0f0aa1e 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -106,7 +106,7 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
QV4::Scope scope(v4);
QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value());
if (sp) {
- QV4::MemberData::Index index{ sp->d(), sp->d()->values.values + m_index };
+ QV4::PropertyIndex index{ sp->d(), sp->d()->values.values + m_index };
index.set(v4, QV4::Primitive::nullValue());
}
}
@@ -176,7 +176,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
}
-QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache)
+QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache)
: object(obj),
cache(cache),
interceptors(nullptr),
@@ -316,7 +316,7 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje
QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine,
QObject *obj,
- QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId)
+ const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlCompilationUnit, int qmlObjectId)
: QQmlInterceptorMetaObject(obj, cache),
engine(engine),
ctxt(QQmlData::get(obj, true)->outerContext),
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 0c82686d47..dbcc9d2884 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -94,7 +94,7 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QAbstractDynamicMetaObject
{
public:
- QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache);
+ QQmlInterceptorMetaObject(QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache);
~QQmlInterceptorMetaObject() override;
void registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor);
@@ -104,7 +104,7 @@ public:
QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) override;
// Used by auto-tests for inspection
- QQmlPropertyCache *propertyCache() const { return cache; }
+ QQmlPropertyCache *propertyCache() const { return cache.data(); }
bool intercepts(QQmlPropertyIndex propertyIndex) const
{
@@ -146,7 +146,7 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId);
+ QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlCompilationUnit, int qmlObjectId);
~QQmlVMEMetaObject() override;
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 567d83f3ee..51e5be4b5b 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -228,8 +228,7 @@ public:
static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
};
void Heap::NamedNodeMap::init(NodeImpl *data, const QList<NodeImpl *> &list)
@@ -250,8 +249,7 @@ public:
V4_NEEDS_DESTROY
// JS API
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
// C++ API
static ReturnedValue create(ExecutionEngine *, NodeImpl *);
@@ -595,7 +593,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
Scope scope(v4);
QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->nodePrototype.isUndefined()) {
- ScopedObject p(scope, v4->memoryManager->allocObject<NodePrototype>());
+ ScopedObject p(scope, v4->memoryManager->allocate<NodePrototype>());
d->nodePrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
@@ -606,12 +604,12 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
{
Scope scope(v4);
- Scoped<Node> instance(scope, v4->memoryManager->allocObject<Node>(data));
+ Scoped<Node> instance(scope, v4->memoryManager->allocate<Node>(data));
ScopedObject p(scope);
switch (data->type) {
case NodeImpl::Attr:
- instance->setPrototype((p = Attr::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Attr::prototype(v4)));
break;
case NodeImpl::Comment:
case NodeImpl::Document:
@@ -623,13 +621,13 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
case NodeImpl::ProcessingInstruction:
return Encode::undefined();
case NodeImpl::CDATA:
- instance->setPrototype((p = CDATA::prototype(v4)));
+ instance->setPrototypeUnchecked((p = CDATA::prototype(v4)));
break;
case NodeImpl::Text:
- instance->setPrototype((p = Text::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Text::prototype(v4)));
break;
case NodeImpl::Element:
- instance->setPrototype((p = Element::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Element::prototype(v4)));
break;
}
@@ -643,7 +641,7 @@ ReturnedValue Element::prototype(ExecutionEngine *engine)
Scope scope(engine);
ScopedObject p(scope, engine->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(engine)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, nullptr);
d->elementPrototype.set(engine, p);
engine->v8Engine->freezeObject(p);
@@ -658,7 +656,7 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine)
Scope scope(engine);
ScopedObject p(scope, engine->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(engine)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("name"), method_name, nullptr);
p->defineAccessorProperty(QStringLiteral("value"), method_value, nullptr);
p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, nullptr);
@@ -715,7 +713,7 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(v4)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, nullptr);
p->defineAccessorProperty(QStringLiteral("length"), method_length, nullptr);
d->characterDataPrototype.set(v4, p);
@@ -751,7 +749,7 @@ ReturnedValue Text::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = CharacterData::prototype(v4)));
+ p->setPrototypeUnchecked((pp = CharacterData::prototype(v4)));
p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, nullptr);
p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, nullptr);
d->textPrototype.set(v4, p);
@@ -768,7 +766,7 @@ ReturnedValue CDATA::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = Text::prototype(v4)));
+ p->setPrototypeUnchecked((pp = Text::prototype(v4)));
d->cdataPrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
@@ -782,7 +780,7 @@ ReturnedValue Document::prototype(ExecutionEngine *v4)
Scope scope(v4);
ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(v4)));
+ p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
p->defineAccessorProperty(QStringLiteral("xmlVersion"), method_xmlVersion, nullptr);
p->defineAccessorProperty(QStringLiteral("xmlEncoding"), method_xmlEncoding, nullptr);
p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, nullptr);
@@ -876,10 +874,10 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
return Encode::null();
}
- ScopedObject instance(scope, v4->memoryManager->allocObject<Node>(document));
+ ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document));
document->release(); // the GC should own the NodeImpl via Node now
ScopedObject p(scope);
- instance->setPrototype((p = Document::prototype(v4)));
+ instance->setPrototypeUnchecked((p = Document::prototype(v4)));
return instance.asReturnedValue();
}
@@ -888,33 +886,33 @@ bool Node::isNull() const
return d()->d == nullptr;
}
-ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasProperty)
+ReturnedValue NamedNodeMap::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
+
const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
- if ((int)index < r->d()->list().count()) {
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+
+ if ((int)index < r->d()->list().count()) {
+ if (hasProperty)
+ *hasProperty = true;
+ return Node::create(v4, r->d()->list().at(index));
+ }
if (hasProperty)
- *hasProperty = true;
- return Node::create(v4, r->d()->list().at(index));
+ *hasProperty = false;
+ return Encode::undefined();
}
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
-}
-ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasProperty)
-{
- Q_ASSERT(m->as<NamedNodeMap>());
- const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
- QV4::ExecutionEngine *v4 = r->engine();
+ if (id.isSymbol())
+ return Object::virtualGet(m, id, receiver, hasProperty);
- name->makeIdentifier();
- if (name->equals(v4->id_length()))
+ if (id == v4->id_length()->propertyKey())
return Primitive::fromInt32(r->d()->list().count()).asReturnedValue();
- QString str = name->toQString();
+ QString str = id.toQString();
for (int ii = 0; ii < r->d()->list().count(); ++ii) {
if (r->d()->list().at(ii)->name == str) {
if (hasProperty)
@@ -930,41 +928,35 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert
ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list)
{
- return (v4->memoryManager->allocObject<NamedNodeMap>(data, list))->asReturnedValue();
+ return (v4->memoryManager->allocate<NamedNodeMap>(data, list))->asReturnedValue();
}
-ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty)
+ReturnedValue NodeList::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
- if ((int)index < r->d()->d->children.count()) {
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if ((int)index < r->d()->d->children.count()) {
+ if (hasProperty)
+ *hasProperty = true;
+ return Node::create(v4, r->d()->d->children.at(index));
+ }
if (hasProperty)
- *hasProperty = true;
- return Node::create(v4, r->d()->d->children.at(index));
+ *hasProperty = false;
+ return Encode::undefined();
}
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
-}
-
-ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
-{
- Q_ASSERT(m->as<NodeList>());
- const NodeList *r = static_cast<const NodeList *>(m);
- QV4::ExecutionEngine *v4 = r->engine();
-
- name->makeIdentifier();
- if (name->equals(v4->id_length()))
+ if (id == v4->id_length()->propertyKey())
return Primitive::fromInt32(r->d()->d->children.count()).asReturnedValue();
- return Object::get(m, name, hasProperty);
+ return Object::virtualGet(m, id, receiver, hasProperty);
}
ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
{
- return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue();
+ return (v4->memoryManager->allocate<NodeList>(data))->asReturnedValue();
}
ReturnedValue Document::method_documentElement(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -1637,19 +1629,19 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
{
V4_OBJECT2(QQmlXMLHttpRequestCtor, FunctionObject)
- static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *, int)
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
{
Scope scope(f->engine());
const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager(), scope.engine);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r));
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
- w->setPrototype(proto);
+ w->setPrototypeUnchecked(proto);
return w.asReturnedValue();
}
- static ReturnedValue call(const FunctionObject *, const Value *, const Value *, int) {
+ static ReturnedValue virtualCall(const FunctionObject *, const Value *, const Value *, int) {
return Encode::undefined();
}
@@ -2049,7 +2041,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
{
Scope scope(v4);
- Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocObject<QQmlXMLHttpRequestCtor>(v4));
+ Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocate<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
v4->globalObject->defineReadonlyProperty(s, ctor);
diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h
index f2836d8301..7515ef8dcc 100644
--- a/src/qml/qml/qqmlxmlhttprequest_p.h
+++ b/src/qml/qml/qqmlxmlhttprequest_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qglobal.h>
#include <private/qqmlglobal_p.h>
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
+QT_REQUIRE_CONFIG(qml_xml_http_request);
QT_BEGIN_NAMESPACE
@@ -64,7 +64,5 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *);
QT_END_NAMESPACE
-#endif // xmlstreamreader && qml_network
-
#endif // QQMLXMLHTTPREQUEST_P_H
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f04bee7f19..e6f68a30b3 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -44,7 +44,9 @@
#include <private/qqmlcomponent_p.h>
#include <private/qqmlloggingcategory_p.h>
#include <private/qqmlstringconverters_p.h>
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <private/qv8engine_p.h>
#include <private/qqmldelayedcallqueue_p.h>
#include <QFileInfo>
@@ -65,6 +67,7 @@
#include <private/qv4jsonobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4stackframe_p.h>
#include <QtCore/qstring.h>
#include <QtCore/qdatetime.h>
@@ -138,7 +141,9 @@ void Heap::QtObject::init(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("btoa"), QV4::QtObject::method_btoa);
o->defineDefaultProperty(QStringLiteral("atob"), QV4::QtObject::method_atob);
o->defineDefaultProperty(QStringLiteral("resolvedUrl"), QV4::QtObject::method_resolvedUrl);
+#if QT_CONFIG(qml_locale)
o->defineDefaultProperty(QStringLiteral("locale"), QV4::QtObject::method_locale);
+#endif
o->defineDefaultProperty(QStringLiteral("binding"), QV4::QtObject::method_binding);
if (qmlEngine) {
@@ -193,35 +198,35 @@ ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) con
return Encode::undefined();
}
-ReturnedValue QtObject::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QtObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
bool hasProp = false;
if (hasProperty == nullptr) {
hasProperty = &hasProp;
}
- ReturnedValue ret = QV4::Object::get(m, name, hasProperty);
+ ReturnedValue ret = QV4::Object::virtualGet(m, id, receiver, hasProperty);
if (*hasProperty) {
return ret;
}
auto that = static_cast<const QtObject*>(m);
if (!that->d()->isComplete()) {
- const QString key = name->toQString();
+ const QString key = id.toQString();
ret = that->findAndAdd(&key, *hasProperty);
}
return ret;
}
-void QtObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+void QtObject::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
auto that = static_cast<QtObject*>(m);
if (!that->d()->isComplete()) {
that->addAll();
}
- QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+ QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
/*!
@@ -1106,7 +1111,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
qmlerror->put((s = v4->newString(QStringLiteral("columnNumber"))), (v = QV4::Primitive::fromInt32(error.column())));
qmlerror->put((s = v4->newString(QStringLiteral("fileName"))), (v = v4->newString(error.url().toString())));
qmlerror->put((s = v4->newString(QStringLiteral("message"))), (v = v4->newString(error.description())));
- qmlerrors->putIndexed(ii, qmlerror);
+ qmlerrors->put(ii, qmlerror);
}
v = v4->newString(errorstr);
@@ -1152,7 +1157,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
if (!parentArg)
THROW_GENERIC_ERROR("Qt.createQmlObject(): Missing parent object");
- QQmlTypeData *typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
+ QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
qml.toUtf8(), url, QQmlTypeLoader::Synchronous);
Q_ASSERT(typeData->isCompleteOrError());
QQmlComponent component(engine);
@@ -1309,6 +1314,7 @@ ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Va
return QV4::QObjectWrapper::wrap(scope.engine, c);
}
+#if QT_CONFIG(qml_locale)
/*!
\qmlmethod Qt::locale(name)
@@ -1343,6 +1349,7 @@ ReturnedValue QtObject::method_locale(const FunctionObject *b, const Value *, co
return QQmlLocale::locale(scope.engine, code);
}
+#endif
void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *bindingFunction)
{
@@ -1416,7 +1423,7 @@ ReturnedValue QtObject::method_binding(const FunctionObject *b, const Value *, c
if (!f)
THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function");
- return Encode(scope.engine->memoryManager->allocObject<QQmlBindingFunction>(f));
+ return Encode(scope.engine->memoryManager->allocate<QQmlBindingFunction>(f));
}
@@ -1551,7 +1558,7 @@ static ReturnedValue writeToConsole(const FunctionObject *b, const Value *, cons
if (i != start)
result.append(QLatin1Char(' '));
- if (argv[i].as<ArrayObject>())
+ if (argv[i].isManaged() && argv[i].managed()->isArrayLike())
result += QLatin1Char('[') + argv[i].toQStringNoThrow() + QLatin1Char(']');
else
result.append(argv[i].toQStringNoThrow());
@@ -1795,7 +1802,7 @@ void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions ext
globalObject->defineDefaultProperty(QStringLiteral("print"), QV4::ConsoleObject::method_log);
- QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocObject<QV4::ConsoleObject>());
+ QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocate<QV4::ConsoleObject>());
globalObject->defineDefaultProperty(QStringLiteral("console"), console);
}
@@ -1850,6 +1857,10 @@ ReturnedValue GlobalExtensions::method_qsTranslate(const FunctionObject *b, cons
if (argc > i)
n = argv[i].toInt32();
+ if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureTranslation();
+
QString result = QCoreApplication::translate(context.toUtf8().constData(),
text.toUtf8().constData(),
comment.toUtf8().constData(),
@@ -1953,6 +1964,10 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value
if (argc > 2)
n = argv[2].toInt32();
+ if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureTranslation();
+
QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
comment.toUtf8().constData(), n);
@@ -2033,6 +2048,10 @@ ReturnedValue GlobalExtensions::method_qsTrId(const FunctionObject *b, const Val
if (argc > 1)
n = argv[1].toInt32();
+ if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureTranslation();
+
return Encode(scope.engine->newString(qtTrId(argv[0].toQStringNoThrow().toUtf8().constData(), n)));
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index ee3b5f7d6e..4b3814c8b8 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -93,8 +93,8 @@ struct QtObject : Object
{
V4_OBJECT2(QtObject, Object)
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_isQtObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_rgba(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
@@ -126,7 +126,9 @@ struct QtObject : Object
static ReturnedValue method_resolvedUrl(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_createQmlObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_createComponent(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+#if QT_CONFIG(qml_locale)
static ReturnedValue method_locale(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+#endif
static ReturnedValue method_binding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_platform(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 038a75d50a..78c9fe822b 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -39,14 +39,21 @@
#include "qv8engine_p.h"
+#if QT_CONFIG(qml_sequence_object)
#include "qv4sequenceobject_p.h"
+#endif
+
#include "private/qjsengine_p.h"
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmllist_p.h>
#include <private/qqmlengine_p.h>
+#if QT_CONFIG(qml_xml_http_request)
#include <private/qqmlxmlhttprequest_p.h>
+#endif
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <private/qqmlglobal_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qqmlplatform_p.h>
@@ -78,6 +85,7 @@
#include <private/qv4script_p.h>
#include <private/qv4include_p.h>
#include <private/qv4jsonobject_p.h>
+#include <private/qv4identifiertable_p.h>
Q_DECLARE_METATYPE(QList<int>)
@@ -123,11 +131,12 @@ static void restoreJSValue(QDataStream &stream, void *data)
}
}
-QV8Engine::QV8Engine(QJSEngine *qq, QV4::ExecutionEngine *v4)
- : q(qq)
- , m_engine(nullptr)
+QV8Engine::QV8Engine(QV4::ExecutionEngine *v4)
+ : m_engine(nullptr)
, m_v4Engine(v4)
+#if QT_CONFIG(qml_xml_http_request)
, m_xmlHttpRequestData(nullptr)
+#endif
{
#ifdef Q_PROCESSOR_X86_32
if (!qCpuHasFeature(SSE2)) {
@@ -157,7 +166,7 @@ QV8Engine::~QV8Engine()
qDeleteAll(m_extensionData);
m_extensionData.clear();
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
+#if QT_CONFIG(qml_xml_http_request)
qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
m_xmlHttpRequestData = nullptr;
#endif
@@ -180,14 +189,16 @@ void QV8Engine::initializeGlobal()
QV4::Scope scope(m_v4Engine);
QV4::GlobalExtensions::init(m_v4Engine->globalObject, QJSEngine::AllExtensions);
- QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocObject<QV4::QtObject>(m_engine));
+ QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocate<QV4::QtObject>(m_engine));
m_v4Engine->globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
+#if QT_CONFIG(qml_locale)
QQmlLocale::registerStringLocaleCompare(m_v4Engine);
QQmlDateExtension::registerExtension(m_v4Engine);
QQmlNumberExtension::registerExtension(m_v4Engine);
+#endif
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
+#if QT_CONFIG(qml_xml_http_request)
qt_add_domexceptions(m_v4Engine);
m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
#endif
@@ -196,8 +207,10 @@ void QV8Engine::initializeGlobal()
{
for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
+ if (m_v4Engine->globalObject->internalClass()->nameMap.at(i).isString()) {
+ QV4::PropertyKey id = m_v4Engine->globalObject->internalClass()->nameMap.at(i);
+ m_illegalNames.insert(id.toQString());
+ }
}
}
}
@@ -210,25 +223,25 @@ static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
QV4::Scope scope(v4);
bool instanceOfObject = false;
- QV4::ScopedObject p(scope, object->prototype());
+ QV4::ScopedObject p(scope, object->getPrototypeOf());
while (p) {
if (p->d() == v4->objectPrototype()->d()) {
instanceOfObject = true;
break;
}
- p = p->prototype();
+ p = p->getPrototypeOf();
}
if (!instanceOfObject)
return;
- QV4::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
if (object->internalClass() == frozen)
return;
object->setInternalClass(frozen);
QV4::ScopedObject o(scope);
for (uint i = 0; i < frozen->size; ++i) {
- if (!frozen->nameMap.at(i))
+ if (!frozen->nameMap.at(i).isStringOrSymbol())
continue;
o = *object->propertyData(i);
if (o)
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index b6a378667e..23559618ef 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -67,6 +67,7 @@
#include <private/qv4value_p.h>
#include <private/qv4identifier_p.h>
#include <private/qv4context_p.h>
+#include <private/qv4stackframe_p.h>
#include <private/qqmldelayedcallqueue_p.h>
QT_BEGIN_NAMESPACE
@@ -154,10 +155,9 @@ class Q_QML_PRIVATE_EXPORT QV8Engine
friend class QJSEngine;
public:
// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
- static QV4::ExecutionEngine *getV4(QJSEngine *q) { return q->handle(); }
static QV4::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; }
- QV8Engine(QJSEngine* qq, QV4::ExecutionEngine *v4);
+ QV8Engine(QV4::ExecutionEngine *v4);
virtual ~QV8Engine();
// This enum should be in sync with QQmlEngine::ObjectOwnership
@@ -170,10 +170,11 @@ public:
void initQmlGlobalObject();
void setEngine(QQmlEngine *engine);
QQmlEngine *engine() { return m_engine; }
- QJSEngine *publicEngine() { return q; }
QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
+#if QT_CONFIG(qml_xml_http_request)
void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
+#endif
void freezeObject(const QV4::Value &value);
@@ -202,13 +203,14 @@ public:
int consoleCountHelper(const QString &file, quint16 line, quint16 column);
protected:
- QJSEngine* q;
QQmlEngine *m_engine;
QQmlDelayedCallQueue m_delayedCallQueue;
QV4::ExecutionEngine *m_v4Engine;
+#if QT_CONFIG(qml_xml_http_request)
void *m_xmlHttpRequestData;
+#endif
QVector<Deletable *> m_extensionData;
diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h
index 6e92867cf5..e02dfa5ed4 100644
--- a/src/qml/qtqmlglobal.h
+++ b/src/qml/qtqmlglobal.h
@@ -52,6 +52,7 @@
# endif
#else
# define QT_FEATURE_qml_debug -1
+# define QT_FEATURE_qml_sequence_object 1
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h
index 4c0ba338d8..bb880451a9 100644
--- a/src/qml/qtqmlglobal_p.h
+++ b/src/qml/qtqmlglobal_p.h
@@ -57,6 +57,8 @@
# include <QtQml/private/qtqml-config_p.h>
#endif
+#define Q_QML_PRIVATE_API_VERSION 2
+
#define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT
#if !defined(QT_QMLDEVTOOLS_LIB) && !defined(QT_BUILD_QMLDEVTOOLS_LIB)
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 7a12813f0c..7aba0689d1 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -93,10 +93,10 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
{
- return scope->engine()->memoryManager->allocObject<DelegateModelGroupFunction>(scope, flag, code);
+ return scope->engine()->memoryManager->allocate<DelegateModelGroupFunction>(scope, flag, code);
}
- static ReturnedValue call(const QV4::FunctionObject *that, const Value *thisObject, const Value *argv, int argc)
+ static ReturnedValue virtualCall(const QV4::FunctionObject *that, const Value *thisObject, const Value *argv, int argc)
{
QV4::Scope scope(that->engine());
QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that));
@@ -200,8 +200,7 @@ QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent)
*/
QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt)
- : m_delegate(nullptr)
- , m_cacheMetaType(nullptr)
+ : m_cacheMetaType(nullptr)
, m_context(ctxt)
, m_parts(nullptr)
, m_filterGroup(QStringLiteral("items"))
@@ -214,6 +213,7 @@ QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt)
, m_transaction(false)
, m_incubatorCleanupScheduled(false)
, m_waitingToFetchMore(false)
+ , m_useFirstColumnOnly(true)
, m_cacheItems(nullptr)
, m_items(nullptr)
, m_persistedItems(nullptr)
@@ -228,6 +228,11 @@ QQmlDelegateModelPrivate::~QQmlDelegateModelPrivate()
m_cacheMetaType->release();
}
+int QQmlDelegateModelPrivate::adaptorModelCount() const
+{
+ return m_useFirstColumnOnly ? m_adaptorModel.rowCount() : m_adaptorModel.count();
+}
+
void QQmlDelegateModelPrivate::requestMoreIfNecessary()
{
Q_Q(QQmlDelegateModel);
@@ -263,6 +268,8 @@ QQmlDelegateModel::QQmlDelegateModel(QQmlContext *ctxt, QObject *parent)
QQmlDelegateModel::~QQmlDelegateModel()
{
Q_D(QQmlDelegateModel);
+ d->disconnectFromAbstractItemModel();
+ d->m_adaptorModel.setObject(nullptr, this);
for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) {
if (cacheItem->object) {
@@ -336,7 +343,7 @@ void QQmlDelegateModel::componentComplete()
static_cast<QQmlPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
QVector<Compositor::Insert> inserts;
- d->m_count = d->m_adaptorModel.count();
+ d->m_count = d->adaptorModelCount();
d->m_compositor.append(
&d->m_adaptorModel,
0,
@@ -368,6 +375,54 @@ QVariant QQmlDelegateModel::model() const
return d->m_adaptorModel.model();
}
+void QQmlDelegateModelPrivate::connectToAbstractItemModel()
+{
+ Q_Q(QQmlDelegateModel);
+ if (!m_adaptorModel.adaptsAim())
+ return;
+
+ auto aim = m_adaptorModel.aim();
+
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ q, QQmlDelegateModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
+ q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ q, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(modelReset()),
+ q, QQmlDelegateModel, SLOT(_q_modelReset()));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ q, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+}
+
+void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
+{
+ Q_Q(QQmlDelegateModel);
+ if (!m_adaptorModel.adaptsAim())
+ return;
+
+ auto aim = m_adaptorModel.aim();
+
+ QObject::disconnect(aim, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ q, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ QObject::disconnect(aim, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ q, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
+ q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ q, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObject::disconnect(aim, SIGNAL(modelReset()),
+ q, SLOT(_q_modelReset()));
+ QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
+ q, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+}
+
void QQmlDelegateModel::setModel(const QVariant &model)
{
Q_D(QQmlDelegateModel);
@@ -375,7 +430,10 @@ void QQmlDelegateModel::setModel(const QVariant &model)
if (d->m_complete)
_q_itemsRemoved(0, d->m_count);
+ d->disconnectFromAbstractItemModel();
d->m_adaptorModel.setModel(model, this, d->m_context->engine());
+ d->connectToAbstractItemModel();
+
d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles);
for (int i = 0; d->m_parts && i < d->m_parts->models.count(); ++i) {
d->m_adaptorModel.replaceWatchedRoles(
@@ -383,7 +441,7 @@ void QQmlDelegateModel::setModel(const QVariant &model)
}
if (d->m_complete) {
- _q_itemsInserted(0, d->m_adaptorModel.count());
+ _q_itemsInserted(0, d->adaptorModelCount());
d->requestMoreIfNecessary();
}
}
@@ -409,7 +467,7 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
return;
}
bool wasValid = d->m_delegate != nullptr;
- d->m_delegate = delegate;
+ d->m_delegate.setObject(delegate, this);
d->m_delegateValidated = false;
if (wasValid && d->m_complete) {
for (int i = 1; i < d->m_groupCount; ++i) {
@@ -470,12 +528,16 @@ void QQmlDelegateModel::setRootIndex(const QVariant &root)
if (changed || !d->m_adaptorModel.isValid()) {
const int oldCount = d->m_count;
d->m_adaptorModel.rootIndex = modelIndex;
- if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) // The previous root index was invalidated, so we need to reconnect the model.
+ if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) {
+ // The previous root index was invalidated, so we need to reconnect the model.
+ d->disconnectFromAbstractItemModel();
d->m_adaptorModel.setModel(d->m_adaptorModel.list.list(), this, d->m_context->engine());
+ d->connectToAbstractItemModel();
+ }
if (d->m_adaptorModel.canFetchMore())
d->m_adaptorModel.fetchMore();
if (d->m_complete) {
- const int newCount = d->m_adaptorModel.count();
+ const int newCount = d->adaptorModelCount();
if (oldCount)
_q_itemsRemoved(0, oldCount);
if (newCount)
@@ -487,6 +549,35 @@ void QQmlDelegateModel::setRootIndex(const QVariant &root)
}
/*!
+ \qmlproperty int QtQml.Models::DelegateModel::rows
+
+ Contains the number of rows in the model. If the model
+ is a list of items, it will be equal to the number of items
+ in the list.
+
+ \since QtQml.Models 2.12
+*/
+int QQmlDelegateModel::rows() const
+{
+ Q_D(const QQmlDelegateModel);
+ return d->m_adaptorModel.rowCount();
+}
+
+/*!
+ \qmlproperty int QtQml.Models::DelegateModel::columns
+
+ Contains the number of columns in the model. If the model
+ is a list of items, it will be equal to \c 1.
+
+ \since QtQml.Models 2.12
+*/
+int QQmlDelegateModel::columns() const
+{
+ Q_D(const QQmlDelegateModel);
+ return d->m_adaptorModel.columnCount();
+}
+
+/*!
\qmlmethod QModelIndex QtQml.Models::DelegateModel::modelIndex(int index)
QAbstractItemModel provides a hierarchical tree of data, whereas
@@ -536,25 +627,24 @@ int QQmlDelegateModel::count() const
QQmlDelegateModel::ReleaseFlags QQmlDelegateModelPrivate::release(QObject *object)
{
- QQmlDelegateModel::ReleaseFlags stat = nullptr;
if (!object)
- return stat;
-
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(object)) {
- if (cacheItem->releaseObject()) {
- cacheItem->destroyObject();
- emitDestroyingItem(object);
- if (cacheItem->incubationTask) {
- releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
- }
- cacheItem->Dispose();
- stat |= QQmlInstanceModel::Destroyed;
- } else {
- stat |= QQmlDelegateModel::Referenced;
- }
+ return QQmlDelegateModel::ReleaseFlags(0);
+
+ QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(object);
+ if (!cacheItem)
+ return QQmlDelegateModel::ReleaseFlags(0);
+
+ if (!cacheItem->releaseObject())
+ return QQmlDelegateModel::Referenced;
+
+ cacheItem->destroyObject();
+ emitDestroyingItem(object);
+ if (cacheItem->incubationTask) {
+ releaseIncubator(cacheItem->incubationTask);
+ cacheItem->incubationTask = nullptr;
}
- return stat;
+ cacheItem->Dispose();
+ return QQmlInstanceModel::Destroyed;
}
/*
@@ -808,6 +898,12 @@ QObject *QQmlDelegateModel::parts()
return d->m_parts;
}
+const QAbstractItemModel *QQmlDelegateModel::abstractItemModel() const
+{
+ Q_D(const QQmlDelegateModel);
+ return d->m_adaptorModel.adaptsAim() ? d->m_adaptorModel.aim() : nullptr;
+}
+
void QQmlDelegateModelPrivate::emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
{
for (int i = 1; i < m_groupCount; ++i)
@@ -862,6 +958,13 @@ void QQmlDelegateModelPrivate::releaseIncubator(QQDMIncubationTask *incubationTa
}
}
+void QQmlDelegateModelPrivate::addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it)
+{
+ m_cache.insert(it.cacheIndex, item);
+ m_compositor.setFlags(it, 1, Compositor::CacheFlag);
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+}
+
void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem)
{
int cidx = m_cache.lastIndexOf(cacheItem);
@@ -951,10 +1054,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ
return nullptr;
cacheItem->groups = it->flags;
-
- m_cache.insert(it.cacheIndex, cacheItem);
- m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ addCacheItem(cacheItem, it);
}
// Bump the reference counts temporarily so neither the content data or the delegate object
@@ -1046,7 +1146,10 @@ QQmlIncubator::Status QQmlDelegateModel::incubationStatus(int index)
if (!it->inCache())
return QQmlIncubator::Null;
- return d->m_cache.at(it.cacheIndex)->incubationTask->status();
+ if (auto incubationTask = d->m_cache.at(it.cacheIndex)->incubationTask)
+ return incubationTask->status();
+
+ return QQmlIncubator::Ready;
}
QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index, const QString &name)
@@ -1266,8 +1369,12 @@ void QQmlDelegateModel::_q_itemsInserted(int index, int count)
const QList<QQmlDelegateModelItem *> cache = d->m_cache;
for (int i = 0, c = cache.count(); i < c; ++i) {
QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() >= index)
- item->setModelIndex(item->modelIndex() + count);
+ if (item->modelIndex() >= index) {
+ const int newIndex = item->modelIndex() + count;
+ const int row = newIndex;
+ const int column = 0;
+ item->setModelIndex(newIndex, row, column);
+ }
}
QVector<Compositor::Insert> inserts;
@@ -1408,10 +1515,14 @@ void QQmlDelegateModel::_q_itemsRemoved(int index, int count)
if (!d->m_cache.contains(item))
continue;
- if (item->modelIndex() >= index + count)
- item->setModelIndex(item->modelIndex() - count);
- else if (item->modelIndex() >= index)
- item->setModelIndex(-1);
+ if (item->modelIndex() >= index + count) {
+ const int newIndex = item->modelIndex() - count;
+ const int row = newIndex;
+ const int column = 0;
+ item->setModelIndex(newIndex, row, column);
+ } else if (item->modelIndex() >= index) {
+ item->setModelIndex(-1, -1, -1);
+ }
}
QVector<Compositor::Remove> removes;
@@ -1456,10 +1567,17 @@ void QQmlDelegateModel::_q_itemsMoved(int from, int to, int count)
const QList<QQmlDelegateModelItem *> cache = d->m_cache;
for (int i = 0, c = cache.count(); i < c; ++i) {
QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() >= from && item->modelIndex() < from + count)
- item->setModelIndex(item->modelIndex() - from + to);
- else if (item->modelIndex() >= minimum && item->modelIndex() < maximum)
- item->setModelIndex(item->modelIndex() + difference);
+ if (item->modelIndex() >= from && item->modelIndex() < from + count) {
+ const int newIndex = item->modelIndex() - from + to;
+ const int row = newIndex;
+ const int column = 0;
+ item->setModelIndex(newIndex, row, column);
+ } else if (item->modelIndex() >= minimum && item->modelIndex() < maximum) {
+ const int newIndex = item->modelIndex() + difference;
+ const int row = newIndex;
+ const int column = 0;
+ item->setModelIndex(newIndex, row, column);
+ }
}
QVector<Compositor::Remove> removes;
@@ -1510,13 +1628,13 @@ void QQmlDelegateModel::_q_modelReset()
d->m_adaptorModel.rootIndex = QModelIndex();
if (d->m_complete) {
- d->m_count = d->m_adaptorModel.count();
+ d->m_count = d->adaptorModelCount();
const QList<QQmlDelegateModelItem *> cache = d->m_cache;
for (int i = 0, c = cache.count(); i < c; ++i) {
QQmlDelegateModelItem *item = cache.at(i);
if (item->modelIndex() != -1)
- item->setModelIndex(-1);
+ item->setModelIndex(-1, -1, -1);
}
QVector<Compositor::Remove> removes;
@@ -1552,7 +1670,8 @@ void QQmlDelegateModel::_q_rowsAboutToBeRemoved(const QModelIndex &parent, int b
if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
const int oldCount = d->m_count;
d->m_count = 0;
- d->m_adaptorModel.invalidateModel(this);
+ d->disconnectFromAbstractItemModel();
+ d->m_adaptorModel.invalidateModel();
if (d->m_complete && oldCount > 0) {
QVector<Compositor::Remove> removes;
@@ -1588,8 +1707,15 @@ void QQmlDelegateModel::_q_rowsMoved(
void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
{
Q_D(QQmlDelegateModel);
- if (begin.parent() == d->m_adaptorModel.rootIndex)
- _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
+ if (begin.parent() != d->m_adaptorModel.rootIndex)
+ return;
+
+ int rowCount = end.row() - begin.row() + 1;
+
+ for (int col = begin.column(); col <= end.column(); ++col) {
+ int startIndex = d->m_adaptorModel.indexAt(begin.row(), col);
+ _q_itemsChanged(startIndex, rowCount, roles);
+ }
}
bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const QList< QPersistentModelIndex >& parents) const
@@ -1804,7 +1930,7 @@ int QQmlDelegateModelItemMetaType::parseGroups(const QV4::Value &groups) const
QV4::ScopedValue v(scope);
uint arrayLength = array->getLength();
for (uint i = 0; i < arrayLength; ++i) {
- v = array->getIndexed(i);
+ v = array->get(i);
const QString groupName = v->toQString();
int index = groupNames.indexOf(groupName);
if (index != -1)
@@ -1906,8 +2032,7 @@ void QV4::Heap::QQmlDelegateModelItemObject::destroy()
}
-QQmlDelegateModelItem::QQmlDelegateModelItem(
- QQmlDelegateModelItemMetaType *metaType, int modelIndex)
+QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex, int row, int column)
: v4(metaType->v4Engine)
, metaType(metaType)
, contextData(nullptr)
@@ -1918,6 +2043,8 @@ QQmlDelegateModelItem::QQmlDelegateModelItem(
, scriptRef(0)
, groups(0)
, index(modelIndex)
+ , row(row)
+ , column(column)
{
metaType->addref();
}
@@ -1952,6 +2079,26 @@ void QQmlDelegateModelItem::Dispose()
delete this;
}
+void QQmlDelegateModelItem::setModelIndex(int idx, int newRow, int newColumn)
+{
+ if (idx == index)
+ return;
+
+ const int prevRow = row;
+ const int prevColumn = column;
+
+ index = idx;
+ row = newRow;
+ column = newColumn;
+
+ Q_EMIT modelIndexChanged();
+
+ if (row != prevRow)
+ emit rowChanged();
+ if (column != prevColumn)
+ emit columnChanged();
+}
+
void QQmlDelegateModelItem::destroyObject()
{
Q_ASSERT(object);
@@ -2080,22 +2227,29 @@ QQmlDelegateModelAttached::QQmlDelegateModelAttached(
, m_previousGroups(cacheItem->groups)
{
QQml_setParent_noEvent(this, parent);
+ resetCurrentIndex();
+ // Let m_previousIndex be equal to m_currentIndex
+ std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex));
+
+ if (!cacheItem->metaType->metaObject)
+ cacheItem->metaType->initializeMetaObject();
+
+ QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject;
+ cacheItem->metaType->metaObject->addref();
+}
+
+void QQmlDelegateModelAttached::resetCurrentIndex()
+{
if (QQDMIncubationTask *incubationTask = m_cacheItem->incubationTask) {
for (int i = 1; i < qMin<int>(m_cacheItem->metaType->groupCount, Compositor::MaximumGroupCount); ++i)
- m_currentIndex[i] = m_previousIndex[i] = incubationTask->index[i];
+ m_currentIndex[i] = incubationTask->index[i];
} else {
QQmlDelegateModelPrivate * const model = QQmlDelegateModelPrivate::get(m_cacheItem->metaType->model);
Compositor::iterator it = model->m_compositor.find(
Compositor::Cache, model->m_cache.indexOf(m_cacheItem));
for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i)
- m_currentIndex[i] = m_previousIndex[i] = it.index[i];
+ m_currentIndex[i] = it.index[i];
}
-
- if (!cacheItem->metaType->metaObject)
- cacheItem->metaType->initializeMetaObject();
-
- QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject;
- cacheItem->metaType->metaObject->addref();
}
/*!
@@ -2483,9 +2637,9 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
model->m_cacheMetaType->initializePrototype();
QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine;
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(cacheItem));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
- o->setPrototype(p);
+ o->setPrototypeOf(p);
++cacheItem->scriptRef;
return QQmlV4Handle(o);
@@ -3194,7 +3348,10 @@ QQmlIncubator::Status QQmlPartsModel::incubationStatus(int index)
if (!it->inCache())
return QQmlIncubator::Null;
- return model->m_cache.at(it.cacheIndex)->incubationTask->status();
+ if (auto incubationTask = model->m_cache.at(it.cacheIndex)->incubationTask)
+ return incubationTask->status();
+
+ return QQmlIncubator::Ready;
}
int QQmlPartsModel::indexOf(QObject *item, QObject *) const
@@ -3214,7 +3371,10 @@ void QQmlPartsModel::createdPackage(int index, QQuickPackage *package)
void QQmlPartsModel::initPackage(int index, QQuickPackage *package)
{
- emit initItem(index, package->part(m_part));
+ if (m_modelUpdatePending)
+ m_pendingPackageInitializations << index;
+ else
+ emit initItem(index, package->part(m_part));
}
void QQmlPartsModel::destroyingPackage(QQuickPackage *package)
@@ -3226,9 +3386,22 @@ void QQmlPartsModel::destroyingPackage(QQuickPackage *package)
void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
+ m_modelUpdatePending = false;
emit modelUpdated(changeSet, reset);
if (changeSet.difference() != 0)
emit countChanged();
+
+ QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
+ QVector<int> pendingPackageInitializations;
+ qSwap(pendingPackageInitializations, m_pendingPackageInitializations);
+ for (int index : pendingPackageInitializations) {
+ if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup))
+ continue;
+ QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous);
+ if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
+ emit initItem(index, package->part(m_part));
+ model->release(object);
+ }
}
//============================================================================
@@ -3238,7 +3411,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object
V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
- return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>();
+ return e->memoryManager->allocate<QQmlDelegateModelGroupChange>();
}
static QV4::ReturnedValue method_get_index(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
@@ -3275,49 +3448,49 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object
public:
static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
- return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes);
+ return engine->memoryManager->allocate<QQmlDelegateModelGroupChangeArray>(changes);
}
quint32 count() const { return d()->changes->count(); }
const QQmlChangeSet::Change &at(int index) const { return d()->changes->at(index); }
- static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
+ static QV4::ReturnedValue virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty)
{
- Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
- QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
-
- if (index >= array->count()) {
- if (hasProperty)
- *hasProperty = false;
- return QV4::Primitive::undefinedValue().asReturnedValue();
- }
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
+ QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
+ QV4::Scope scope(v4);
+ QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
+
+ if (index >= array->count()) {
+ if (hasProperty)
+ *hasProperty = false;
+ return QV4::Primitive::undefinedValue().asReturnedValue();
+ }
- const QQmlChangeSet::Change &change = array->at(index);
+ const QQmlChangeSet::Change &change = array->at(index);
- QV4::ScopedObject changeProto(scope, engineData(v4)->changeProto.value());
- QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
- object->setPrototype(changeProto);
- object->d()->change = change;
+ QV4::ScopedObject changeProto(scope, engineData(v4)->changeProto.value());
+ QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
+ object->setPrototypeOf(changeProto);
+ object->d()->change = change;
- if (hasProperty)
- *hasProperty = true;
- return object.asReturnedValue();
- }
+ if (hasProperty)
+ *hasProperty = true;
+ return object.asReturnedValue();
+ }
- static QV4::ReturnedValue get(const QV4::Managed *m, QV4::String *name, bool *hasProperty)
- {
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m);
- if (name->equals(array->engine()->id_length())) {
+ if (id == array->engine()->id_length()->propertyKey()) {
if (hasProperty)
*hasProperty = true;
return QV4::Encode(array->count());
}
- return Object::get(m, name, hasProperty);
+ return Object::virtualGet(m, id, receiver, hasProperty);
}
};
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
index b0786cd088..65b1b82d70 100644
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ b/src/qml/types/qqmldelegatemodel_p.h
@@ -88,6 +88,8 @@ class Q_QML_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, public
Q_PROPERTY(QQmlListProperty<QQmlDelegateModelGroup> groups READ groups CONSTANT)
Q_PROPERTY(QObject *parts READ parts CONSTANT)
Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
+ Q_PROPERTY(int rows READ rows NOTIFY rowsChanged REVISION 12)
+ Q_PROPERTY(int columns READ columns NOTIFY columnsChanged REVISION 12)
Q_CLASSINFO("DefaultProperty", "delegate")
Q_INTERFACES(QQmlParserStatus)
public:
@@ -107,6 +109,9 @@ public:
QVariant rootIndex() const;
void setRootIndex(const QVariant &root);
+ int rows() const;
+ int columns() const;
+
Q_INVOKABLE QVariant modelIndex(int idx) const;
Q_INVOKABLE QVariant parentModelIndex() const;
@@ -130,6 +135,8 @@ public:
QQmlListProperty<QQmlDelegateModelGroup> groups();
QObject *parts();
+ const QAbstractItemModel *abstractItemModel() const override;
+
bool event(QEvent *) override;
static QQmlDelegateModelAttached *qmlAttachedProperties(QObject *obj);
@@ -138,6 +145,8 @@ Q_SIGNALS:
void filterGroupChanged();
void defaultGroupsChanged();
void rootIndexChanged();
+ Q_REVISION(12) void rowsChanged();
+ Q_REVISION(12) void columnsChanged();
private Q_SLOTS:
void _q_itemsChanged(int index, int count, const QVector<int> &roles);
@@ -212,6 +221,7 @@ public:
QQmlDelegateModelAttached(QQmlDelegateModelItem *cacheItem, QObject *parent);
~QQmlDelegateModelAttached() {}
+ void resetCurrentIndex();
void setCacheItem(QQmlDelegateModelItem *item);
QQmlDelegateModel *model() const;
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 18980cfd7c..c4e253800a 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -68,7 +68,7 @@ typedef QQmlListCompositor Compositor;
class QQmlDelegateModelAttachedMetaObject;
-class QQmlDelegateModelItemMetaType : public QQmlRefCount
+class Q_QML_PRIVATE_EXPORT QQmlDelegateModelItemMetaType : public QQmlRefCount
{
public:
QQmlDelegateModelItemMetaType(QV4::ExecutionEngine *engine, QQmlDelegateModel *model, const QStringList &groupNames);
@@ -95,9 +95,11 @@ class QQmlDelegateModelItem : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged)
+ Q_PROPERTY(int row MEMBER row NOTIFY rowChanged)
+ Q_PROPERTY(int column MEMBER column NOTIFY columnChanged)
Q_PROPERTY(QObject *model READ modelObject CONSTANT)
public:
- QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex);
+ QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex, int row, int column);
~QQmlDelegateModelItem();
void referenceObject() { ++objectRef; }
@@ -121,7 +123,7 @@ public:
int groupIndex(Compositor::Group group);
int modelIndex() const { return index; }
- void setModelIndex(int idx) { index = idx; Q_EMIT modelIndexChanged(); }
+ virtual void setModelIndex(int idx, int newRow, int newColumn);
virtual QV4::ReturnedValue get() { return QV4::QObjectWrapper::wrap(v4, this); }
@@ -148,9 +150,13 @@ public:
Q_SIGNALS:
void modelIndexChanged();
+ void rowChanged();
+ void columnChanged();
protected:
void objectDestroyed(QObject *);
+ int row;
+ int column;
};
namespace QV4 {
@@ -190,8 +196,8 @@ public:
void statusChanged(Status) override;
void setInitialState(QObject *) override;
- QQmlDelegateModelItem *incubating;
- QQmlDelegateModelPrivate *vdm;
+ QQmlDelegateModelItem *incubating = nullptr;
+ QQmlDelegateModelPrivate *vdm = nullptr;
int index[QQmlListCompositor::MaximumGroupCount];
};
@@ -256,6 +262,8 @@ public:
void init();
void connectModel(QQmlAdaptorModel *model);
+ void connectToAbstractItemModel();
+ void disconnectFromAbstractItemModel();
void requestMoreIfNecessary();
QObject *object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode);
@@ -269,6 +277,7 @@ public:
Q_EMIT q_func()->initItem(incubationTask->index[m_compositorGroup], item); }
void emitDestroyingPackage(QQuickPackage *package);
void emitDestroyingItem(QObject *item) { Q_EMIT q_func()->destroyingItem(item); }
+ void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it);
void removeCacheItem(QQmlDelegateModelItem *cacheItem);
void updateFilterGroup();
@@ -295,6 +304,8 @@ public:
bool insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups);
+ int adaptorModelCount() const;
+
static void group_append(QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group);
static int group_count(QQmlListProperty<QQmlDelegateModelGroup> *property);
static QQmlDelegateModelGroup *group_at(QQmlListProperty<QQmlDelegateModelGroup> *property, int index);
@@ -305,7 +316,7 @@ public:
QQmlAdaptorModel m_adaptorModel;
QQmlListCompositor m_compositor;
- QQmlComponent *m_delegate;
+ QQmlStrongJSQObjectReference<QQmlComponent> m_delegate;
QQmlDelegateModelItemMetaType *m_cacheMetaType;
QPointer<QQmlContext> m_context;
QQmlDelegateModelParts *m_parts;
@@ -327,6 +338,7 @@ public:
bool m_transaction : 1;
bool m_incubatorCleanupScheduled : 1;
bool m_waitingToFetchMore : 1;
+ bool m_useFirstColumnOnly : 1;
union {
struct {
@@ -378,8 +390,10 @@ private:
QString m_part;
QString m_filterGroup;
QList<QByteArray> m_watchedRoles;
+ QVector<int> m_pendingPackageInitializations; // vector holds model indices
Compositor::Group m_compositorGroup;
bool m_inheritGroup;
+ bool m_modelUpdatePending = true;
};
class QMetaPropertyBuilder;
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 830c2bef5a..2325eca469 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -62,6 +62,8 @@
#include <QtCore/qdatetime.h>
#include <QScopedValueRollback>
+Q_DECLARE_METATYPE(const QV4::CompiledData::Binding*);
+
QT_BEGIN_NAMESPACE
// Set to 1024 as a debugging aid - easier to distinguish uids from indices of elements/models.
@@ -124,8 +126,8 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data
const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::Role::DataType type)
{
- const int dataSizes[] = { sizeof(QString), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QPointer<QObject>), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
- const int dataAlignments[] = { sizeof(QString), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
+ const int dataSizes[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QPointer<QObject>), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
+ const int dataAlignments[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
Role *r = new Role;
r->name = key;
@@ -227,6 +229,10 @@ const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QV
data.value<QJSValue>().isCallable()) {
type = Role::Function;
break;
+ } else if (data.userType() == qMetaTypeId<const QV4::CompiledData::Binding*>()
+ && data.value<const QV4::CompiledData::Binding*>()->isTranslationBinding()) {
+ type = Role::String;
+ break;
} else {
type = Role::List;
break;
@@ -261,6 +267,75 @@ const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key) const
return r;
}
+StringOrTranslation::StringOrTranslation(const QString &s)
+{
+ d.setFlag();
+ setString(s);
+}
+
+StringOrTranslation::StringOrTranslation(const QV4::CompiledData::Binding *binding)
+{
+ d.setFlag();
+ clear();
+ d = binding;
+}
+
+StringOrTranslation::~StringOrTranslation()
+{
+ clear();
+}
+
+void StringOrTranslation::setString(const QString &s)
+{
+ d.setFlag();
+ clear();
+ QStringData *stringData = const_cast<QString &>(s).data_ptr();
+ d = stringData;
+ if (stringData)
+ stringData->ref.ref();
+}
+
+void StringOrTranslation::setTranslation(const QV4::CompiledData::Binding *binding)
+{
+ d.setFlag();
+ clear();
+ d = binding;
+}
+
+QString StringOrTranslation::toString(const QQmlListModel *owner) const
+{
+ if (d.isNull())
+ return QString();
+ if (d.isT1()) {
+ QStringDataPtr holder = { d.asT1() };
+ holder.ptr->ref.ref();
+ return QString(holder);
+ }
+ if (!owner)
+ return QString();
+ return d.asT2()->valueAsString(owner->m_compilationUnit->data);
+}
+
+QString StringOrTranslation::asString() const
+{
+ if (d.isNull())
+ return QString();
+ if (!d.isT1())
+ return QString();
+ QStringDataPtr holder = { d.asT1() };
+ holder.ptr->ref.ref();
+ return QString(holder);
+}
+
+void StringOrTranslation::clear()
+{
+ if (QStringData *strData = d.isT1() ? d.asT1() : nullptr) {
+ if (!strData->ref.deref())
+ QStringData::deallocate(strData);
+ }
+ d = static_cast<QStringData *>(nullptr);
+}
+
QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
{
ListElement *e = elements[elementIndex];
@@ -512,7 +587,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
- o = a->getIndexed(j);
+ o = a->get(j);
subModel->append(o);
}
@@ -593,7 +668,7 @@ void ListModel::set(int elementIndex, QV4::Object *object)
int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
- o = a->getIndexed(j);
+ o = a->get(j);
subModel->append(o);
}
@@ -717,11 +792,11 @@ ModelNodeMetaObject *ListElement::objectCache()
return ModelNodeMetaObject::get(m_objectCache);
}
-QString *ListElement::getStringProperty(const ListLayout::Role &role)
+StringOrTranslation *ListElement::getStringProperty(const ListLayout::Role &role)
{
char *mem = getPropertyMemory(role);
- QString *s = reinterpret_cast<QString *>(mem);
- return s->data_ptr() ? s : nullptr;
+ StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
+ return s;
}
QObject *ListElement::getQObjectProperty(const ListLayout::Role &role)
@@ -806,9 +881,9 @@ QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListMo
break;
case ListLayout::Role::String:
{
- QString *value = reinterpret_cast<QString *>(mem);
- if (value->data_ptr() != nullptr)
- data = *value;
+ StringOrTranslation *value = reinterpret_cast<StringOrTranslation *>(mem);
+ if (value->isSet())
+ data = value->toString(owner);
}
break;
case ListLayout::Role::Bool:
@@ -878,15 +953,13 @@ int ListElement::setStringProperty(const ListLayout::Role &role, const QString &
if (role.type == ListLayout::Role::String) {
char *mem = getPropertyMemory(role);
- QString *c = reinterpret_cast<QString *>(mem);
+ StringOrTranslation *c = reinterpret_cast<StringOrTranslation *>(mem);
bool changed;
- if (c->data_ptr() == nullptr) {
- new (mem) QString(s);
+ if (!c->isSet() || c->isTranslation())
changed = true;
- } else {
- changed = c->compare(s) != 0;
- *c = s;
- }
+ else
+ changed = c->asString().compare(s) != 0;
+ c->setString(s);
if (changed)
roleIndex = role.index;
}
@@ -1048,11 +1121,25 @@ int ListElement::setFunctionProperty(const ListLayout::Role &role, const QJSValu
return roleIndex;
}
+int ListElement::setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b)
+{
+ int roleIndex = -1;
+
+ if (role.type == ListLayout::Role::String) {
+ char *mem = getPropertyMemory(role);
+ StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
+ s->setTranslation(b);
+ roleIndex = role.index;
+ }
+
+ return roleIndex;
+}
+
void ListElement::setStringPropertyFast(const ListLayout::Role &role, const QString &s)
{
char *mem = getPropertyMemory(role);
- new (mem) QString(s);
+ new (mem) StringOrTranslation(s);
}
void ListElement::setDoublePropertyFast(const ListLayout::Role &role, double d)
@@ -1219,9 +1306,9 @@ void ListElement::destroy(ListLayout *layout)
switch (r.type) {
case ListLayout::Role::String:
{
- QString *string = getStringProperty(r);
+ StringOrTranslation *string = getStringProperty(r);
if (string)
- string->~QString();
+ string->~StringOrTranslation();
}
break;
case ListLayout::Role::List:
@@ -1284,7 +1371,10 @@ int ListElement::setVariantProperty(const ListLayout::Role &role, const QVariant
roleIndex = setDoubleProperty(role, d.toDouble());
break;
case ListLayout::Role::String:
- roleIndex = setStringProperty(role, d.toString());
+ if (d.userType() == qMetaTypeId<const QV4::CompiledData::Binding *>())
+ roleIndex = setTranslationProperty(role, d.value<const QV4::CompiledData::Binding*>());
+ else
+ roleIndex = setStringProperty(role, d.toString());
break;
case ListLayout::Role::Bool:
roleIndex = setBoolProperty(role, d.toBool());
@@ -1332,7 +1422,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
ListModel *subModel = new ListModel(role.subLayout, nullptr);
int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
- o = a->getIndexed(j);
+ o = a->get(j);
subModel->append(o);
}
roleIndex = setListProperty(role, subModel);
@@ -1446,7 +1536,7 @@ void ModelNodeMetaObject::propertyWritten(int index)
return;
QString propName = QString::fromUtf8(name(index));
- QVariant value = operator[](index);
+ const QVariant value = this->value(index);
QV4::Scope scope(m_model->engine());
QV4::ScopedValue v(scope, scope.engine->fromVariant(value));
@@ -1474,29 +1564,37 @@ void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCo
namespace QV4 {
-bool ModelObject::put(Managed *m, String *name, const Value &value)
+bool ModelObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
+ if (!id.isString())
+ return Object::virtualPut(m, id, value, receiver);
+ QString propName = id.toQString();
+
ModelObject *that = static_cast<ModelObject*>(m);
ExecutionEngine *eng = that->engine();
const int elementIndex = that->d()->elementIndex();
- const QString propName = name->toQString();
int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
if (roleIndex != -1)
that->d()->m_model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
if (mo->initialized())
- mo->emitPropertyNotification(name->toQString().toUtf8());
+ mo->emitPropertyNotification(propName.toUtf8());
return true;
}
-ReturnedValue ModelObject::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue ModelObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
+ if (!id.isString())
+ return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
+
const ModelObject *that = static_cast<const ModelObject*>(m);
+ Scope scope(that);
+ ScopedString name(scope, id.asStringOrSymbol());
const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
if (!role)
- return QObjectWrapper::get(m, name, hasProperty);
+ return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
if (hasProperty)
*hasProperty = true;
@@ -1512,7 +1610,7 @@ ReturnedValue ModelObject::get(const Managed *m, String *name, bool *hasProperty
return that->engine()->fromVariant(value);
}
-void ModelObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+void ModelObject::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
ModelObject *that = static_cast<ModelObject*>(m);
ExecutionEngine *v4 = that->engine();
@@ -1532,7 +1630,7 @@ void ModelObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, u
// Fall back to QV4::Object as opposed to QV4::QObjectWrapper otherwise it will add
// unnecessary entries that relate to the roles used. These just create extra work
// later on as they will just be ignored.
- QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+ QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
DEFINE_OBJECT_VTABLE(ModelObject);
@@ -1809,6 +1907,7 @@ QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::E
m_listModel = data;
m_engine = engine;
+ m_compilationUnit = owner->m_compilationUnit;
}
QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent)
@@ -1828,6 +1927,7 @@ QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agen
ListModel::sync(orig->m_listModel, m_listModel);
m_engine = nullptr;
+ m_compilationUnit = orig->m_compilationUnit;
}
QQmlListModel::~QQmlListModel()
@@ -2244,7 +2344,7 @@ void QQmlListModel::insert(QQmlV4Function *args)
int objectArrayLength = objectArray->getLength();
emitItemsAboutToBeInserted(index, objectArrayLength);
for (int i=0 ; i < objectArrayLength ; ++i) {
- argObject = objectArray->getIndexed(i);
+ argObject = objectArray->get(i);
if (m_dynamicRoles) {
m_modelObjects.insert(index+i, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
@@ -2356,7 +2456,7 @@ void QQmlListModel::append(QQmlV4Function *args)
emitItemsAboutToBeInserted(index, objectArrayLength);
for (int i=0 ; i < objectArrayLength ; ++i) {
- argObject = objectArray->getIndexed(i);
+ argObject = objectArray->get(i);
if (m_dynamicRoles) {
m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
@@ -2434,7 +2534,7 @@ QQmlV4Handle QQmlListModel::get(int index) const
QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
QQmlData *ddata = QQmlData::get(object);
if (ddata->jsWrapper.isNullOrUndefined()) {
- result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this));
+ result = scope.engine->memoryManager->allocate<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this));
// Keep track of the QObjectWrapper in persistent value storage
ddata->jsWrapper.set(scope.engine, result);
} else {
@@ -2631,7 +2731,9 @@ bool QQmlListModelParser::applyProperty(QV4::CompiledData::CompilationUnit *comp
} else {
QVariant value;
- if (binding->evaluatesToString()) {
+ if (binding->isTranslationBinding()) {
+ value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding);
+ } else if (binding->evaluatesToString()) {
value = binding->valueAsString(qmlUnit);
} else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
value = binding->valueAsNumber();
@@ -2693,6 +2795,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, QV4::CompiledData::Compila
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
rv->m_engine = qmlEngine(rv)->handle();
+ rv->m_compilationUnit = compilationUnit;
const QV4::CompiledData::Unit *qmlUnit = compilationUnit->data;
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 0c0859dc80..56a1a95a02 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -64,6 +64,8 @@
#include <private/qv4engine_p.h>
#include <private/qpodvector_p.h>
+QT_REQUIRE_CONFIG(qml_list_model);
+
QT_BEGIN_NAMESPACE
@@ -122,6 +124,7 @@ private:
friend class ListElement;
friend class DynamicRoleModelNode;
friend class DynamicRoleModelNodeMetaObject;
+ friend struct StringOrTranslation;
// Constructs a flat list model for a worker agent
QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent);
@@ -133,6 +136,7 @@ private:
QQmlListModelWorkerAgent *m_agent;
mutable QV4::ExecutionEngine *m_engine;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
bool m_mainThread;
bool m_primary;
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index ad5e94c909..e4a850e8a5 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -57,6 +57,8 @@
#include <private/qv4qobjectwrapper_p.h>
#include <qqml.h>
+QT_REQUIRE_CONFIG(qml_list_model);
+
QT_BEGIN_NAMESPACE
@@ -142,16 +144,6 @@ protected:
private:
using QQmlOpenMetaObject::setValue;
- void setValue(const QByteArray &name, const QVariant &val, bool force)
- {
- if (force) {
- QVariant existingValue = value(name);
- if (existingValue.isValid()) {
- (*this)[name] = QVariant();
- }
- }
- setValue(name, val);
- }
void emitDirectNotifies(const int *changedRoles, int roleCount);
@@ -181,12 +173,13 @@ struct ModelObject : public QObjectWrapper {
struct ModelObject : public QObjectWrapper
{
- static bool put(Managed *m, String *name, const Value& value);
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
-
V4_OBJECT2(ModelObject, QObjectWrapper)
V4_NEEDS_DESTROY
+
+protected:
+ static bool virtualPut(Managed *m, PropertyKey id, const Value& value, Value *receiver);
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
} // namespace QV4
@@ -252,6 +245,22 @@ private:
QStringHash<Role *> roleHash;
};
+struct StringOrTranslation
+{
+ explicit StringOrTranslation(const QString &s);
+ explicit StringOrTranslation(const QV4::CompiledData::Binding *binding);
+ ~StringOrTranslation();
+ bool isSet() const { return d.flag(); }
+ bool isTranslation() const { return d.isT2(); }
+ void setString(const QString &s);
+ void setTranslation(const QV4::CompiledData::Binding *binding);
+ QString toString(const QQmlListModel *owner) const;
+ QString asString() const;
+private:
+ void clear();
+ QBiPointer<QStringData, const QV4::CompiledData::Binding> d;
+};
+
/*!
\internal
*/
@@ -287,6 +296,7 @@ private:
int setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m);
int setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt);
int setFunctionProperty(const ListLayout::Role &role, const QJSValue &f);
+ int setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b);
void setStringPropertyFast(const ListLayout::Role &role, const QString &s);
void setDoublePropertyFast(const ListLayout::Role &role, double n);
@@ -301,7 +311,7 @@ private:
QVariant getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng);
ListModel *getListProperty(const ListLayout::Role &role);
- QString *getStringProperty(const ListLayout::Role &role);
+ StringOrTranslation *getStringProperty(const ListLayout::Role &role);
QObject *getQObjectProperty(const ListLayout::Role &role);
QPointer<QObject> *getGuardProperty(const ListLayout::Role &role);
QVariantMap *getVariantMapProperty(const ListLayout::Role &role);
diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h
index 2120f25744..ae2d4b11e0 100644
--- a/src/qml/types/qqmllistmodelworkeragent_p.h
+++ b/src/qml/types/qqmllistmodelworkeragent_p.h
@@ -59,6 +59,8 @@
#include <private/qv8engine_p.h>
+QT_REQUIRE_CONFIG(qml_list_model);
+
QT_BEGIN_NAMESPACE
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
index e217b63c6f..d9756704d1 100644
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ b/src/qml/types/qqmlmodelsmodule.cpp
@@ -39,7 +39,9 @@
#include "qqmlmodelsmodule_p.h"
#include <QtCore/qitemselectionmodel.h>
+#if QT_CONFIG(qml_list_model)
#include <private/qqmllistmodel_p.h>
+#endif
#if QT_CONFIG(qml_delegate_model)
#include <private/qqmldelegatemodel_p.h>
#endif
@@ -51,10 +53,13 @@ void QQmlModelsModule::defineModule()
{
const char uri[] = "QtQml.Models";
+#if QT_CONFIG(qml_list_model)
qmlRegisterType<QQmlListElement>(uri, 2, 1, "ListElement");
qmlRegisterCustomType<QQmlListModel>(uri, 2, 1, "ListModel", new QQmlListModelParser);
+#endif
#if QT_CONFIG(qml_delegate_model)
qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
+ qmlRegisterType<QQmlDelegateModel,12>(uri, 2, 9, "DelegateModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
#endif
qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
index 267828dcdd..4ac4f1c65b 100644
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ b/src/qml/types/qqmlobjectmodel_p.h
@@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE
class QObject;
class QQmlChangeSet;
+class QAbstractItemModel;
class Q_QML_PRIVATE_EXPORT QQmlInstanceModel : public QObject
{
@@ -83,6 +84,7 @@ public:
virtual QQmlIncubator::Status incubationStatus(int index) = 0;
virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
+ virtual const QAbstractItemModel *abstractItemModel() const { return nullptr; }
Q_SIGNALS:
void countChanged();
diff --git a/src/qml/types/qqmltableinstancemodel.cpp b/src/qml/types/qqmltableinstancemodel.cpp
new file mode 100644
index 0000000000..dcad84cfb8
--- /dev/null
+++ b/src/qml/types/qqmltableinstancemodel.cpp
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmltableinstancemodel_p.h"
+#include "qqmltableinstancemodel_p.h"
+
+#include <QtCore/QTimer>
+
+#include <QtQml/private/qqmlincubator_p.h>
+#include <QtQml/private/qqmlchangeset_p.h>
+#include <QtQml/private/qqmlcomponent_p.h>
+
+QT_BEGIN_NAMESPACE
+
+const char* kModelItemTag = "_tableinstancemodel_modelItem";
+
+bool QQmlTableInstanceModel::isDoneIncubating(QQmlDelegateModelItem *modelItem)
+{
+ if (!modelItem->incubationTask)
+ return true;
+
+ const auto status = modelItem->incubationTask->status();
+ return (status == QQmlIncubator::Ready) || (status == QQmlIncubator::Error);
+}
+
+void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelItem)
+{
+ Q_ASSERT(modelItem);
+
+ delete modelItem->object;
+ modelItem->object = nullptr;
+
+ if (modelItem->contextData) {
+ modelItem->contextData->invalidate();
+ Q_ASSERT(modelItem->contextData->refCount == 1);
+ modelItem->contextData = nullptr;
+ }
+
+ modelItem->deleteLater();
+}
+
+QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent)
+ : QQmlInstanceModel(*(new QObjectPrivate()), parent)
+ , m_qmlContext(qmlContext)
+ , m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList()))
+{
+}
+
+QQmlTableInstanceModel::~QQmlTableInstanceModel()
+{
+ deleteAllFinishedIncubationTasks();
+
+ // If we have model items loaded at this point, it means that
+ // the view is still holding references to them. So basically
+ // the view needs to be deleted first (and thereby release all
+ // its items), before this destructor is run.
+ Q_ASSERT(m_modelItems.isEmpty());
+}
+
+QObject *QQmlTableInstanceModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
+{
+ Q_ASSERT(m_delegate);
+ Q_ASSERT(index >= 0 && index < m_adaptorModel.count());
+ Q_ASSERT(m_qmlContext && m_qmlContext->isValid());
+
+ // Check if we've already created an item for the given index
+ QQmlDelegateModelItem *modelItem = m_modelItems.value(index, nullptr);
+
+ if (!modelItem) {
+ // Create a new model item
+ modelItem = m_adaptorModel.createItem(m_metaType, index);
+ if (!modelItem) {
+ qWarning() << Q_FUNC_INFO << "Adaptor model failed creating a model item";
+ return nullptr;
+ }
+ m_modelItems.insert(index, modelItem);
+ }
+
+ if (modelItem->object) {
+ // The model item has already been incubated. So
+ // just bump the ref-count and return it.
+ modelItem->referenceObject();
+ return modelItem->object;
+ }
+
+ // Guard the model item temporarily so that it's not deleted from
+ // incubatorStatusChanged(), in case the incubation is done synchronously.
+ modelItem->scriptRef++;
+
+ if (modelItem->incubationTask) {
+ // We're already incubating the model item from a previous request. If the previous call requested
+ // the item async, but the current request needs it sync, we need to force-complete the incubation.
+ const bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
+ if (sync && modelItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous)
+ modelItem->incubationTask->forceCompletion();
+ } else {
+ modelItem->incubationTask = new QQmlTableInstanceModelIncubationTask(this, modelItem, incubationMode);
+
+ QQmlContextData *ctxt = new QQmlContextData;
+ QQmlContext *creationContext = m_delegate->creationContext();
+ ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data()));
+ ctxt->contextObject = modelItem;
+ modelItem->contextData = ctxt;
+
+ QQmlComponentPrivate::get(m_delegate)->incubateObject(
+ modelItem->incubationTask,
+ m_delegate,
+ m_qmlContext->engine(),
+ ctxt,
+ QQmlContextData::get(m_qmlContext));
+ }
+
+ // Remove the temporary guard
+ modelItem->scriptRef--;
+ Q_ASSERT(modelItem->scriptRef == 0);
+
+ if (!isDoneIncubating(modelItem))
+ return nullptr;
+
+ // When incubation is done, the task should be removed
+ Q_ASSERT(!modelItem->incubationTask);
+
+ if (!modelItem->object) {
+ // The object was incubated synchronously (otherwise we would return above). But since
+ // we have no object, the incubation must have failed. And when we have no object, there
+ // should be no object references either. And there should also not be any internal script
+ // refs at this point. So we delete the model item.
+ Q_ASSERT(!modelItem->isObjectReferenced());
+ Q_ASSERT(!modelItem->isReferenced());
+ m_modelItems.remove(modelItem->index);
+ delete modelItem;
+ return nullptr;
+ }
+
+ // Incubation was completed sync and successful
+ modelItem->referenceObject();
+ return modelItem->object;
+}
+
+QQmlInstanceModel::ReleaseFlags QQmlTableInstanceModel::release(QObject *object)
+{
+ Q_ASSERT(object);
+ auto modelItem = qvariant_cast<QQmlDelegateModelItem *>(object->property(kModelItemTag));
+ Q_ASSERT(modelItem);
+
+ if (!modelItem->releaseObject())
+ return QQmlDelegateModel::Referenced;
+
+ if (modelItem->isReferenced()) {
+ // We still have an internal reference to this object, which means that we are told to release an
+ // object while the createdItem signal for it is still on the stack. This can happen when objects
+ // are e.g delivered async, and the user flicks back and forth quicker than the loading can catch
+ // up with. The view might then find that the object is no longer visible and should be released.
+ // We detect this case in incubatorStatusChanged(), and delete it there instead. But from the callers
+ // points of view, it should consider it destroyed.
+ return QQmlDelegateModel::Destroyed;
+ }
+
+ m_modelItems.remove(modelItem->index);
+ modelItem->destroyObject();
+ emit destroyingItem(object);
+
+ delete modelItem;
+ return QQmlInstanceModel::Destroyed;
+}
+
+void QQmlTableInstanceModel::cancel(int index)
+{
+ auto modelItem = m_modelItems.value(index);
+ Q_ASSERT(modelItem);
+
+ // Since the view expects the item to be incubating, there should be
+ // an incubation task. And since the incubation is not done, no-one
+ // should yet have received, and therfore hold a reference to, the object.
+ Q_ASSERT(modelItem->incubationTask);
+ Q_ASSERT(!modelItem->isObjectReferenced());
+
+ m_modelItems.remove(index);
+
+ if (modelItem->object)
+ delete modelItem->object;
+
+ // modelItem->incubationTask will be deleted from the modelItems destructor
+ delete modelItem;
+}
+
+void QQmlTableInstanceModel::incubatorStatusChanged(QQmlTableInstanceModelIncubationTask *incubationTask, QQmlIncubator::Status status)
+{
+ QQmlDelegateModelItem *modelItem = incubationTask->modelItemToIncubate;
+ Q_ASSERT(modelItem->incubationTask);
+
+ modelItem->incubationTask = nullptr;
+ incubationTask->modelItemToIncubate = nullptr;
+
+ if (status == QQmlIncubator::Ready) {
+ // Tag the incubated object with the model item for easy retrieval upon release etc.
+ modelItem->object->setProperty(kModelItemTag, QVariant::fromValue(modelItem));
+
+ // Emit that the item has been created. What normally happens next is that the view
+ // upon receiving the signal asks for the model item once more. And since the item is
+ // now in the map, it will be returned directly.
+ Q_ASSERT(modelItem->object);
+ modelItem->scriptRef++;
+ emit createdItem(modelItem->index, modelItem->object);
+ modelItem->scriptRef--;
+ } else if (status == QQmlIncubator::Error) {
+ qWarning() << "Error incubating delegate:" << incubationTask->errors();
+ }
+
+ if (!modelItem->isReferenced() && !modelItem->isObjectReferenced()) {
+ // We have no internal reference to the model item, and the view has no
+ // reference to the incubated object. So just delete the model item.
+ // Note that being here means that the object was incubated _async_
+ // (otherwise modelItem->isReferenced() would be true).
+ m_modelItems.remove(modelItem->index);
+
+ if (modelItem->object) {
+ modelItem->scriptRef++;
+ emit destroyingItem(modelItem->object);
+ modelItem->scriptRef--;
+ Q_ASSERT(!modelItem->isReferenced());
+ }
+
+ deleteModelItemLater(modelItem);
+ }
+
+ deleteIncubationTaskLater(incubationTask);
+}
+
+QQmlIncubator::Status QQmlTableInstanceModel::incubationStatus(int index) {
+ const auto modelItem = m_modelItems.value(index, nullptr);
+ if (!modelItem)
+ return QQmlIncubator::Null;
+
+ if (modelItem->incubationTask)
+ return modelItem->incubationTask->status();
+
+ // Since we clear the incubation task when we're done
+ // incubating, it means that the status is Ready.
+ return QQmlIncubator::Ready;
+}
+
+void QQmlTableInstanceModel::deleteIncubationTaskLater(QQmlIncubator *incubationTask)
+{
+ // We often need to post-delete incubation tasks, since we cannot
+ // delete them while we're in the middle of an incubation change callback.
+ Q_ASSERT(!m_finishedIncubationTasks.contains(incubationTask));
+ m_finishedIncubationTasks.append(incubationTask);
+ if (m_finishedIncubationTasks.count() == 1)
+ QTimer::singleShot(1, this, &QQmlTableInstanceModel::deleteAllFinishedIncubationTasks);
+}
+
+void QQmlTableInstanceModel::deleteAllFinishedIncubationTasks()
+{
+ qDeleteAll(m_finishedIncubationTasks);
+ m_finishedIncubationTasks.clear();
+}
+
+QVariant QQmlTableInstanceModel::model() const
+{
+ return m_adaptorModel.model();
+}
+
+void QQmlTableInstanceModel::setModel(const QVariant &model)
+{
+ m_adaptorModel.setModel(model, this, m_qmlContext->engine());
+}
+
+QQmlComponent *QQmlTableInstanceModel::delegate() const
+{
+ return m_delegate;
+}
+
+void QQmlTableInstanceModel::setDelegate(QQmlComponent *delegate)
+{
+ m_delegate = delegate;
+}
+
+const QAbstractItemModel *QQmlTableInstanceModel::abstractItemModel() const
+{
+ return m_adaptorModel.aim();
+}
+
+// --------------------------------------------------------
+
+void QQmlTableInstanceModelIncubationTask::setInitialState(QObject *object)
+{
+ modelItemToIncubate->object = object;
+ emit tableInstanceModel->initItem(modelItemToIncubate->index, object);
+}
+
+void QQmlTableInstanceModelIncubationTask::statusChanged(QQmlIncubator::Status status)
+{
+ if (!QQmlTableInstanceModel::isDoneIncubating(modelItemToIncubate))
+ return;
+
+ // We require the view to cancel any ongoing load
+ // requests before the tableInstanceModel is destructed.
+ Q_ASSERT(tableInstanceModel);
+
+ tableInstanceModel->incubatorStatusChanged(this, status);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/qml/types/qqmltableinstancemodel_p.h b/src/qml/types/qqmltableinstancemodel_p.h
new file mode 100644
index 0000000000..fb222d8bc4
--- /dev/null
+++ b/src/qml/types/qqmltableinstancemodel_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLTABLEINSTANCEMODEL_P_H
+#define QQMLTABLEINSTANCEMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <QtQml/private/qqmldelegatemodel_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTableInstanceModel;
+
+class QQmlTableInstanceModelIncubationTask : public QQDMIncubationTask
+{
+public:
+ QQmlTableInstanceModelIncubationTask(
+ QQmlTableInstanceModel *tableInstanceModel
+ , QQmlDelegateModelItem* modelItemToIncubate
+ , IncubationMode mode)
+ : QQDMIncubationTask(nullptr, mode)
+ , modelItemToIncubate(modelItemToIncubate)
+ , tableInstanceModel(tableInstanceModel) {
+ clear();
+ }
+
+ void statusChanged(Status status) override;
+ void setInitialState(QObject *object) override;
+
+ QQmlDelegateModelItem *modelItemToIncubate = nullptr;
+ QQmlTableInstanceModel *tableInstanceModel = nullptr;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlTableInstanceModel : public QQmlInstanceModel
+{
+public:
+ QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent = nullptr);
+ ~QQmlTableInstanceModel() override;
+
+ int count() const override { return m_adaptorModel.count(); }
+ int rows() const { return m_adaptorModel.rowCount(); }
+ int columns() const { return m_adaptorModel.columnCount(); }
+
+ bool isValid() const override { return true; }
+
+ QVariant model() const;
+ void setModel(const QVariant &model);
+
+ QQmlComponent *delegate() const;
+ void setDelegate(QQmlComponent *);
+
+ const QAbstractItemModel *abstractItemModel() const override;
+
+ QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
+ ReleaseFlags release(QObject *) override;
+ void cancel(int) override;
+
+ QQmlIncubator::Status incubationStatus(int index) override;
+
+ QString stringValue(int, const QString &) override { Q_UNREACHABLE(); return QString(); }
+ void setWatchedRoles(const QList<QByteArray> &) override { Q_UNREACHABLE(); }
+ int indexOf(QObject *, QObject *) const override { Q_UNREACHABLE(); return 0; }
+
+private:
+ QQmlComponent *m_delegate = nullptr;
+ QQmlAdaptorModel m_adaptorModel;
+ QPointer<QQmlContext> m_qmlContext;
+ QQmlDelegateModelItemMetaType *m_metaType;
+
+ QHash<int, QQmlDelegateModelItem *> m_modelItems;
+ QList<QQmlIncubator *> m_finishedIncubationTasks;
+
+ void incubatorStatusChanged(QQmlTableInstanceModelIncubationTask *dmIncubationTask, QQmlIncubator::Status status);
+ void deleteIncubationTaskLater(QQmlIncubator *incubationTask);
+ void deleteAllFinishedIncubationTasks();
+
+ static bool isDoneIncubating(QQmlDelegateModelItem *modelItem);
+ static void deleteModelItemLater(QQmlDelegateModelItem *modelItem);
+
+ friend class QQmlTableInstanceModelIncubationTask;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLTABLEINSTANCEMODEL_P_H
diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h
index d597869994..0160e97a2f 100644
--- a/src/qml/types/qqmltimer_p.h
+++ b/src/qml/types/qqmltimer_p.h
@@ -57,6 +57,8 @@
#include <private/qtqmlglobal_p.h>
+QT_REQUIRE_CONFIG(qml_animation);
+
QT_BEGIN_NAMESPACE
class QQmlTimerPrivate;
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 98f819337b..f8879160b2 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -37,9 +37,12 @@
**
****************************************************************************/
+#include "qtqmlglobal_p.h"
#include "qquickworkerscript_p.h"
+#if QT_CONFIG(qml_list_model)
#include "qqmllistmodel_p.h"
#include "qqmllistmodelworkeragent_p.h"
+#endif
#include <private/qqmlengine_p.h>
#include <private/qqmlexpression_p.h>
@@ -201,7 +204,7 @@ private:
};
QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent)
- : QV8Engine(nullptr, new QV4::ExecutionEngine), p(parent)
+ : QV8Engine(new QV4::ExecutionEngine), p(parent)
#if QT_CONFIG(qml_network)
, accessManager(nullptr)
#endif
@@ -241,14 +244,13 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
QV4::Scope scope(m_v4Engine);
QV4::ExecutionContext *globalContext = scope.engine->rootContext();
- onmessage.set(scope.engine, QV4::Script(globalContext, QV4::Compiler::GlobalCode, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
+ onmessage.set(scope.engine, QV4::Script(globalContext, QV4::Compiler::ContextType::Global, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
Q_ASSERT(!scope.engine->hasException);
- QV4::Script createsendscript(globalContext, QV4::Compiler::GlobalCode, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
+ QV4::Script createsendscript(globalContext, QV4::Compiler::ContextType::Global, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
QV4::ScopedFunctionObject createsendconstructor(scope, createsendscript.run());
Q_ASSERT(!scope.engine->hasException);
QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
- QV4::ScopedValue function(scope, QV4::FunctionObject::createBuiltinFunction(globalContext, name,
- QQuickWorkerScriptEnginePrivate::method_sendMessage));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createBuiltinFunction(m_v4Engine, name, method_sendMessage, 1));
QV4::JSCallData jsCallData(scope, 1);
jsCallData->args[0] = function;
*jsCallData->thisObject = m_v4Engine->global();
diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri
index 8bcbd6e544..6a74d70a0e 100644
--- a/src/qml/types/types.pri
+++ b/src/qml/types/types.pri
@@ -1,28 +1,36 @@
SOURCES += \
$$PWD/qqmlbind.cpp \
$$PWD/qqmlconnections.cpp \
- $$PWD/qqmllistmodel.cpp \
- $$PWD/qqmllistmodelworkeragent.cpp \
$$PWD/qqmlmodelsmodule.cpp \
$$PWD/qqmlmodelindexvaluetype.cpp \
$$PWD/qqmlobjectmodel.cpp \
$$PWD/qquickpackage.cpp \
$$PWD/qquickworkerscript.cpp \
- $$PWD/qqmlinstantiator.cpp
+ $$PWD/qqmlinstantiator.cpp \
+ $$PWD/qqmltableinstancemodel.cpp
HEADERS += \
$$PWD/qqmlbind_p.h \
$$PWD/qqmlconnections_p.h \
- $$PWD/qqmllistmodel_p.h \
- $$PWD/qqmllistmodel_p_p.h \
- $$PWD/qqmllistmodelworkeragent_p.h \
$$PWD/qqmlmodelsmodule_p.h \
$$PWD/qqmlmodelindexvaluetype_p.h \
$$PWD/qqmlobjectmodel_p.h \
$$PWD/qquickpackage_p.h \
$$PWD/qquickworkerscript_p.h \
$$PWD/qqmlinstantiator_p.h \
- $$PWD/qqmlinstantiator_p_p.h
+ $$PWD/qqmlinstantiator_p_p.h \
+ $$PWD/qqmltableinstancemodel_p.h
+
+qtConfig(qml-list-model) {
+ SOURCES += \
+ $$PWD/qqmllistmodel.cpp \
+ $$PWD/qqmllistmodelworkeragent.cpp
+
+ HEADERS += \
+ $$PWD/qqmllistmodel_p.h \
+ $$PWD/qqmllistmodel_p_p.h \
+ $$PWD/qqmllistmodelworkeragent_p.h
+}
qtConfig(qml-delegate-model) {
SOURCES += \
@@ -33,7 +41,7 @@ qtConfig(qml-delegate-model) {
$$PWD/qqmldelegatemodel_p_p.h
}
-qtConfig(animation) {
+qtConfig(qml-animation) {
SOURCES += \
$$PWD/qqmltimer.cpp
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index b4bebb9d5d..24d9c14611 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -96,7 +96,7 @@ public:
QQmlDMCachedModelData(
QQmlDelegateModelItemMetaType *metaType,
VDMModelDelegateDataType *dataType,
- int index);
+ int index, int row, int column);
int metaCall(QMetaObject::Call call, int id, void **arguments);
@@ -228,8 +228,8 @@ public:
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
QV4::ExecutionContext *global = v4->rootContext();
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
+ QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
+ QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
p->setGetter(g);
p->setSetter(s);
proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
@@ -262,9 +262,8 @@ public:
bool hasModelData;
};
-QQmlDMCachedModelData::QQmlDMCachedModelData(
- QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index)
- : QQmlDelegateModelItem(metaType, index)
+QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index, int row, int column)
+ : QQmlDelegateModelItem(metaType, index, row, column)
, type(dataType)
{
if (index == -1)
@@ -326,13 +325,12 @@ void QQmlDMCachedModelData::setValue(const QString &role, const QVariant &value)
}
}
-bool QQmlDMCachedModelData::resolveIndex(const QQmlAdaptorModel &, int idx)
+bool QQmlDMCachedModelData::resolveIndex(const QQmlAdaptorModel &adaptorModel, int idx)
{
if (index == -1) {
Q_ASSERT(idx >= 0);
- index = idx;
cachedData.clear();
- emit modelIndexChanged();
+ setModelIndex(idx, adaptorModel.rowAt(idx), adaptorModel.columnAt(idx));
const QMetaObject *meta = metaObject();
const int propertyCount = type->propertyRoles.count();
for (int i = 0; i < propertyCount; ++i)
@@ -400,12 +398,13 @@ class QQmlDMAbstractItemModelData : public QQmlDMCachedModelData
{
Q_OBJECT
Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
+
public:
QQmlDMAbstractItemModelData(
QQmlDelegateModelItemMetaType *metaType,
VDMModelDelegateDataType *dataType,
- int index)
- : QQmlDMCachedModelData(metaType, dataType, index)
+ int index, int row, int column)
+ : QQmlDMCachedModelData(metaType, dataType, index, row, column)
{
}
@@ -413,7 +412,7 @@ public:
{
if (index >= 0 && *type->model) {
const QAbstractItemModel * const model = type->model->aim();
- return model->hasChildren(model->index(index, 0, type->model->rootIndex));
+ return model->hasChildren(model->index(row, column, type->model->rootIndex));
} else {
return false;
}
@@ -421,13 +420,13 @@ public:
QVariant value(int role) const override
{
- return type->model->aim()->index(index, 0, type->model->rootIndex).data(role);
+ return type->model->aim()->index(row, column, type->model->rootIndex).data(role);
}
void setValue(int role, const QVariant &value) override
{
type->model->aim()->setData(
- type->model->aim()->index(index, 0, type->model->rootIndex), value, role);
+ type->model->aim()->index(row, column, type->model->rootIndex), value, role);
}
QV4::ReturnedValue get() override
@@ -438,8 +437,8 @@ public:
}
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
- o->setPrototype(proto);
+ QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
+ o->setPrototypeOf(proto);
++scriptRef;
return o.asReturnedValue();
}
@@ -453,31 +452,18 @@ public:
{
}
- int count(const QQmlAdaptorModel &model) const override
+ int rowCount(const QQmlAdaptorModel &model) const override
{
return model.aim()->rowCount(model.rootIndex);
}
- void cleanup(QQmlAdaptorModel &model, QQmlDelegateModel *vdm) const override
- {
- QAbstractItemModel * const aim = model.aim();
- if (aim && vdm) {
- QObject::disconnect(aim, SIGNAL(rowsInserted(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- vdm, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(aim, SIGNAL(modelReset()),
- vdm, SLOT(_q_modelReset()));
- QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- vdm, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- }
+ int columnCount(const QQmlAdaptorModel &model) const override
+ {
+ return model.aim()->columnCount(model.rootIndex);
+ }
+ void cleanup(QQmlAdaptorModel &) const override
+ {
const_cast<VDMAbstractItemModelDataType *>(this)->release();
}
@@ -485,9 +471,9 @@ public:
{
QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
if (it != roleNames.end()) {
- return model.aim()->index(index, 0, model.rootIndex).data(*it);
+ return model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex).data(*it);
} else if (role == QLatin1String("hasModelChildren")) {
- return QVariant(model.aim()->hasChildren(model.aim()->index(index, 0, model.rootIndex)));
+ return QVariant(model.aim()->hasChildren(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex)));
} else {
return QVariant();
}
@@ -503,7 +489,7 @@ public:
QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
{
return model
- ? QVariant::fromValue(model.aim()->index(index, 0, model.rootIndex))
+ ? QVariant::fromValue(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex))
: QVariant();
}
@@ -521,12 +507,12 @@ public:
QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
- int index) const override
+ int index, int row, int column) const override
{
VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
if (!metaObject)
dataType->initializeMetaType(model);
- return new QQmlDMAbstractItemModelData(metaType, dataType, index);
+ return new QQmlDMAbstractItemModelData(metaType, dataType, index, row, column);
}
void initializeMetaType(QQmlAdaptorModel &model)
@@ -567,8 +553,8 @@ class QQmlDMListAccessorData : public QQmlDelegateModelItem
Q_OBJECT
Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
public:
- QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType, int index, const QVariant &value)
- : QQmlDelegateModelItem(metaType, index)
+ QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType, int index, int row, int column, const QVariant &value)
+ : QQmlDelegateModelItem(metaType, index, row, column)
, cachedData(value)
{
}
@@ -613,9 +599,9 @@ public:
{
QQmlAdaptorModelEngineData *data = engineData(v4);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
QV4::ScopedObject p(scope, data->listItemProto.value());
- o->setPrototype(p);
+ o->setPrototypeOf(p);
++scriptRef;
return o.asReturnedValue();
}
@@ -653,11 +639,16 @@ class VDMListDelegateDataType : public QQmlAdaptorModel::Accessors
public:
inline VDMListDelegateDataType() {}
- int count(const QQmlAdaptorModel &model) const override
+ int rowCount(const QQmlAdaptorModel &model) const override
{
return model.list.count();
}
+ int columnCount(const QQmlAdaptorModel &) const override
+ {
+ return 1;
+ }
+
QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
{
return role == QLatin1String("modelData")
@@ -668,11 +659,11 @@ public:
QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
- int index) const override
+ int index, int row, int column) const override
{
return new QQmlDMListAccessorData(
metaType,
- index,
+ index, row, column,
index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
}
};
@@ -691,7 +682,7 @@ public:
QQmlDMObjectData(
QQmlDelegateModelItemMetaType *metaType,
VDMObjectDelegateDataType *dataType,
- int index,
+ int index, int row, int column,
QObject *object);
QObject *modelData() const { return object; }
@@ -737,11 +728,16 @@ public:
free(metaObject);
}
- int count(const QQmlAdaptorModel &model) const override
+ int rowCount(const QQmlAdaptorModel &model) const override
{
return model.list.count();
}
+ int columnCount(const QQmlAdaptorModel &) const override
+ {
+ return 1;
+ }
+
QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
{
if (QObject *object = model.list.at(index).value<QObject *>())
@@ -752,13 +748,13 @@ public:
QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
- int index) const override
+ int index, int row, int column) const override
{
VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
if (!metaObject)
dataType->initializeMetaType(model);
return index >= 0 && index < model.list.count()
- ? new QQmlDMObjectData(metaType, dataType, index, qvariant_cast<QObject *>(model.list.at(index)))
+ ? new QQmlDMObjectData(metaType, dataType, index, row, column, qvariant_cast<QObject *>(model.list.at(index)))
: nullptr;
}
@@ -769,7 +765,7 @@ public:
metaObject = builder.toMetaObject();
}
- void cleanup(QQmlAdaptorModel &, QQmlDelegateModel *) const override
+ void cleanup(QQmlAdaptorModel &) const override
{
const_cast<VDMObjectDelegateDataType *>(this)->release();
}
@@ -872,12 +868,11 @@ public:
VDMObjectDelegateDataType *m_type;
};
-QQmlDMObjectData::QQmlDMObjectData(
- QQmlDelegateModelItemMetaType *metaType,
+QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
VDMObjectDelegateDataType *dataType,
- int index,
+ int index, int row, int column,
QObject *object)
- : QQmlDelegateModelItem(metaType, index)
+ : QQmlDelegateModelItem(metaType, index, row, column)
, object(object)
{
new QQmlDMObjectDataMetaObject(this, dataType);
@@ -904,50 +899,34 @@ QQmlAdaptorModel::~QQmlAdaptorModel()
accessors->cleanup(*this);
}
-void QQmlAdaptorModel::setModel(const QVariant &variant, QQmlDelegateModel *vdm, QQmlEngine *engine)
+void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *parent, QQmlEngine *engine)
{
- accessors->cleanup(*this, vdm);
+ accessors->cleanup(*this);
list.setList(variant, engine);
if (QObject *object = qvariant_cast<QObject *>(list.list())) {
- setObject(object);
- if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(object)) {
+ setObject(object, parent);
+ if (qobject_cast<QAbstractItemModel *>(object))
accessors = new VDMAbstractItemModelDataType(this);
-
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
- vdm, QQmlDelegateModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- vdm, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- vdm, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- vdm, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- vdm, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()),
- vdm, QQmlDelegateModel, SLOT(_q_modelReset()));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- vdm, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- } else {
+ else
accessors = new VDMObjectDelegateDataType;
- }
} else if (list.type() == QQmlListAccessor::ListProperty) {
- setObject(static_cast<const QQmlListReference *>(variant.constData())->object());
+ setObject(static_cast<const QQmlListReference *>(variant.constData())->object(), parent);
accessors = new VDMObjectDelegateDataType;
} else if (list.type() != QQmlListAccessor::Invalid
&& list.type() != QQmlListAccessor::Instance) { // Null QObject
- setObject(nullptr);
+ setObject(nullptr, parent);
accessors = &qt_vdm_list_accessors;
} else {
- setObject(nullptr);
+ setObject(nullptr, parent);
accessors = &qt_vdm_null_accessors;
}
}
-void QQmlAdaptorModel::invalidateModel(QQmlDelegateModel *vdm)
+void QQmlAdaptorModel::invalidateModel()
{
- accessors->cleanup(*this, vdm);
+ accessors->cleanup(*this);
accessors = &qt_vdm_null_accessors;
// Don't clear the model object as we still need the guard to clear the list variant if the
// object is destroyed.
@@ -958,6 +937,38 @@ bool QQmlAdaptorModel::isValid() const
return accessors != &qt_vdm_null_accessors;
}
+int QQmlAdaptorModel::count() const
+{
+ return rowCount() * columnCount();
+}
+
+int QQmlAdaptorModel::rowCount() const
+{
+ return qMax(0, accessors->rowCount(*this));
+}
+
+int QQmlAdaptorModel::columnCount() const
+{
+ return qMax(isValid() ? 1 : 0, accessors->columnCount(*this));
+}
+
+int QQmlAdaptorModel::rowAt(int index) const
+{
+ int count = rowCount();
+ return count <= 0 ? -1 : index % count;
+}
+
+int QQmlAdaptorModel::columnAt(int index) const
+{
+ int count = rowCount();
+ return count <= 0 ? -1 : index / count;
+}
+
+int QQmlAdaptorModel::indexAt(int row, int column) const
+{
+ return row + (column * rowCount());
+}
+
void QQmlAdaptorModel::objectDestroyed(QObject *)
{
setModel(QVariant(), nullptr, nullptr);
diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h
index b152a886a5..b834704163 100644
--- a/src/qml/util/qqmladaptormodel_p.h
+++ b/src/qml/util/qqmladaptormodel_p.h
@@ -56,6 +56,7 @@
#include "private/qqmllistaccessor_p.h"
#include <private/qqmlguard_p.h>
+#include <private/qqmlnullablevalue_p.h>
QT_REQUIRE_CONFIG(qml_delegate_model);
@@ -67,7 +68,7 @@ class QQmlDelegateModel;
class QQmlDelegateModelItem;
class QQmlDelegateModelItemMetaType;
-class QQmlAdaptorModel : public QQmlGuard<QObject>
+class Q_QML_PRIVATE_EXPORT QQmlAdaptorModel : public QQmlStrongJSQObjectReference<QObject>
{
public:
class Accessors
@@ -75,8 +76,9 @@ public:
public:
inline Accessors() {}
virtual ~Accessors();
- virtual int count(const QQmlAdaptorModel &) const { return 0; }
- virtual void cleanup(QQmlAdaptorModel &, QQmlDelegateModel * = nullptr) const {}
+ virtual int rowCount(const QQmlAdaptorModel &) const { return 0; }
+ virtual int columnCount(const QQmlAdaptorModel &) const { return 0; }
+ virtual void cleanup(QQmlAdaptorModel &) const {}
virtual QVariant value(const QQmlAdaptorModel &, int, const QString &) const {
return QVariant(); }
@@ -84,7 +86,7 @@ public:
virtual QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &,
QQmlDelegateModelItemMetaType *,
- int) const { return nullptr; }
+ int, int, int) const { return nullptr; }
virtual bool notify(
const QQmlAdaptorModel &,
@@ -112,19 +114,25 @@ public:
~QQmlAdaptorModel();
inline QVariant model() const { return list.list(); }
- void setModel(const QVariant &variant, QQmlDelegateModel *vdm, QQmlEngine *engine);
- void invalidateModel(QQmlDelegateModel *vdm);
+ void setModel(const QVariant &variant, QObject *parent, QQmlEngine *engine);
+ void invalidateModel();
bool isValid() const;
-
+ int count() const;
+ int rowCount() const;
+ int columnCount() const;
+ int rowAt(int index) const;
+ int columnAt(int index) const;
+ int indexAt(int row, int column) const;
+
+ inline bool adaptsAim() const { return qobject_cast<QAbstractItemModel *>(object()); }
inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); }
inline const QAbstractItemModel *aim() const { return static_cast<const QAbstractItemModel *>(object()); }
- inline int count() const { return qMax(0, accessors->count(*this)); }
inline QVariant value(int index, const QString &role) const {
return accessors->value(*this, index, role); }
inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) {
- return accessors->createItem(*this, metaType, index); }
+ return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index)); }
inline bool hasProxyObject() const {
return list.type() == QQmlListAccessor::Instance || list.type() == QQmlListAccessor::ListProperty; }
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 578c05086f..3f78ca6b69 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -122,7 +122,7 @@ QVariant QQmlPropertyMapMetaObject::propertyWriteValue(int index, const QVariant
void QQmlPropertyMapMetaObject::propertyWritten(int index)
{
- priv->emitChanged(priv->propertyName(index), operator[](index));
+ priv->emitChanged(priv->propertyName(index), value(index));
}
void QQmlPropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b)
@@ -311,7 +311,7 @@ QVariant &QQmlPropertyMap::operator[](const QString &key)
if (!d->keys.contains(key))
insert(key, QVariant());//force creation -- needed below
- return (*(d->mo))[utf8key];
+ return d->mo->valueRef(utf8key);
}
/*!
diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro
index 2c1b71797d..0807482d23 100644
--- a/src/qmldebug/qmldebug.pro
+++ b/src/qmldebug/qmldebug.pro
@@ -9,6 +9,7 @@ SOURCES += \
qqmldebugconnection.cpp \
qqmldebugmessageclient.cpp \
qqmlenginecontrolclient.cpp \
+ qqmlpreviewclient.cpp \
qqmlprofilerclient.cpp \
qqmlprofilerevent.cpp \
qqmlprofilereventlocation.cpp \
@@ -22,6 +23,8 @@ HEADERS += \
qqmldebugmessageclient_p.h \
qqmlenginecontrolclient_p.h \
qqmlenginecontrolclient_p_p.h \
+ qqmlpreviewclient_p.h \
+ qqmlpreviewclient_p_p.h \
qqmlprofilerclient_p.h \
qqmlprofilerclient_p_p.h \
qqmlprofilerevent_p.h \
diff --git a/src/qmldebug/qqmldebugclient.cpp b/src/qmldebug/qqmldebugclient.cpp
index d412b7b267..03123cc6e0 100644
--- a/src/qmldebug/qqmldebugclient.cpp
+++ b/src/qmldebug/qqmldebugclient.cpp
@@ -117,11 +117,6 @@ QQmlDebugConnection *QQmlDebugClient::connection() const
return d->connection;
}
-void QQmlDebugClient::stateChanged(QQmlDebugClient::State state)
-{
- Q_UNUSED(state);
-}
-
void QQmlDebugClient::messageReceived(const QByteArray &message)
{
Q_UNUSED(message);
diff --git a/src/qmldebug/qqmldebugclient_p.h b/src/qmldebug/qqmldebugclient_p.h
index 723de5ee43..469b65d4a9 100644
--- a/src/qmldebug/qqmldebugclient_p.h
+++ b/src/qmldebug/qqmldebugclient_p.h
@@ -76,13 +76,14 @@ public:
QQmlDebugConnection *connection() const;
+signals:
+ void stateChanged(State state);
+
protected:
QQmlDebugClient(QQmlDebugClientPrivate &dd);
private:
friend class QQmlDebugConnection;
-
- virtual void stateChanged(State state);
virtual void messageReceived(const QByteArray &message);
};
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
index 67bad8d812..4e087ee6db 100644
--- a/src/qmldebug/qqmldebugconnection.cpp
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -259,7 +259,7 @@ QQmlDebugConnection::~QQmlDebugConnection()
Q_D(QQmlDebugConnection);
QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter)
- iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+ emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
}
int QQmlDebugConnection::currentDataStreamVersion() const
@@ -295,7 +295,7 @@ void QQmlDebugConnection::close()
QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter)
- iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+ emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
}
if (d->device) {
diff --git a/src/qmldebug/qqmldebugmessageclient.cpp b/src/qmldebug/qqmldebugmessageclient.cpp
index a03c1f8af2..0892404194 100644
--- a/src/qmldebug/qqmldebugmessageclient.cpp
+++ b/src/qmldebug/qqmldebugmessageclient.cpp
@@ -58,11 +58,6 @@ QQmlDebugMessageClient::QQmlDebugMessageClient(QQmlDebugConnection *client)
{
}
-void QQmlDebugMessageClient::stateChanged(State state)
-{
- emit newState(state);
-}
-
void QQmlDebugMessageClient::messageReceived(const QByteArray &data)
{
QDataStream ds(data);
diff --git a/src/qmldebug/qqmldebugmessageclient_p.h b/src/qmldebug/qqmldebugmessageclient_p.h
index 75c70044e4..a2a7f28f81 100644
--- a/src/qmldebug/qqmldebugmessageclient_p.h
+++ b/src/qmldebug/qqmldebugmessageclient_p.h
@@ -71,15 +71,10 @@ class QQmlDebugMessageClient : public QQmlDebugClient
public:
explicit QQmlDebugMessageClient(QQmlDebugConnection *client);
- virtual void stateChanged(State state) override;
virtual void messageReceived(const QByteArray &) override;
signals:
- void newState(QQmlDebugClient::State);
void message(QtMsgType, const QString &, const QQmlDebugContextInfo &);
-
-private:
- Q_DISABLE_COPY(QQmlDebugMessageClient)
};
QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlenginecontrolclient.cpp b/src/qmldebug/qqmlenginecontrolclient.cpp
index 45d672d4bc..cdc724ef2f 100644
--- a/src/qmldebug/qqmlenginecontrolclient.cpp
+++ b/src/qmldebug/qqmlenginecontrolclient.cpp
@@ -98,8 +98,8 @@ void QQmlEngineControlClient::messageReceived(const QByteArray &data)
{
Q_D(QQmlEngineControlClient);
QPacket stream(d->connection->currentDataStreamVersion(), data);
- int message;
- int id;
+ qint32 message;
+ qint32 id;
QString name;
stream >> message >> id;
@@ -150,7 +150,7 @@ void QQmlEngineControlClientPrivate::sendCommand(
{
Q_Q(QQmlEngineControlClient);
QPacket stream(connection->currentDataStreamVersion());
- stream << int(command) << engineId;
+ stream << static_cast<qint32>(command) << engineId;
q->sendMessage(stream.data());
}
diff --git a/src/qmldebug/qqmlpreviewclient.cpp b/src/qmldebug/qqmlpreviewclient.cpp
new file mode 100644
index 0000000000..fa040e226b
--- /dev/null
+++ b/src/qmldebug/qqmlpreviewclient.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qqmlpreviewclient_p_p.h"
+#include <private/qpacket_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdir.h>
+#include <QtQml/qqmlfile.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlPreviewClient::QQmlPreviewClient(QQmlDebugConnection *connection)
+ : QQmlDebugClient(*(new QQmlPreviewClientPrivate(connection)))
+{
+}
+
+void QQmlPreviewClient::messageReceived(const QByteArray &message)
+{
+ QPacket packet(connection()->currentDataStreamVersion(), message);
+
+ qint8 command;
+ packet >> command;
+
+ if (command == Error) {
+ QString seviceError;
+ packet >> seviceError;
+ emit error(seviceError);
+ return;
+ }
+
+ Q_ASSERT(command == Request);
+
+ QString fileName;
+ packet >> fileName;
+ emit request(fileName);
+}
+
+void QQmlPreviewClient::sendDirectory(const QString &path, const QStringList &entries)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Directory) << path << entries;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::sendFile(const QString &path, const QByteArray &contents)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(File) << path << contents;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::sendError(const QString &path)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Error) << path;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerLoad(const QUrl &url)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Load) << url;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerRerun()
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Rerun);
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerZoom(float factor)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Zoom) << factor;
+ sendMessage(packet.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlpreviewclient_p.h b/src/qmldebug/qqmlpreviewclient_p.h
new file mode 100644
index 0000000000..49d147c866
--- /dev/null
+++ b/src/qmldebug/qqmlpreviewclient_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QQMLPREVIEWCLIENT_P_H
+#define QQMLPREVIEWCLIENT_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/qqmldebugclient_p.h>
+#include <private/qqmldebugconnection_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewClientPrivate;
+class QQmlPreviewClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlPreviewClient)
+public:
+ enum Command {
+ File,
+ Load,
+ Request,
+ Error,
+ Rerun,
+ Directory,
+ ClearCache,
+ Zoom
+ };
+
+ QQmlPreviewClient(QQmlDebugConnection *parent);
+ void messageReceived(const QByteArray &message) override;
+
+ void sendDirectory(const QString &path, const QStringList &entries);
+ void sendFile(const QString &path, const QByteArray &contents);
+ void sendError(const QString &path);
+
+ void triggerLoad(const QUrl &url);
+ void triggerRerun();
+ void triggerZoom(float factor);
+
+signals:
+ void request(const QString &path);
+ void error(const QString &message);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWCLIENT_P_H
diff --git a/src/qmldebug/qqmlpreviewclient_p_p.h b/src/qmldebug/qqmlpreviewclient_p_p.h
new file mode 100644
index 0000000000..8fb2b4b18c
--- /dev/null
+++ b/src/qmldebug/qqmlpreviewclient_p_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPREVIEWCLIENT_P_P_H
+#define QQMLPREVIEWCLIENT_P_P_H
+
+#include "qqmlpreviewclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlPreviewClient)
+public:
+ QQmlPreviewClientPrivate(QQmlDebugConnection *connection)
+ : QQmlDebugClientPrivate(QLatin1String("QmlPreview"), connection)
+ {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWCLIENT_P_P_H
diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp
index 661b43f164..73db2ad94d 100644
--- a/src/qmldebug/qqmlprofilerclient.cpp
+++ b/src/qmldebug/qqmlprofilerclient.cpp
@@ -42,6 +42,10 @@
QT_BEGIN_NAMESPACE
+QQmlProfilerClientPrivate::~QQmlProfilerClientPrivate()
+{
+}
+
int QQmlProfilerClientPrivate::resolveType(const QQmlProfilerTypedEvent &event)
{
int typeIndex = -1;
@@ -165,6 +169,7 @@ QQmlProfilerClient::QQmlProfilerClient(QQmlDebugConnection *connection,
{
Q_D(QQmlProfilerClient);
setRequestedFeatures(features);
+ connect(this, &QQmlDebugClient::stateChanged, this, &QQmlProfilerClient::onStateChanged);
connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeAdded,
this, &QQmlProfilerClient::sendRecordingStatus);
connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeRemoved,
@@ -314,7 +319,7 @@ bool QQmlProfilerClientPrivate::updateFeatures(ProfileFeature feature)
return true;
}
-void QQmlProfilerClient::stateChanged(State status)
+void QQmlProfilerClient::onStateChanged(State status)
{
if (status == Enabled) {
sendRecordingStatus(-1);
diff --git a/src/qmldebug/qqmlprofilerclient_p.h b/src/qmldebug/qqmlprofilerclient_p.h
index 7b8e286f5b..89c117a8b5 100644
--- a/src/qmldebug/qqmlprofilerclient_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p.h
@@ -76,7 +76,6 @@ public:
void setRecording(bool);
quint64 recordedFeatures() const;
virtual void messageReceived(const QByteArray &) override;
- virtual void stateChanged(State status) override;
void clearEvents();
void clearAll();
@@ -87,6 +86,7 @@ public:
protected:
QQmlProfilerClient(QQmlProfilerClientPrivate &dd);
+ void onStateChanged(State status);
signals:
void complete(qint64 maximumTime);
diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h
index 994c08cafc..df73209858 100644
--- a/src/qmldebug/qqmlprofilerclient_p_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p_p.h
@@ -79,7 +79,7 @@ public:
{
}
- virtual ~QQmlProfilerClientPrivate() override {}
+ virtual ~QQmlProfilerClientPrivate() override;
void sendRecordingStatus(int engineId);
bool updateFeatures(ProfileFeature feature);
@@ -112,4 +112,3 @@ public:
QT_END_NAMESPACE
#endif // QQMLPROFILERCLIENT_P_P_H
-
diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc
index 1f84db405c..f641d8248f 100644
--- a/src/qmltest/doc/src/qtquicktest-index.qdoc
+++ b/src/qmltest/doc/src/qtquicktest-index.qdoc
@@ -146,6 +146,11 @@
\li Name
\li Purpose
\row
+ \row
+ \li void applicationAvailable()
+ \li Called right after the QApplication object was instantiated.
+ Use this function to setup everything that is not related
+ to QML directly.
\li void qmlEngineAvailable(QQmlEngine*)
\li Called when the QML engine is available.
Any \l {QQmlEngine::addImportPath}{import paths},
diff --git a/src/qmltest/qtestoptions_p.h b/src/qmltest/qtestoptions_p.h
index 68fe09f793..7be5c88590 100644
--- a/src/qmltest/qtestoptions_p.h
+++ b/src/qmltest/qtestoptions_p.h
@@ -51,7 +51,11 @@
// We mean it.
//
-#include <QtTest/qttestglobal.h>
+#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
+# include <QtTest/qtest_global.h>
+#else
+# include <QtTest/qttestglobal.h>
+#endif
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 8b9ff4c5cd..53d223678c 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -215,8 +215,8 @@ public:
m_errors += component.errors();
if (component.isReady()) {
- CompilationUnit *rootCompilationUnit = QQmlComponentPrivate::get(&component)->compilationUnit;
- TestCaseEnumerationResult result = enumerateTestCases(rootCompilationUnit);
+ QQmlRefPointer<CompilationUnit> rootCompilationUnit = QQmlComponentPrivate::get(&component)->compilationUnit;
+ TestCaseEnumerationResult result = enumerateTestCases(rootCompilationUnit.data());
m_testCases = result.testCases + result.finalizedPartialTestCases();
m_errors += result.errors;
}
@@ -278,7 +278,7 @@ private:
if (!object) // Start at root of compilation unit if not enumerating a specific child
object = compilationUnit->objectAt(0);
- if (CompilationUnit *superTypeUnit = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)->compilationUnit) {
+ if (CompilationUnit *superTypeUnit = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)->compilationUnit.data()) {
// We have a non-C++ super type, which could indicate we're a subtype of a TestCase
if (testCaseType.isValid() && superTypeUnit->url() == testCaseType.sourceUrl())
result.isTestCase = true;
@@ -359,6 +359,11 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
}
}
+ if (setup) {
+ // Don't check the return value; it's OK if it doesn't exist.
+ QMetaObject::invokeMethod(setup, "applicationAvailable");
+ }
+
// Look for QML-specific command-line options.
// -import dir Specify an import directory.
// -plugins dir Specify a directory where to search for plugins.
@@ -476,6 +481,9 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
// Register the test object
qmlRegisterSingletonType<QTestRootObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject);
+ QSet<QString> commandLineTestFunctions = QTest::testFunctions.toSet();
+ const bool filteringTestFunctions = !commandLineTestFunctions.isEmpty();
+
// Scan through all of the "tst_*.qml" files and run each of them
// in turn with a separate QQuickView (for test isolation).
for (const QString &file : qAsConst(files)) {
@@ -508,10 +516,10 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
continue;
}
- static const QSet<QString> commandLineTestFunctions = QTest::testFunctions.toSet();
- if (!commandLineTestFunctions.isEmpty() &&
- !availableTestFunctions.toSet().intersects(commandLineTestFunctions))
+ const QSet<QString> availableTestSet = availableTestFunctions.toSet();
+ if (filteringTestFunctions && !availableTestSet.intersects(commandLineTestFunctions))
continue;
+ commandLineTestFunctions.subtract(availableTestSet);
QQuickView view(&engine, nullptr);
view.setFlags(Qt::Window | Qt::WindowSystemMenuHint
@@ -584,6 +592,14 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
QuickTestResult::setProgramName(nullptr);
delete app;
+ // Check that all test functions passed on the command line were found
+ if (!commandLineTestFunctions.isEmpty()) {
+ qWarning() << "Could not find the following test functions:";
+ for (const QString &functionName : qAsConst(commandLineTestFunctions))
+ qWarning(" %s()", qUtf8Printable(functionName));
+ return commandLineTestFunctions.count();
+ }
+
// Return the number of failures as the exit code.
return QuickTestResult::exitCode();
}
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index c4a3280cf6..3b854dfccd 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -61,6 +61,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/QUrl>
#include <QtCore/QDir>
+#include <QtCore/qregularexpression.h>
#include <QtQuick/qquickwindow.h>
#include <QtGui/qvector3d.h>
#include <QtGui/qimagewriter.h>
@@ -625,9 +626,18 @@ void QuickTestResult::warn(const QString &message, const QUrl &location, int lin
QTestLog::warn(message.toLatin1().constData(), qtestFixUrl(location).toLatin1().constData(), line);
}
-void QuickTestResult::ignoreWarning(const QString &message)
+void QuickTestResult::ignoreWarning(const QJSValue &message)
{
- QTestLog::ignoreMessage(QtWarningMsg, message.toLatin1().constData());
+ if (message.isRegExp()) {
+ // ### we should probably handle QRegularExpression conversion engine-side
+ QRegExp re = message.toVariant().toRegExp();
+ QRegularExpression::PatternOptions opts = re.caseSensitivity() ==
+ Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption;
+ QRegularExpression re2(re.pattern(), opts);
+ QTestLog::ignoreMessage(QtWarningMsg, re2);
+ } else {
+ QTestLog::ignoreMessage(QtWarningMsg, message.toString().toLatin1());
+ }
}
void QuickTestResult::wait(int ms)
diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h
index 6e7b72830e..f222cd3e87 100644
--- a/src/qmltest/quicktestresult_p.h
+++ b/src/qmltest/quicktestresult_p.h
@@ -137,7 +137,7 @@ public Q_SLOTS:
const QUrl &location, int line);
void warn(const QString &message, const QUrl &location, int line);
- void ignoreWarning(const QString &message);
+ void ignoreWarning(const QJSValue &message);
void wait(int ms);
void sleep(int ms);
diff --git a/src/quick/configure.json b/src/quick/configure.json
index ea1d49baad..ab356be557 100644
--- a/src/quick/configure.json
+++ b/src/quick/configure.json
@@ -15,6 +15,7 @@
"quick-flipable": "boolean",
"quick-gridview": "boolean",
"quick-listview": "boolean",
+ "quick-tableview": "boolean",
"quick-path": "boolean",
"quick-pathview": "boolean",
"quick-positioners": "boolean",
@@ -86,7 +87,7 @@
},
"quick-itemview": {
"label": "ItemView item",
- "condition": "features.quick-gridview || features.quick-listview",
+ "condition": "features.quick-gridview || features.quick-listview || features.quick-tableview",
"output": [
"privateFeature"
]
@@ -107,6 +108,14 @@
"privateFeature"
]
},
+ "quick-tableview": {
+ "label": "TableView item",
+ "purpose": "Provides the TableView item.",
+ "section": "Qt Quick",
+ "output": [
+ "privateFeature"
+ ]
+ },
"quick-particles": {
"label": "Particle support",
"purpose": "Provides a particle system.",
@@ -183,6 +192,7 @@
"quick-flipable",
"quick-gridview",
"quick-listview",
+ "quick-tableview",
"quick-path",
"quick-pathview",
"quick-positioners",
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
index 09493c30d6..2efcdada8b 100644
--- a/src/quick/designer/qqmldesignermetaobject.cpp
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -83,7 +83,7 @@ static QQmlPropertyCache *cacheForObject(QObject *object, QQmlEngine *engine)
{
QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object);
if (metaObject)
- return metaObject->cache;
+ return metaObject->cache.data();
return QQmlEnginePrivate::get(engine)->cache(object);
}
@@ -139,7 +139,7 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi
cache->setParent(ddata->propertyCache);
cache->invalidate(engine, this);
ddata->propertyCache->release();
- ddata->propertyCache = cache;
+ ddata->propertyCache = cache.data();
ddata->propertyCache->addref();
}
diff --git a/src/quick/doc/images/qml-item-canvas-lineDash.png b/src/quick/doc/images/qml-item-canvas-lineDash.png
new file mode 100644
index 0000000000..a2a038abe0
--- /dev/null
+++ b/src/quick/doc/images/qml-item-canvas-lineDash.png
Binary files differ
diff --git a/src/quick/doc/snippets/qml/pathview/pathview.qml b/src/quick/doc/snippets/qml/pathview/pathview.qml
index 1a31f1372b..58d19b1a0c 100644
--- a/src/quick/doc/snippets/qml/pathview/pathview.qml
+++ b/src/quick/doc/snippets/qml/pathview/pathview.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -59,6 +59,7 @@ Rectangle {
id: delegate
Column {
id: wrapper
+ opacity: PathView.isCurrentItem ? 1 : 0.5
Image {
anchors.horizontalCenter: nameText.horizontalCenter
width: 64; height: 64
@@ -68,7 +69,6 @@ Rectangle {
id: nameText
text: name
font.pointSize: 16
- color: wrapper.PathView.isCurrentItem ? "red" : "black"
}
}
}
diff --git a/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml b/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml
index 031bee960d..e52a0ce0ef 100644
--- a/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml
+++ b/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml
@@ -80,5 +80,17 @@ Rectangle {
}
}
//! [rectangles]
+
+//! [presets]
+Rectangle {
+ y: 0; width: 80; height: 80
+ gradient: Gradient.NightFade
+}
+
+Rectangle {
+ y: 0; width: 80; height: 80
+ gradient: "NightFade"
+}
+//! [presets]
}
}
diff --git a/src/quick/handlers/handlers.pri b/src/quick/handlers/handlers.pri
index 8bd74d95da..111a526ce2 100644
--- a/src/quick/handlers/handlers.pri
+++ b/src/quick/handlers/handlers.pri
@@ -1,17 +1,24 @@
HEADERS += \
$$PWD/qquickdraghandler_p.h \
+ $$PWD/qquickhandlerpoint_p.h \
$$PWD/qquickhandlersmodule_p.h \
+ $$PWD/qquickhoverhandler_p.h \
$$PWD/qquickmultipointhandler_p.h \
$$PWD/qquickpinchhandler_p.h \
$$PWD/qquickpointerdevicehandler_p.h \
+ $$PWD/qquickpointerdevicehandler_p_p.h \
$$PWD/qquickpointerhandler_p.h \
+ $$PWD/qquickpointerhandler_p_p.h \
$$PWD/qquickpointhandler_p.h \
$$PWD/qquicksinglepointhandler_p.h \
$$PWD/qquicktaphandler_p.h \
+ $$PWD/qquickdragaxis_p.h
SOURCES += \
$$PWD/qquickdraghandler.cpp \
+ $$PWD/qquickhandlerpoint.cpp \
$$PWD/qquickhandlersmodule.cpp \
+ $$PWD/qquickhoverhandler.cpp \
$$PWD/qquickmultipointhandler.cpp \
$$PWD/qquickpinchhandler.cpp \
$$PWD/qquickpointerdevicehandler.cpp \
@@ -19,4 +26,4 @@ SOURCES += \
$$PWD/qquickpointhandler.cpp \
$$PWD/qquicksinglepointhandler.cpp \
$$PWD/qquicktaphandler.cpp \
-
+ $$PWD/qquickdragaxis.cpp
diff --git a/src/quick/handlers/qquickdragaxis.cpp b/src/quick/handlers/qquickdragaxis.cpp
new file mode 100644
index 0000000000..5efe19b2fe
--- /dev/null
+++ b/src/quick/handlers/qquickdragaxis.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qquickdragaxis_p.h"
+#include <limits>
+
+QQuickDragAxis::QQuickDragAxis()
+ : m_minimum(-std::numeric_limits<qreal>::max())
+ , m_maximum(std::numeric_limits<qreal>::max())
+ , m_enabled(true)
+{
+}
+
+void QQuickDragAxis::setMinimum(qreal minimum)
+{
+ if (m_minimum == minimum)
+ return;
+
+ m_minimum = minimum;
+ emit minimumChanged();
+}
+
+void QQuickDragAxis::setMaximum(qreal maximum)
+{
+ if (m_maximum == maximum)
+ return;
+
+ m_maximum = maximum;
+ emit maximumChanged();
+}
+
+void QQuickDragAxis::setEnabled(bool enabled)
+{
+ if (m_enabled == enabled)
+ return;
+
+ m_enabled = enabled;
+ emit enabledChanged();
+}
+
diff --git a/src/quick/handlers/qquickdragaxis_p.h b/src/quick/handlers/qquickdragaxis_p.h
new file mode 100644
index 0000000000..2c2e0a426d
--- /dev/null
+++ b/src/quick/handlers/qquickdragaxis_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKDRAGAXIS_P_H
+#define QQUICKDRAGAXIS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qglobal.h>
+
+class Q_AUTOTEST_EXPORT QQuickDragAxis : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal minimum READ minimum WRITE setMinimum NOTIFY minimumChanged)
+ Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+
+public:
+ QQuickDragAxis();
+
+ qreal minimum() const { return m_minimum; }
+ void setMinimum(qreal minimum);
+
+ qreal maximum() const { return m_maximum; }
+ void setMaximum(qreal maximum);
+
+ bool enabled() const { return m_enabled; }
+ void setEnabled(bool enabled);
+
+signals:
+ void minimumChanged();
+ void maximumChanged();
+ void enabledChanged();
+
+private:
+ qreal m_minimum;
+ qreal m_maximum;
+ bool m_enabled;
+};
+
+#endif // QQUICKDRAGAXIS_P_H
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 5e540b3615..8bb8612fb3 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
\brief Handler for dragging.
DragHandler is a handler that is used to interactively move an Item.
- Like other Pointer Handlers, by default it is fully functional, and
+ Like other Input Handlers, by default it is fully functional, and
manipulates its \l {PointerHandler::target} {target}.
\snippet pointerHandlers/dragHandler.qml 0
@@ -243,39 +243,6 @@ void QQuickDragHandler::setTranslation(const QVector2D &trans)
applied to the \l {PointerHandler::target} {target}.
If \c enabled is true, vertical dragging is allowed.
*/
-QQuickDragAxis::QQuickDragAxis()
- : m_minimum(-DBL_MAX)
- , m_maximum(DBL_MAX)
- , m_enabled(true)
-{
-}
-
-void QQuickDragAxis::setMinimum(qreal minimum)
-{
- if (m_minimum == minimum)
- return;
-
- m_minimum = minimum;
- emit minimumChanged();
-}
-
-void QQuickDragAxis::setMaximum(qreal maximum)
-{
- if (m_maximum == maximum)
- return;
-
- m_maximum = maximum;
- emit maximumChanged();
-}
-
-void QQuickDragAxis::setEnabled(bool enabled)
-{
- if (m_enabled == enabled)
- return;
-
- m_enabled = enabled;
- emit enabledChanged();
-}
/*!
\readonly
diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h
index 363df31a64..7ba1021924 100644
--- a/src/quick/handlers/qquickdraghandler_p.h
+++ b/src/quick/handlers/qquickdraghandler_p.h
@@ -52,39 +52,10 @@
//
#include "qquicksinglepointhandler_p.h"
+#include "qquickdragaxis_p.h"
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QQuickDragAxis : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(qreal minimum READ minimum WRITE setMinimum NOTIFY minimumChanged)
- Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
-
-public:
- QQuickDragAxis();
-
- qreal minimum() const { return m_minimum; }
- void setMinimum(qreal minimum);
-
- qreal maximum() const { return m_maximum; }
- void setMaximum(qreal maximum);
-
- bool enabled() const { return m_enabled; }
- void setEnabled(bool enabled);
-
-signals:
- void minimumChanged();
- void maximumChanged();
- void enabledChanged();
-
-private:
- qreal m_minimum;
- qreal m_maximum;
- bool m_enabled;
-};
-
class Q_AUTOTEST_EXPORT QQuickDragHandler : public QQuickSinglePointHandler
{
Q_OBJECT
diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp
new file mode 100644
index 0000000000..4bd5d2cbfb
--- /dev/null
+++ b/src/quick/handlers/qquickhandlerpoint.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickhandlerpoint_p.h"
+#include "private/qquickevents_p_p.h"
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH_TARGET)
+
+/*!
+ \qmltype HandlerPoint
+ \instantiates QQuickHandlerPoint
+ \inqmlmodule Qt.labs.handlers
+ \ingroup qtquick-handlers
+ \brief An event point.
+
+ A QML representation of a QQuickEventPoint.
+
+ It's possible to make bindings to properties of a \l SinglePointHandler's
+ current point. For example:
+
+ \snippet pointerHandlers/dragHandlerNullTarget.qml 0
+
+ The point is kept up-to-date when the DragHandler is actively responding to
+ an EventPoint; but when the point is released, or the current point is
+ being handled by a different handler, \c position.x and \c position.y are 0.
+
+ \note This is practically identical to QtQuick::EventPoint; however an
+ EventPoint is a long-lived QObject which is invalidated between gestures
+ and reused for subsequent event deliveries. Continuous bindings to its
+ properties are not possible, and an individual handler cannot rely on it
+ outside the period when that point is part of an active gesture which that
+ handler is handling. HandlerPoint is a Q_GADGET that the handler owns.
+ This allows you to make lifetime bindings to its properties.
+
+ \sa SinglePointHandler::point
+*/
+
+QQuickHandlerPoint::QQuickHandlerPoint()
+ : m_id(0)
+ , m_rotation(0)
+ , m_pressure(0)
+{}
+
+void QQuickHandlerPoint::reset()
+{
+ m_id = 0;
+ m_uniqueId = QPointingDeviceUniqueId();
+ m_position = QPointF();
+ m_scenePosition = QPointF();
+ m_pressPosition = QPointF();
+ m_scenePressPosition = QPointF();
+ m_sceneGrabPosition = QPointF();
+ m_velocity = QVector2D();
+ m_rotation = 0;
+ m_pressure = 0;
+ m_ellipseDiameters = QSizeF();
+ m_pressedButtons = Qt::NoButton;
+ m_pressedModifiers = Qt::NoModifier;
+}
+
+void QQuickHandlerPoint::reset(const QQuickEventPoint *point)
+{
+ m_id = point->pointId();
+ const QQuickPointerEvent *event = point->pointerEvent();
+ switch (point->state()) {
+ case QQuickEventPoint::Pressed:
+ m_pressPosition = point->position();
+ m_scenePressPosition = point->scenePosition();
+ m_pressedButtons = event->buttons();
+ break;
+ case QQuickEventPoint::Released:
+ reset();
+ return;
+ default:
+ m_pressedButtons = event->buttons();
+ break;
+ }
+ m_pressedModifiers = event->modifiers();
+ if (event->asPointerTouchEvent()) {
+ const QQuickEventTouchPoint *tp = static_cast<const QQuickEventTouchPoint *>(point);
+ m_uniqueId = tp->uniqueId();
+ m_rotation = tp->rotation();
+ m_pressure = tp->pressure();
+ m_ellipseDiameters = tp->ellipseDiameters();
+ } else if (event->asPointerTabletEvent()) {
+ // TODO
+ } else {
+ m_uniqueId = event->device()->uniqueId();
+ m_rotation = 0;
+ m_pressure = event->buttons() ? 1 : 0;
+ m_ellipseDiameters = QSizeF();
+ }
+ m_position = point->position();
+ m_scenePosition = point->scenePosition();
+ if (point->state() == QQuickEventPoint::Updated)
+ m_velocity = point->velocity();
+}
+
+void QQuickHandlerPoint::reset(const QVector<QQuickEventPoint *> &points)
+{
+ if (points.isEmpty()) {
+ qWarning("reset: no points");
+ return;
+ }
+ if (points.count() == 1) {
+ reset(points.first());
+ return;
+ }
+ // all points are required to be from the same event
+ const QQuickPointerEvent *event = points.first()->pointerEvent();
+ QPointF posSum;
+ QPointF scenePosSum;
+ QVector2D velocitySum;
+ qreal pressureSum = 0;
+ QSizeF ellipseDiameterSum;
+ bool press = false;
+ const QQuickPointerTouchEvent *touchEvent = event->asPointerTouchEvent();
+ for (const QQuickEventPoint *point : qAsConst(points)) {
+ posSum += point->position();
+ scenePosSum += point->scenePosition();
+ velocitySum += point->velocity();
+ if (touchEvent) {
+ pressureSum += static_cast<const QQuickEventTouchPoint *>(point)->pressure();
+ ellipseDiameterSum += static_cast<const QQuickEventTouchPoint *>(point)->ellipseDiameters();
+ }
+ if (point->state() == QQuickEventPoint::Pressed)
+ press = true;
+ }
+ m_id = 0;
+ m_uniqueId = QPointingDeviceUniqueId();
+ m_pressedButtons = event->buttons();
+ m_pressedModifiers = event->modifiers();
+ m_position = posSum / points.size();
+ m_scenePosition = scenePosSum / points.size();
+ if (press) {
+ m_pressPosition = m_position;
+ m_scenePressPosition = m_scenePosition;
+ }
+ m_velocity = velocitySum / points.size();
+ m_rotation = 0; // averaging the rotations of all the points isn't very sensible
+ m_pressure = pressureSum / points.size();
+ m_ellipseDiameters = ellipseDiameterSum / points.size();
+}
+
+/*!
+ \readonly
+ \qmlproperty int QtQuick::HandlerPoint::id
+ \brief The ID number of the point
+
+ During a touch gesture, from the time that the first finger is pressed
+ until the last finger is released, each touchpoint will have a unique ID
+ number. Likewise, if input from multiple devices occurs (for example
+ simultaneous mouse and touch presses), all the current event points from
+ all the devices will have unique IDs.
+
+ \note Do not assume that id numbers start at zero or that they are
+ sequential. Such an assumption is often false due to the way the underlying
+ drivers work.
+
+ \sa QTouchEvent::TouchPoint::id
+*/
+
+/*!
+ \readonly
+ \qmlproperty PointingDeviceUniqueId QtQuick::HandlerPoint::uniqueId
+ \brief The unique ID of the point, if any
+
+ This is normally empty, because touchscreens cannot uniquely identify fingers.
+
+ On some types of touchscreens, especially those using TUIO drivers,
+ it's possible to use recognizable physical tokens (fiducial objects)
+ in addition to fingers. So if this point is a touch point, and
+ uniqueId is set, it is the identifier for such an object.
+
+ On a graphics tablet, each type of stylus or other tool often has a unique
+ ID or serial number, which can be useful to respond in different ways to
+ different tools.
+
+ Interpreting the contents of this ID requires knowledge of the hardware and
+ drivers in use.
+
+ \sa QTabletEvent::uniqueId, QtQuick::TouchPoint::uniqueId, QtQuick::EventTouchPoint::uniqueId
+*/
+
+/*!
+ \readonly
+ \qmlproperty QPointF QtQuick::HandlerPoint::position
+ \brief The position within the \c parent Item
+
+ This is the position of the event point relative to the bounds of
+ the \l {PointerHandler::parent} {parent}.
+*/
+
+/*!
+ \readonly
+ \qmlproperty QPointF QtQuick::HandlerPoint::scenePosition
+ \brief The position within the scene
+
+ This is the position of the event point relative to the bounds of the Qt
+ Quick scene (typically the whole window).
+*/
+
+/*!
+ \readonly
+ \qmlproperty QPointF QtQuick::HandlerPoint::pressPosition
+ \brief The pressed position within the \c parent Item
+
+ This is the position at which this point was pressed, relative to the
+ bounds of the \l {PointerHandler::parent} {parent}.
+*/
+
+/*!
+ \readonly
+ \qmlproperty QPointF QtQuick::HandlerPoint::scenePressPosition
+ \brief The pressed position within the scene
+
+ This is the position at which this point was pressed, in the coordinate
+ system of the \l {Qt Quick Scene Graph}{scene graph}.
+*/
+
+/*!
+ \readonly
+ \qmlproperty QPointF QtQuick::HandlerPoint::sceneGrabPosition
+ \brief The grabbed position within the scene
+
+ If this point has been grabbed by a Pointer Handler or an Item, it means
+ that object has taken sole responsibility for handling the movement and the
+ release if this point. In that case, this is the position at which the grab
+ occurred, in the coordinate system of the \l {Qt Quick Scene Graph}{scene graph}.
+*/
+
+/*!
+ \readonly
+ \qmlproperty enum QtQuick::HandlerPoint::pressedButtons
+ \brief Which mouse or stylus buttons are currently pressed
+
+ \sa MouseArea::pressedButtons
+*/
+
+/*!
+ \readonly
+ \qmlproperty enum QtQuick::HandlerPoint::modifiers
+ \brief Which modifier keys are currently pressed
+
+ This property holds the keyboard modifiers that were pressed at the time
+ the event occurred.
+
+ \sa MouseArea::modifiers
+*/
+
+/*!
+ \readonly
+ \qmlproperty QVector2D QtQuick::HandlerPoint::velocity
+ \brief A vector representing the average speed and direction of movement
+
+ This is a velocity vector pointing in the direction of movement, in logical
+ pixels per second. It has x and y components, at least one of which will be
+ nonzero when this point is in motion. It holds the average recent velocity:
+ how fast and in which direction the event point has been moving recently.
+
+ \sa QtQuick::EventPoint::velocity, QtQuick::TouchPoint::velocity, QTouchEvent::TouchPoint::velocity
+*/
+
+/*!
+ \readonly
+ \qmlproperty qreal QtQuick::HandlerPoint::rotation
+
+ This property holds the rotation angle of the stylus on a graphics tablet
+ or the contact patch of a touchpoint on a touchscreen.
+
+ It is valid only with certain tablet stylus devices and touchscreens that
+ can measure the rotation angle. Otherwise, it will be zero.
+*/
+
+/*!
+ \readonly
+ \qmlproperty qreal QtQuick::HandlerPoint::pressure
+
+ This property tells how hard the user is pressing the stylus on a graphics
+ tablet or the finger against a touchscreen, in the range from \c 0 (no
+ measurable pressure) to \c 1.0 (maximum pressure which the device can
+ measure).
+
+ It is valid only with certain tablets and touchscreens that can measure
+ pressure. Otherwise, it will be zero.
+*/
+
+/*!
+ \readonly
+ \qmlproperty size QtQuick::HandlerPoint::ellipseDiameters
+
+ This property holds the diameters of the contact patch, if the event
+ comes from a touchpoint and the device provides this information.
+
+ A touchpoint is modeled as an elliptical area where the finger is pressed
+ against the touchscreen. (In fact, it could also be modeled as a bitmap;
+ but in that case we expect an elliptical bounding estimate to be fitted to
+ the contact patch before the event is sent.) The harder the user presses,
+ the larger the contact patch; so, these diameters provide an alternate way
+ of detecting pressure, in case the device does not include a separate
+ pressure sensor. The ellipse is centered on \l scenePosition (\l position
+ in the PointerHandler's Item's local coordinates). The \l rotation property
+ provides the rotation of the ellipse, if known. It is expected that if the
+ \l rotation is zero, the \l {QSize::height}{height} is the larger dimension
+ (the major axis), because of the usual hand position, reaching upward or
+ outward across the surface.
+
+ If the contact patch is unknown, or the device is not a touchscreen,
+ these values will be zero.
+
+ \sa QtQuick::EventTouchPoint::ellipseDiameters, QtQuick::TouchPoint::ellipseDiameters, QTouchEvent::TouchPoint::ellipseDiameters
+*/
+
+QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickhandlerpoint_p.h b/src/quick/handlers/qquickhandlerpoint_p.h
new file mode 100644
index 0000000000..1dff52942a
--- /dev/null
+++ b/src/quick/handlers/qquickhandlerpoint_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKHANDLERPOINT_H
+#define QQUICKHANDLERPOINT_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 "qquickpointerdevicehandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMultiPointHandler;
+class QQuickSinglePointHandler;
+
+class Q_QUICK_PRIVATE_EXPORT QQuickHandlerPoint {
+ Q_GADGET
+ Q_PROPERTY(int id READ id)
+ Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId)
+ Q_PROPERTY(QPointF position READ position)
+ Q_PROPERTY(QPointF scenePosition READ scenePosition)
+ Q_PROPERTY(QPointF pressPosition READ pressPosition)
+ Q_PROPERTY(QPointF scenePressPosition READ scenePressPosition)
+ Q_PROPERTY(QPointF sceneGrabPosition READ sceneGrabPosition)
+ Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers)
+ Q_PROPERTY(QVector2D velocity READ velocity)
+ Q_PROPERTY(qreal rotation READ rotation)
+ Q_PROPERTY(qreal pressure READ pressure)
+ Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters)
+
+public:
+ QQuickHandlerPoint();
+
+ int id() const { return m_id; }
+ Qt::MouseButtons pressedButtons() const { return m_pressedButtons; }
+ Qt::KeyboardModifiers modifiers() const { return m_pressedModifiers; }
+ QPointF pressPosition() const { return m_pressPosition; }
+ QPointF scenePressPosition() const { return m_scenePressPosition; }
+ QPointF sceneGrabPosition() const { return m_sceneGrabPosition; }
+ QPointF position() const { return m_position; }
+ QPointF scenePosition() const { return m_scenePosition; }
+ QVector2D velocity() const { return m_velocity; }
+ qreal rotation() const { return m_rotation; }
+ qreal pressure() const { return m_pressure; }
+ QSizeF ellipseDiameters() const { return m_ellipseDiameters; }
+ QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; }
+
+ void reset();
+ void reset(const QQuickEventPoint *point);
+ void reset(const QVector<QQuickEventPoint *> &points);
+
+private:
+ int m_id;
+ QPointingDeviceUniqueId m_uniqueId;
+ Qt::MouseButtons m_pressedButtons;
+ Qt::KeyboardModifiers m_pressedModifiers;
+ QPointF m_position;
+ QPointF m_scenePosition;
+ QPointF m_pressPosition;
+ QPointF m_scenePressPosition;
+ QPointF m_sceneGrabPosition;
+ QVector2D m_velocity;
+ qreal m_rotation;
+ qreal m_pressure;
+ QSizeF m_ellipseDiameters;
+ friend class QQuickMultiPointHandler;
+ friend class QQuickSinglePointHandler;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickHandlerPoint)
+
+#endif // QQUICKHANDLERPOINT_H
diff --git a/src/quick/handlers/qquickhandlersmodule.cpp b/src/quick/handlers/qquickhandlersmodule.cpp
index c9e08fe4f2..814602c0bd 100644
--- a/src/quick/handlers/qquickhandlersmodule.cpp
+++ b/src/quick/handlers/qquickhandlersmodule.cpp
@@ -40,6 +40,7 @@
#include "qquickhandlersmodule_p.h"
#include "qquickpointerhandler_p.h"
#include "qquickdraghandler_p.h"
+#include "qquickhoverhandler_p.h"
#include "qquickpinchhandler_p.h"
#include "qquickpointhandler_p.h"
#include "qquicktaphandler_p.h"
@@ -87,6 +88,7 @@ static void qt_quickhandlers_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickDragHandler>(uri,major,minor,"DragHandler");
qmlRegisterUncreatableType<QQuickDragAxis>(uri, major, minor, "DragAxis",
QQuickDragHandler::tr("DragAxis is only available as a grouped property of DragHandler"));
+ qmlRegisterType<QQuickHoverHandler>(uri,major,minor,"HoverHandler");
qmlRegisterType<QQuickPinchHandler>(uri,major,minor,"PinchHandler");
qmlRegisterType<QQuickTapHandler>(uri,major,minor,"TapHandler");
qRegisterMetaType<QQuickHandlerPoint>();
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
new file mode 100644
index 0000000000..430722bd93
--- /dev/null
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickhoverhandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcHoverHandler, "qt.quick.handler.hover")
+
+/*!
+ \qmltype HoverHandler
+ \instantiates QQuickHoverHandler
+ \inqmlmodule QtQuick
+ \ingroup qtquick-handlers
+ \brief Handler for mouse and tablet hover
+
+ HoverHandler detects a hovering cursor. Since touchscreens don't generally
+ offer hover events, in practice it detects a hovering mouse or tablet stylus.
+
+ \sa MouseArea
+*/
+
+QQuickHoverHandler::QQuickHoverHandler(QObject *parent)
+ : QQuickSinglePointHandler(parent)
+ , m_hovered(false)
+{
+ // Rule out the touchscreen for now (can be overridden in QML in case a hover-detecting touchscreen exists)
+ setAcceptedDevices(static_cast<QQuickPointerDevice::DeviceType>(
+ static_cast<int>(QQuickPointerDevice::AllDevices) ^ static_cast<int>(QQuickPointerDevice::TouchScreen)));
+}
+
+QQuickHoverHandler::~QQuickHoverHandler()
+{
+ QQuickItemPrivate *parItemPrivate = QQuickItemPrivate::get(parentItem());
+ parItemPrivate->setHasHoverInChild(false);
+}
+
+void QQuickHoverHandler::componentComplete()
+{
+ parentItem()->setAcceptHoverEvents(true);
+ QQuickItemPrivate::get(parentItem())->setHasHoverInChild(true);
+}
+
+bool QQuickHoverHandler::wantsPointerEvent(QQuickPointerEvent *event)
+{
+ QQuickEventPoint *point = event->point(0);
+ if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(point)) {
+ // assume this is a mouse event, so there's only one point
+ setPointId(point->pointId());
+ return true;
+ }
+ setHovered(false);
+ return false;
+}
+
+void QQuickHoverHandler::handleEventPoint(QQuickEventPoint *point)
+{
+ setHovered(true);
+ setPassiveGrab(point);
+}
+
+void QQuickHoverHandler::setHovered(bool hovered)
+{
+ if (m_hovered != hovered) {
+ qCDebug(lcHoverHandler) << objectName() << "hovered" << m_hovered << "->" << hovered;
+ m_hovered = hovered;
+ emit hoveredChanged();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickhoverhandler_p.h b/src/quick/handlers/qquickhoverhandler_p.h
new file mode 100644
index 0000000000..876d01761b
--- /dev/null
+++ b/src/quick/handlers/qquickhoverhandler_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKHOVERHANDLER_H
+#define QQUICKHOVERHANDLER_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 "qquickitem.h"
+#include "qevent.h"
+#include "qquicksinglepointhandler_p.h"
+#include <QtCore/qbasictimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QQuickHoverHandler : public QQuickSinglePointHandler
+{
+ Q_OBJECT
+ Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged)
+
+public:
+ explicit QQuickHoverHandler(QObject *parent = 0);
+ ~QQuickHoverHandler();
+
+ bool isHovered() const { return m_hovered; }
+
+Q_SIGNALS:
+ void hoveredChanged();
+
+protected:
+ void componentComplete() override;
+ bool wantsPointerEvent(QQuickPointerEvent *event) override;
+ void handleEventPoint(QQuickEventPoint *point) override;
+
+private:
+ void setHovered(bool hovered);
+
+private:
+ bool m_hovered;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickHoverHandler)
+
+#endif // QQUICKHOVERHANDLER_H
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index d595b4c9b4..9a3732ff84 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -63,7 +63,6 @@ QQuickMultiPointHandler::QQuickMultiPointHandler(QObject *parent, int minimumPoi
: QQuickPointerDeviceHandler(parent)
, m_minimumPointCount(minimumPointCount)
, m_maximumPointCount(-1)
- , m_pointDistanceThreshold(0)
{
}
@@ -81,7 +80,7 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
return true;
#endif
- if (sameAsCurrentPoints(event))
+ if (hasCurrentPoints(event))
return true;
const QVector<QQuickEventPoint *> candidatePoints = eligiblePoints(event);
@@ -91,12 +90,24 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
return ret;
}
+void QQuickMultiPointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
+{
+ QQuickPointerHandler::handlePointerEventImpl(event);
+ m_centroid.reset(m_currentPoints);
+ emit centroidChanged();
+}
+
+void QQuickMultiPointHandler::onActiveChanged()
+{
+ if (active()) {
+ m_centroid.m_sceneGrabPosition = m_centroid.m_scenePosition;
+ }
+}
+
QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointerEvent *event)
{
QVector<QQuickEventPoint *> ret;
int c = event->pointCount();
- QRectF parentBounds = parentItem()->mapRectToScene(parentItem()->boundingRect())
- .marginsAdded(QMarginsF(m_pointDistanceThreshold, m_pointDistanceThreshold, m_pointDistanceThreshold, m_pointDistanceThreshold));
// If one or more points are newly pressed or released, all non-released points are candidates for this handler.
// In other cases however, do not steal the grab: that is, if a point has a grabber,
// it's not a candidate for this handler.
@@ -108,7 +119,7 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe
if (exclusiveGrabber && exclusiveGrabber != this)
continue;
}
- if (p->state() != QQuickEventPoint::Released && parentBounds.contains(p->scenePosition()))
+ if (p->state() != QQuickEventPoint::Released && wantsEventPoint(p))
ret << p;
}
return ret;
@@ -122,7 +133,7 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe
If a smaller number of touchpoints are in contact with the
\l {PointerHandler::parent}{parent}, they will be ignored.
- Any ignored points are eligible to activate other Pointer Handlers that
+ Any ignored points are eligible to activate other Input Handlers that
have different constraints, on the same Item or on other Items.
The default value is 2.
@@ -148,7 +159,7 @@ void QQuickMultiPointHandler::setMinimumPointCount(int c)
chosen in the order that they are pressed, and the remaining points will
be ignored.
- Any ignored points are eligible to activate other Pointer Handlers that
+ Any ignored points are eligible to activate other Input Handlers that
have different constraints, on the same Item or on other Items.
The default value is the same as \l minimumPointCount.
@@ -162,34 +173,11 @@ void QQuickMultiPointHandler::setMaximumPointCount(int maximumPointCount)
emit maximumPointCountChanged();
}
-/*!
- \qmlproperty real MultiPointHandler::pointDistanceThreshold
-
- The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
- item within which a touch point can activate this handler. For example, on
- a PinchHandler where the \l {PointerHandler::target}{target} is also the
- \c parent, it's useful to set this to a distance at least half the width
- of a typical user's finger, so that if the \c parent has been scaled down
- to a very small size, the pinch gesture is still possible.
-
- The default value is 0.
-
- \image pointDistanceThreshold.png
-*/
-void QQuickMultiPointHandler::setPointDistanceThreshold(qreal pointDistanceThreshold)
-{
- if (m_pointDistanceThreshold == pointDistanceThreshold)
- return;
-
- m_pointDistanceThreshold = pointDistanceThreshold;
- emit pointDistanceThresholdChanged();
-}
-
-bool QQuickMultiPointHandler::sameAsCurrentPoints(QQuickPointerEvent *event)
+bool QQuickMultiPointHandler::hasCurrentPoints(QQuickPointerEvent *event)
{
bool ret = true;
int c = event->pointCount();
- if (c != m_currentPoints.size())
+ if (c < m_currentPoints.size())
return false;
// TODO optimize: either ensure the points are sorted,
// or use std::equal with a predicate
@@ -207,27 +195,6 @@ bool QQuickMultiPointHandler::sameAsCurrentPoints(QQuickPointerEvent *event)
return ret;
}
-// TODO make templates for these functions somehow?
-QPointF QQuickMultiPointHandler::touchPointCentroid()
-{
- QPointF ret;
- if (Q_UNLIKELY(m_currentPoints.size() == 0))
- return ret;
- for (QQuickEventPoint *point : qAsConst(m_currentPoints))
- ret += point->scenePosition();
- return ret / m_currentPoints.size();
-}
-
-QVector2D QQuickMultiPointHandler::touchPointCentroidVelocity()
-{
- QVector2D ret;
- if (Q_UNLIKELY(m_currentPoints.size() == 0))
- return ret;
- for (QQuickEventPoint *point : qAsConst(m_currentPoints))
- ret += point->velocity();
- return ret / m_currentPoints.size();
-}
-
qreal QQuickMultiPointHandler::averageTouchPointDistance(const QPointF &ref)
{
qreal ret = 0;
diff --git a/src/quick/handlers/qquickmultipointhandler_p.h b/src/quick/handlers/qquickmultipointhandler_p.h
index 67e550d387..06045771fb 100644
--- a/src/quick/handlers/qquickmultipointhandler_p.h
+++ b/src/quick/handlers/qquickmultipointhandler_p.h
@@ -53,6 +53,7 @@
#include "qquickitem.h"
#include "qevent.h"
+#include "qquickhandlerpoint_p.h"
#include "qquickpointerdevicehandler_p.h"
QT_BEGIN_NAMESPACE
@@ -62,7 +63,7 @@ class Q_AUTOTEST_EXPORT QQuickMultiPointHandler : public QQuickPointerDeviceHand
Q_OBJECT
Q_PROPERTY(int minimumPointCount READ minimumPointCount WRITE setMinimumPointCount NOTIFY minimumPointCountChanged)
Q_PROPERTY(int maximumPointCount READ maximumPointCount WRITE setMaximumPointCount NOTIFY maximumPointCountChanged)
- Q_PROPERTY(qreal pointDistanceThreshold READ pointDistanceThreshold WRITE setPointDistanceThreshold NOTIFY pointDistanceThresholdChanged)
+ Q_PROPERTY(QQuickHandlerPoint centroid READ centroid NOTIFY centroidChanged)
public:
explicit QQuickMultiPointHandler(QObject *parent = nullptr, int minimumPointCount = 2);
@@ -74,13 +75,13 @@ public:
int maximumPointCount() const { return m_maximumPointCount >= 0 ? m_maximumPointCount : m_minimumPointCount; }
void setMaximumPointCount(int maximumPointCount);
- qreal pointDistanceThreshold() const { return m_pointDistanceThreshold; }
- void setPointDistanceThreshold(qreal pointDistanceThreshold);
+ QQuickHandlerPoint centroid() const { return m_centroid; }
signals:
void minimumPointCountChanged();
void maximumPointCountChanged();
void pointDistanceThresholdChanged();
+ void centroidChanged();
protected:
struct PointData {
@@ -91,10 +92,10 @@ protected:
};
bool wantsPointerEvent(QQuickPointerEvent *event) override;
- bool sameAsCurrentPoints(QQuickPointerEvent *event);
+ void handlePointerEventImpl(QQuickPointerEvent *event) override;
+ void onActiveChanged() override;
+ bool hasCurrentPoints(QQuickPointerEvent *event);
QVector<QQuickEventPoint *> eligiblePoints(QQuickPointerEvent *event);
- QPointF touchPointCentroid();
- QVector2D touchPointCentroidVelocity();
qreal averageTouchPointDistance(const QPointF &ref);
qreal averageStartingDistance(const QPointF &ref);
qreal averageTouchPointAngle(const QPointF &ref);
@@ -106,9 +107,9 @@ protected:
protected:
QVector<QQuickEventPoint *> m_currentPoints;
+ QQuickHandlerPoint m_centroid;
int m_minimumPointCount;
int m_maximumPointCount;
- qreal m_pointDistanceThreshold;
};
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 57d851ed59..c251ae6d36 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -61,7 +61,7 @@ Q_LOGGING_CATEGORY(lcPinchHandler, "qt.quick.handler.pinch")
\brief Handler for pinch gestures.
PinchHandler is a handler that interprets a multi-finger gesture to
- interactively rotate, zoom, and drag an Item. Like other Pointer Handlers,
+ interactively rotate, zoom, and drag an Item. Like other Input Handlers,
by default it is fully functional, and manipulates its \l target,
which is the Item within which it is declared.
@@ -88,6 +88,7 @@ Q_LOGGING_CATEGORY(lcPinchHandler, "qt.quick.handler.pinch")
QQuickPinchHandler::QQuickPinchHandler(QObject *parent)
: QQuickMultiPointHandler(parent, 2)
, m_activeScale(1)
+ , m_accumulatedScale(1)
, m_activeRotation(0)
, m_activeTranslation(0,0)
, m_minimumScale(-qInf())
@@ -287,11 +288,11 @@ bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event)
void QQuickPinchHandler::onActiveChanged()
{
+ QQuickMultiPointHandler::onActiveChanged();
if (active()) {
m_startMatrix = QMatrix4x4();
- m_startCentroid = touchPointCentroid();
- m_startAngles = angles(m_startCentroid);
- m_startDistance = averageTouchPointDistance(m_startCentroid);
+ m_startAngles = angles(m_centroid.sceneGrabPosition());
+ m_startDistance = averageTouchPointDistance(m_centroid.sceneGrabPosition());
m_activeRotation = 0;
m_activeTranslation = QVector2D();
if (const QQuickItem *t = target()) {
@@ -304,7 +305,7 @@ void QQuickPinchHandler::onActiveChanged()
m_startMatrix.rotate(m_startRotation, 0, 0, -1);
m_startMatrix.translate(-xformOrigin);
} else {
- m_startScale = 1;
+ m_startScale = m_accumulatedScale;
m_startRotation = 0;
}
qCInfo(lcPinchHandler) << "activated with starting scale" << m_startScale << "rotation" << m_startRotation;
@@ -319,6 +320,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
for (QQuickEventPoint *point : qAsConst(m_currentPoints))
qCDebug(lcPinchHandler) << point->state() << point->sceneGrabPosition() << "->" << point->scenePosition();
}
+ QQuickMultiPointHandler::handlePointerEventImpl(event);
qreal dist = 0;
#if QT_CONFIG(gestures)
@@ -328,8 +330,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
m_activeScale = 1;
m_activeRotation = 0;
m_activeTranslation = QVector2D();
- m_centroid = QPointF();
- m_centroidVelocity = QVector2D();
+ m_centroid.reset();
setActive(false);
emit updated();
return;
@@ -344,12 +345,9 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
return;
}
if (!active()) {
- m_centroid = gesture->point(0)->scenePosition();
setActive(true);
- m_startCentroid = m_centroid;
// Native gestures for 2-finger pinch do not allow dragging, so
// the centroid won't move during the gesture, and translation stays at zero
- m_centroidVelocity = QVector2D();
m_activeTranslation = QVector2D();
}
} else
@@ -374,17 +372,15 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
return;
}
// TODO check m_pinchOrigin: right now it acts like it's set to PinchCenter
- m_centroid = touchPointCentroid();
- m_centroidVelocity = touchPointCentroidVelocity();
// avoid mapping the minima and maxima, as they might have unmappable values
// such as -inf/+inf. Because of this we perform the bounding to min/max in local coords.
// 1. scale
- dist = averageTouchPointDistance(m_centroid);
+ dist = averageTouchPointDistance(m_centroid.scenePosition());
m_activeScale = dist / m_startDistance;
m_activeScale = qBound(m_minimumScale/m_startScale, m_activeScale, m_maximumScale/m_startScale);
// 2. rotate
- QVector<PointData> newAngles = angles(m_centroid);
+ QVector<PointData> newAngles = angles(m_centroid.scenePosition());
const qreal angleDelta = averageAngleDelta(m_startAngles, newAngles);
m_activeRotation += angleDelta;
m_startAngles = std::move(newAngles);
@@ -396,20 +392,19 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
QPointF centroidParentPos;
QRectF bounds(m_minimumX, m_minimumY, m_maximumX - m_minimumX, m_maximumY - m_minimumY);
if (target() && target()->parentItem()) {
- centroidParentPos = target()->parentItem()->mapFromScene(m_centroid);
+ centroidParentPos = target()->parentItem()->mapFromScene(m_centroid.scenePosition());
centroidParentPos = QPointF(qBound(bounds.left(), centroidParentPos.x(), bounds.right()),
qBound(bounds.top(), centroidParentPos.y(), bounds.bottom()));
}
const qreal totalRotation = m_startRotation + m_activeRotation;
const qreal rotation = qBound(m_minimumRotation, totalRotation, m_maximumRotation);
m_activeRotation += (rotation - totalRotation); //adjust for the potential bounding above
- const qreal scale = m_startScale * m_activeScale;
+ m_accumulatedScale = m_startScale * m_activeScale;
if (target() && target()->parentItem()) {
// 3. Drag/translate
- const QPointF centroidStartParentPos = target()->parentItem()->mapFromScene(m_startCentroid);
+ const QPointF centroidStartParentPos = target()->parentItem()->mapFromScene(m_centroid.sceneGrabPosition());
m_activeTranslation = QVector2D(centroidParentPos - centroidStartParentPos);
-
// apply rotation + scaling around the centroid - then apply translation.
QMatrix4x4 mat;
@@ -428,16 +423,16 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
target()->setPosition(pos);
target()->setRotation(rotation);
- target()->setScale(scale);
+ target()->setScale(m_accumulatedScale);
// TODO some translation inadvertently happens; try to hold the chosen pinch origin in place
} else {
- m_activeTranslation = QVector2D(m_centroid - m_startCentroid);
+ m_activeTranslation = QVector2D(m_centroid.scenePosition() - m_centroid.scenePressPosition());
}
- qCDebug(lcPinchHandler) << "centroid" << m_startCentroid << "->" << m_centroid
+ qCDebug(lcPinchHandler) << "centroid" << m_centroid.scenePressPosition() << "->" << m_centroid.scenePosition()
<< ", distance" << m_startDistance << "->" << dist
- << ", startScale" << m_startScale << "->" << scale
+ << ", startScale" << m_startScale << "->" << m_accumulatedScale
<< ", activeRotation" << m_activeRotation
<< ", rotation" << rotation
<< " from " << event->device()->type();
@@ -456,22 +451,25 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
/*!
\readonly
- \qmlproperty QVector2D QtQuick::PinchHandler::centroidVelocity
+ \qmlproperty real QtQuick::PinchHandler::scale
- The average velocity of the \l centroid: a vector representing the speed
- and direction of movement of the whole group of touchpoints, in logical
- pixels per second.
+ The scale factor that will automatically be set on the \l target if it is not null.
+ Otherwise, bindings can be used to do arbitrary things with this value.
+ While the pinch gesture is being performed, it is continuously multiplied by
+ \l activeScale; after the gesture ends, it stays the same; and when the next
+ pinch gesture begins, it begins to be multiplied by activeScale again.
*/
/*!
\readonly
- \qmlproperty real QtQuick::PinchHandler::scale
-
- The scale factor. It is 1.0 when the gesture begins, increases as the
- touchpoints are spread apart, and decreases as the touchpoints are brought
- together. If \l target is not null, this will be automatically applied to its
- \l {Item::scale}{scale}. Otherwise, bindings can be used to do arbitrary
- things with this value.
+ \qmlproperty real QtQuick::PinchHandler::activeScale
+
+ The scale factor while the pinch gesture is being performed.
+ It is 1.0 when the gesture begins, increases as the touchpoints are spread
+ apart, and decreases as the touchpoints are brought together.
+ If \l target is not null, its \l {Item::scale}{scale} will be automatically
+ multiplied by this value.
+ Otherwise, bindings can be used to do arbitrary things with this value.
*/
/*!
diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h
index 9a17971416..0d0630d2a9 100644
--- a/src/quick/handlers/qquickpinchhandler_p.h
+++ b/src/quick/handlers/qquickpinchhandler_p.h
@@ -66,9 +66,8 @@ class Q_AUTOTEST_EXPORT QQuickPinchHandler : public QQuickMultiPointHandler
Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged)
Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged)
Q_PROPERTY(PinchOrigin pinchOrigin READ pinchOrigin WRITE setPinchOrigin NOTIFY pinchOriginChanged)
- Q_PROPERTY(QPointF centroid READ centroid NOTIFY updated)
- Q_PROPERTY(QVector2D centroidVelocity READ centroidVelocity NOTIFY updated)
Q_PROPERTY(qreal scale READ scale NOTIFY updated)
+ Q_PROPERTY(qreal activeScale READ activeScale NOTIFY updated)
Q_PROPERTY(qreal rotation READ rotation NOTIFY updated)
Q_PROPERTY(QVector2D translation READ translation NOTIFY updated)
Q_PROPERTY(qreal minimumX READ minimumX WRITE setMinimumX NOTIFY minimumXChanged)
@@ -101,11 +100,9 @@ public:
void setPinchOrigin(PinchOrigin pinchOrigin);
QVector2D translation() const { return m_activeTranslation; }
- qreal scale() const { return m_activeScale; }
+ qreal scale() const { return m_accumulatedScale; }
+ qreal activeScale() const { return m_activeScale; }
qreal rotation() const { return m_activeRotation; }
- QPointF centroid() const { return m_centroid; }
- QVector2D centroidVelocity() const { return m_centroidVelocity; }
-
qreal minimumX() const { return m_minimumX; }
void setMinimumX(qreal minX);
qreal maximumX() const { return m_maximumX; }
@@ -135,10 +132,9 @@ protected:
private:
// properties
qreal m_activeScale;
+ qreal m_accumulatedScale;
qreal m_activeRotation;
QVector2D m_activeTranslation;
- QPointF m_centroid;
- QVector2D m_centroidVelocity;
qreal m_minimumScale;
qreal m_maximumScale;
@@ -156,7 +152,6 @@ private:
// internal
qreal m_startScale;
qreal m_startRotation;
- QPointF m_startCentroid;
qreal m_startDistance;
QPointF m_startPos;
diff --git a/src/quick/handlers/qquickpointerdevicehandler.cpp b/src/quick/handlers/qquickpointerdevicehandler.cpp
index 06831613b6..7b9f6839b1 100644
--- a/src/quick/handlers/qquickpointerdevicehandler.cpp
+++ b/src/quick/handlers/qquickpointerdevicehandler.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qquickpointerdevicehandler_p.h"
+#include "qquickpointerdevicehandler_p_p.h"
#include <private/qquickitem_p.h>
#include <QMouseEvent>
#include <QDebug>
@@ -59,10 +59,12 @@ QT_BEGIN_NAMESPACE
allow filtering based on device type, pointer type, or keyboard modifiers.
*/
QQuickPointerDeviceHandler::QQuickPointerDeviceHandler(QObject *parent)
- : QQuickPointerHandler(parent)
- , m_acceptedDevices(QQuickPointerDevice::AllDevices)
- , m_acceptedPointerTypes(QQuickPointerDevice::AllPointerTypes)
- , m_acceptedModifiers(Qt::KeyboardModifierMask)
+ : QQuickPointerHandler(*(new QQuickPointerDeviceHandlerPrivate), parent)
+{
+}
+
+QQuickPointerDeviceHandler::QQuickPointerDeviceHandler(QQuickPointerDeviceHandlerPrivate &dd, QObject *parent)
+ : QQuickPointerHandler(dd, parent)
{
}
@@ -70,6 +72,69 @@ QQuickPointerDeviceHandler::~QQuickPointerDeviceHandler()
{
}
+QQuickPointerDevice::DeviceTypes QQuickPointerDeviceHandler::acceptedDevices() const
+{
+ Q_D(const QQuickPointerDeviceHandler);
+ return d->acceptedDevices;
+}
+
+QQuickPointerDevice::PointerTypes QQuickPointerDeviceHandler::acceptedPointerTypes() const
+{
+ Q_D(const QQuickPointerDeviceHandler);
+ return d->acceptedPointerTypes;
+}
+
+/*!
+ \qmlproperty int QtQuick::PointerDeviceHandler::acceptedButtons
+
+ The mouse buttons which can activate this Pointer Handler.
+
+ By default, this property is set to \l {QtQuick::MouseEvent::button} {Qt.LeftButton}.
+ It can be set to an OR combination of mouse buttons, and will ignore events
+ from other buttons.
+
+ For example, a control could be made to respond to left and right clicks
+ in different ways, with two handlers:
+
+ \qml
+ Item {
+ TapHandler {
+ onTapped: console.log("left clicked")
+ }
+ TapHandler {
+ acceptedButtons: Qt.RightButton
+ onTapped: console.log("right clicked")
+ }
+ }
+ \endqml
+
+ \note Tapping on a touchscreen or tapping the stylus on a graphics tablet
+ emulates clicking the left mouse button. This behavior can be altered via
+ \l {PointerDeviceHandler::acceptedDevices}{acceptedDevices} or
+ \l {PointerDeviceHandler::acceptedPointerTypes}{acceptedPointerTypes}.
+*/
+Qt::MouseButtons QQuickPointerDeviceHandler::acceptedButtons() const
+{
+ Q_D(const QQuickPointerDeviceHandler);
+ return d->acceptedButtons;
+}
+
+void QQuickPointerDeviceHandler::setAcceptedButtons(Qt::MouseButtons buttons)
+{
+ Q_D(QQuickPointerDeviceHandler);
+ if (d->acceptedButtons == buttons)
+ return;
+
+ d->acceptedButtons = buttons;
+ emit acceptedButtonsChanged();
+}
+
+Qt::KeyboardModifiers QQuickPointerDeviceHandler::acceptedModifiers() const
+{
+ Q_D(const QQuickPointerDeviceHandler);
+ return d->acceptedModifiers;
+}
+
/*!
\qmlproperty int PointerDeviceHandler::acceptedDevices
@@ -98,10 +163,11 @@ QQuickPointerDeviceHandler::~QQuickPointerDeviceHandler()
*/
void QQuickPointerDeviceHandler::setAcceptedDevices(QQuickPointerDevice::DeviceTypes acceptedDevices)
{
- if (m_acceptedDevices == acceptedDevices)
+ Q_D(QQuickPointerDeviceHandler);
+ if (d->acceptedDevices == acceptedDevices)
return;
- m_acceptedDevices = acceptedDevices;
+ d->acceptedDevices = acceptedDevices;
emit acceptedDevicesChanged();
}
@@ -136,10 +202,11 @@ void QQuickPointerDeviceHandler::setAcceptedDevices(QQuickPointerDevice::DeviceT
*/
void QQuickPointerDeviceHandler::setAcceptedPointerTypes(QQuickPointerDevice::PointerTypes acceptedPointerTypes)
{
- if (m_acceptedPointerTypes == acceptedPointerTypes)
+ Q_D(QQuickPointerDeviceHandler);
+ if (d->acceptedPointerTypes == acceptedPointerTypes)
return;
- m_acceptedPointerTypes = acceptedPointerTypes;
+ d->acceptedPointerTypes = acceptedPointerTypes;
emit acceptedPointerTypesChanged();
}
@@ -171,26 +238,28 @@ void QQuickPointerDeviceHandler::setAcceptedPointerTypes(QQuickPointerDevice::Po
*/
void QQuickPointerDeviceHandler::setAcceptedModifiers(Qt::KeyboardModifiers acceptedModifiers)
{
- if (m_acceptedModifiers == acceptedModifiers)
+ Q_D(QQuickPointerDeviceHandler);
+ if (d->acceptedModifiers == acceptedModifiers)
return;
- m_acceptedModifiers = acceptedModifiers;
+ d->acceptedModifiers = acceptedModifiers;
emit acceptedModifiersChanged();
}
bool QQuickPointerDeviceHandler::wantsPointerEvent(QQuickPointerEvent *event)
{
+ Q_D(QQuickPointerDeviceHandler);
if (!QQuickPointerHandler::wantsPointerEvent(event))
return false;
qCDebug(lcPointerHandlerDispatch) << objectName()
- << "checking device type" << m_acceptedDevices
- << "pointer type" << m_acceptedPointerTypes
- << "modifiers" << m_acceptedModifiers;
- if ((event->device()->type() & m_acceptedDevices) == 0)
+ << "checking device type" << d->acceptedDevices
+ << "pointer type" << d->acceptedPointerTypes
+ << "modifiers" << d->acceptedModifiers;
+ if ((event->device()->type() & d->acceptedDevices) == 0)
return false;
- if ((event->device()->pointerType() & m_acceptedPointerTypes) == 0)
+ if ((event->device()->pointerType() & d->acceptedPointerTypes) == 0)
return false;
- if (m_acceptedModifiers != Qt::KeyboardModifierMask && event->modifiers() != m_acceptedModifiers)
+ if (d->acceptedModifiers != Qt::KeyboardModifierMask && event->modifiers() != d->acceptedModifiers)
return false;
return true;
}
diff --git a/src/quick/handlers/qquickpointerdevicehandler_p.h b/src/quick/handlers/qquickpointerdevicehandler_p.h
index 1638604ea7..4194769fd7 100644
--- a/src/quick/handlers/qquickpointerdevicehandler_p.h
+++ b/src/quick/handlers/qquickpointerdevicehandler_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -36,6 +36,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#include "qquickpointerhandler_p.h"
#ifndef QQUICKPOINTERDEVICEHANDLER_H
#define QQUICKPOINTERDEVICEHANDLER_H
@@ -51,42 +52,45 @@
// We mean it.
//
-#include "qquickpointerhandler_p.h"
-
QT_BEGIN_NAMESPACE
+class QQuickPointerDeviceHandlerPrivate;
+
class Q_AUTOTEST_EXPORT QQuickPointerDeviceHandler : public QQuickPointerHandler
{
Q_OBJECT
Q_PROPERTY(QQuickPointerDevice::DeviceTypes acceptedDevices READ acceptedDevices WRITE setAcceptedDevices NOTIFY acceptedDevicesChanged)
Q_PROPERTY(QQuickPointerDevice::PointerTypes acceptedPointerTypes READ acceptedPointerTypes WRITE setAcceptedPointerTypes NOTIFY acceptedPointerTypesChanged)
+ Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
Q_PROPERTY(Qt::KeyboardModifiers acceptedModifiers READ acceptedModifiers WRITE setAcceptedModifiers NOTIFY acceptedModifiersChanged)
public:
explicit QQuickPointerDeviceHandler(QObject *parent = nullptr);
~QQuickPointerDeviceHandler();
- QQuickPointerDevice::DeviceTypes acceptedDevices() const { return m_acceptedDevices; }
- QQuickPointerDevice::PointerTypes acceptedPointerTypes() const { return m_acceptedPointerTypes; }
- Qt::KeyboardModifiers acceptedModifiers() const { return m_acceptedModifiers; }
+ QQuickPointerDevice::DeviceTypes acceptedDevices() const;
+ QQuickPointerDevice::PointerTypes acceptedPointerTypes() const;
+ Qt::MouseButtons acceptedButtons() const;
+ Qt::KeyboardModifiers acceptedModifiers() const;
-public slots:
+public Q_SLOTS:
void setAcceptedDevices(QQuickPointerDevice::DeviceTypes acceptedDevices);
void setAcceptedPointerTypes(QQuickPointerDevice::PointerTypes acceptedPointerTypes);
+ void setAcceptedButtons(Qt::MouseButtons buttons);
void setAcceptedModifiers(Qt::KeyboardModifiers acceptedModifiers);
Q_SIGNALS:
void acceptedDevicesChanged();
void acceptedPointerTypesChanged();
+ void acceptedButtonsChanged();
void acceptedModifiersChanged();
protected:
+ QQuickPointerDeviceHandler(QQuickPointerDeviceHandlerPrivate &dd, QObject *parent = nullptr);
+
bool wantsPointerEvent(QQuickPointerEvent *event) override;
-protected:
- QQuickPointerDevice::DeviceTypes m_acceptedDevices;
- QQuickPointerDevice::PointerTypes m_acceptedPointerTypes;
- Qt::KeyboardModifiers m_acceptedModifiers;
+ Q_DECLARE_PRIVATE(QQuickPointerDeviceHandler)
};
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickpointerdevicehandler_p_p.h b/src/quick/handlers/qquickpointerdevicehandler_p_p.h
new file mode 100644
index 0000000000..6a950590f3
--- /dev/null
+++ b/src/quick/handlers/qquickpointerdevicehandler_p_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOINTERDEVICEHANDLER_P_H
+#define QQUICKPOINTERDEVICEHANDLER_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 "qquickpointerdevicehandler_p.h"
+#include "qquickpointerhandler_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QQuickPointerDeviceHandlerPrivate : public QQuickPointerHandlerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickPointerDeviceHandler)
+
+public:
+ static QQuickPointerDeviceHandlerPrivate* get(QQuickPointerDeviceHandler *q) { return q->d_func(); }
+ static const QQuickPointerDeviceHandlerPrivate* get(const QQuickPointerDeviceHandler *q) { return q->d_func(); }
+
+ QQuickPointerDevice::DeviceTypes acceptedDevices = QQuickPointerDevice::AllDevices;
+ QQuickPointerDevice::PointerTypes acceptedPointerTypes = QQuickPointerDevice::AllPointerTypes;
+ Qt::MouseButtons acceptedButtons = Qt::LeftButton;
+ Qt::KeyboardModifiers acceptedModifiers = Qt::KeyboardModifierMask;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOINTERDEVICEHANDLER_P_H
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index e5b1dc8985..8e10003c6a 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -38,6 +38,8 @@
****************************************************************************/
#include "qquickpointerhandler_p.h"
+#include "qquickpointerhandler_p_p.h"
+#include <QtQuick/private/qquickitem_p.h>
QT_BEGIN_NAMESPACE
@@ -55,20 +57,17 @@ Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active")
\ingroup qtquick-handlers
\brief Abstract handler for pointer events.
- PointerHandler is the base class handler (not registered as a QML type) for
- pointer events without regard to source (touch, mouse or graphics tablet).
+ PointerHandler is the base class Input Handler (not registered as a QML type) for
+ events from any kind of pointing device (touch, mouse or graphics tablet).
*/
QQuickPointerHandler::QQuickPointerHandler(QObject *parent)
- : QObject(parent)
- , m_currentEvent(nullptr)
- , m_target(nullptr)
- , m_enabled(true)
- , m_active(false)
- , m_targetExplicitlySet(false)
- , m_hadKeepMouseGrab(false)
- , m_hadKeepTouchGrab(false)
- , m_grabPermissions(CanTakeOverFromItems | CanTakeOverFromHandlersOfDifferentType | ApprovesTakeOverByAnything)
+ : QObject(*(new QQuickPointerHandlerPrivate), parent)
+{
+}
+
+QQuickPointerHandler::QQuickPointerHandler(QQuickPointerHandlerPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
{
}
@@ -82,13 +81,46 @@ QQuickPointerHandler::~QQuickPointerHandler()
}
/*!
+ \qmlproperty real PointerHandler::margin
+
+ The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
+ item within which an event point can activate this handler. For example, on
+ a PinchHandler where the \l {PointerHandler::target}{target} is also the
+ \c parent, it's useful to set this to a distance at least half the width
+ of a typical user's finger, so that if the \c parent has been scaled down
+ to a very small size, the pinch gesture is still possible. Or, if a
+ TapHandler-based button is placed near the screen edge, it can be used
+ to comply with Fitts's Law: react to mouse clicks at the screen edge
+ even though the button is visually spaced away from the edge by a few pixels.
+
+ The default value is 0.
+
+ \image pointDistanceThreshold.png
+*/
+qreal QQuickPointerHandler::margin() const
+{
+ Q_D(const QQuickPointerHandler);
+ return d->m_margin;
+}
+
+void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
+{
+ Q_D(QQuickPointerHandler);
+ if (d->m_margin == pointDistanceThreshold)
+ return;
+
+ d->m_margin = pointDistanceThreshold;
+ emit marginChanged();
+}
+
+/*!
Notification that the grab has changed in some way which is relevant to this handler.
- The \a grabber (subject) will be the PointerHandler whose state is changing,
+ The \a grabber (subject) will be the Input Handler whose state is changing,
or null if the state change regards an Item.
The \a stateChange (verb) tells what happened.
The \a point (object) is the point that was grabbed or ungrabbed.
EventPoint has the sole responsibility to call this function.
- The PointerHandler must react in whatever way is appropriate, and must
+ The Input Handler must react in whatever way is appropriate, and must
emit the relevant signals (for the benefit of QML code).
A subclass is allowed to override this virtual function, but must always
call its parent class's implementation in addition to (usually after)
@@ -113,8 +145,9 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEv
setActive(false);
point->setAccepted(false);
if (auto par = parentItem()) {
- par->setKeepMouseGrab(m_hadKeepMouseGrab);
- par->setKeepTouchGrab(m_hadKeepTouchGrab);
+ Q_D(const QQuickPointerHandler);
+ par->setKeepMouseGrab(d->hadKeepMouseGrab);
+ par->setKeepTouchGrab(d->hadKeepTouchGrab);
}
break;
case QQuickEventPoint::OverrideGrabPassive:
@@ -124,19 +157,17 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEv
}
if (wasCanceled)
emit canceled(point);
- else
- emit grabChanged(point);
+ emit grabChanged(stateChange, point);
}
}
/*!
- \internal
Acquire or give up a passive grab of the given \a point, according to the \a grab state.
- Unlike the exclusive grab, multiple PointerHandlers can have passive grabs
+ Unlike the exclusive grab, multiple Input Handlers can have passive grabs
simultaneously. This means that each of them will receive further events
- when the \a point moves, and when it is finally released. Typically a
- PointerHandler should acquire a passive grab as soon as a point is pressed,
+ when the \a point moves, and when it is finally released. Typically an
+ Input Handler should acquire a passive grab as soon as a point is pressed,
if the handler's constraints do not clearly rule out any interest in that
point. For example, DragHandler needs a passive grab in order to watch the
movement of a point to see whether it will be dragged past the drag
@@ -181,19 +212,20 @@ bool QQuickPointerHandler::canGrab(QQuickEventPoint *point)
*/
bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObject *proposedGrabber)
{
+ Q_D(const QQuickPointerHandler);
bool allowed = false;
if (proposedGrabber == this) {
QObject* existingGrabber = point->exclusiveGrabber();
- allowed = (existingGrabber == nullptr) || ((m_grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
+ allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
if (existingGrabber) {
if (QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler()) {
- if (!allowed && (m_grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
+ if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
existingPhGrabber->metaObject()->className() != metaObject()->className())
allowed = true;
- if (!allowed && (m_grabPermissions & CanTakeOverFromHandlersOfSameType) &&
+ if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfSameType) &&
existingPhGrabber->metaObject()->className() == metaObject()->className())
allowed = true;
- } else if ((m_grabPermissions & CanTakeOverFromItems)) {
+ } else if ((d->grabPermissions & CanTakeOverFromItems)) {
QQuickItem * existingItemGrabber = point->grabberItem();
if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && point->pointerEvent()->asPointerMouseEvent()) ||
(existingItemGrabber->keepTouchGrab() && point->pointerEvent()->asPointerTouchEvent())))
@@ -203,18 +235,18 @@ bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObjec
} else {
// proposedGrabber is different: that means this instance will lose its grab
if (proposedGrabber) {
- if ((m_grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything)
+ if ((d->grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything)
allowed = true;
- if (!allowed && (m_grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) &&
+ if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) &&
proposedGrabber->metaObject()->className() != metaObject()->className())
allowed = true;
- if (!allowed && (m_grabPermissions & ApprovesTakeOverByHandlersOfSameType) &&
+ if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfSameType) &&
proposedGrabber->metaObject()->className() == metaObject()->className())
allowed = true;
- if (!allowed && (m_grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits("QQuickItem"))
+ if (!allowed && (d->grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits("QQuickItem"))
allowed = true;
} else {
- if (!allowed && (m_grabPermissions & ApprovesCancellation))
+ if (!allowed && (d->grabPermissions & ApprovesCancellation))
allowed = true;
}
}
@@ -236,12 +268,19 @@ bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObjec
which allows most takeover scenarios but avoids e.g. two PinchHandlers fighting
over the same touchpoints.
*/
+QQuickPointerHandler::GrabPermissions QQuickPointerHandler::grabPermissions() const
+{
+ Q_D(const QQuickPointerHandler);
+ return static_cast<QQuickPointerHandler::GrabPermissions>(d->grabPermissions);
+}
+
void QQuickPointerHandler::setGrabPermissions(GrabPermissions grabPermission)
{
- if (m_grabPermissions == grabPermission)
+ Q_D(QQuickPointerHandler);
+ if (d->grabPermissions == grabPermission)
return;
- m_grabPermissions = grabPermission;
+ d->grabPermissions = grabPermission;
emit grabPermissionChanged();
}
@@ -253,8 +292,13 @@ void QQuickPointerHandler::componentComplete()
{
}
+QQuickPointerEvent *QQuickPointerHandler::currentEvent()
+{
+ Q_D(const QQuickPointerHandler);
+ return d->currentEvent;
+}
+
/*!
- \internal
Acquire or give up the exclusive grab of the given \a point, according to
the \a grab state, and subject to the rules: canGrab(), and the rule not to
relinquish another handler's grab. Returns true if permission is granted,
@@ -284,7 +328,6 @@ bool QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab)
}
/*!
- \internal
Cancel any existing grab of the given \a point.
*/
void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point)
@@ -300,9 +343,19 @@ QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const
bool QQuickPointerHandler::parentContains(const QQuickEventPoint *point) const
{
- if (point) {
- if (QQuickItem *par = parentItem())
- return par->contains(par->mapFromScene(point->scenePosition()));
+ if (!point)
+ return false;
+ if (QQuickItem *par = parentItem()) {
+ if (par->window()) {
+ QPoint screenPosition = par->window()->mapToGlobal(point->scenePosition().toPoint());
+ if (!par->window()->geometry().contains(screenPosition))
+ return false;
+ }
+ QPointF p = par->mapFromScene(point->scenePosition());
+ qreal m = margin();
+ if (m > 0)
+ return p.x() >= -m && p.y() >= -m && p.x() <= par->width() + m && p.y() <= par->height() + m;
+ return par->contains(p);
}
return false;
}
@@ -313,15 +366,28 @@ bool QQuickPointerHandler::parentContains(const QQuickEventPoint *point) const
If a PointerHandler is disabled, it will reject all events
and no signals will be emitted.
*/
+bool QQuickPointerHandler::enabled() const
+{
+ Q_D(const QQuickPointerHandler);
+ return d->enabled;
+}
+
void QQuickPointerHandler::setEnabled(bool enabled)
{
- if (m_enabled == enabled)
+ Q_D(QQuickPointerHandler);
+ if (d->enabled == enabled)
return;
- m_enabled = enabled;
+ d->enabled = enabled;
emit enabledChanged();
}
+bool QQuickPointerHandler::active() const
+{
+ Q_D(const QQuickPointerHandler);
+ return d->active;
+}
+
/*!
\qmlproperty Item QtQuick::PointerHandler::target
@@ -335,21 +401,28 @@ void QQuickPointerHandler::setEnabled(bool enabled)
*/
void QQuickPointerHandler::setTarget(QQuickItem *target)
{
- m_targetExplicitlySet = true;
- if (m_target == target)
+ Q_D(QQuickPointerHandler);
+ d->targetExplicitlySet = true;
+ if (d->target == target)
return;
- QQuickItem *oldTarget = m_target;
- m_target = target;
+ QQuickItem *oldTarget = d->target;
+ d->target = target;
onTargetChanged(oldTarget);
emit targetChanged();
}
+QQuickItem *QQuickPointerHandler::parentItem() const
+{
+ return static_cast<QQuickItem *>(QObject::parent());
+}
+
QQuickItem *QQuickPointerHandler::target() const
{
- if (!m_targetExplicitlySet)
+ Q_D(const QQuickPointerHandler);
+ if (!d->targetExplicitlySet)
return parentItem();
- return m_target;
+ return d->target;
}
void QQuickPointerHandler::handlePointerEvent(QQuickPointerEvent *event)
@@ -374,15 +447,24 @@ void QQuickPointerHandler::handlePointerEvent(QQuickPointerEvent *event)
bool QQuickPointerHandler::wantsPointerEvent(QQuickPointerEvent *event)
{
+ Q_D(const QQuickPointerHandler);
Q_UNUSED(event)
- return m_enabled;
+ return d->enabled;
+}
+
+bool QQuickPointerHandler::wantsEventPoint(QQuickEventPoint *point)
+{
+ bool ret = parentContains(point);
+ qCDebug(lcPointerHandlerDispatch) << hex << point->pointId() << "@" << point->scenePosition()
+ << metaObject()->className() << objectName() << ret;
+ return ret;
}
/*!
\readonly
\qmlproperty bool QtQuick::PointerHandler::active
- This holds true whenever this PointerHandler has taken sole responsibility
+ This holds true whenever this Input Handler has taken sole responsibility
for handing one or more EventPoints, by successfully taking an exclusive
grab of those points. This means that it is keeping its properties
up-to-date according to the movements of those Event Points and actively
@@ -390,9 +472,10 @@ bool QQuickPointerHandler::wantsPointerEvent(QQuickPointerEvent *event)
*/
void QQuickPointerHandler::setActive(bool active)
{
- if (m_active != active) {
- qCDebug(lcPointerHandlerActive) << this << m_active << "->" << active;
- m_active = active;
+ Q_D(QQuickPointerHandler);
+ if (d->active != active) {
+ qCDebug(lcPointerHandlerActive) << this << d->active << "->" << active;
+ d->active = active;
onActiveChanged();
emit activeChanged();
}
@@ -400,7 +483,8 @@ void QQuickPointerHandler::setActive(bool active)
void QQuickPointerHandler::handlePointerEventImpl(QQuickPointerEvent *event)
{
- m_currentEvent = event;
+ Q_D(QQuickPointerHandler);
+ d->currentEvent = event;
}
/*!
@@ -417,10 +501,13 @@ void QQuickPointerHandler::handlePointerEventImpl(QQuickPointerEvent *event)
*/
/*!
- \qmlsignal QtQuick::PointerHandler::grabChanged(EventPoint point)
+ \qmlsignal QtQuick::PointerHandler::grabChanged(GrabState stateChange, EventPoint point)
+
+ This signal is emitted when the grab has changed in some way which is
+ relevant to this handler.
- This signal is emitted when this handler has acquired or relinquished a
- passive or exclusive grab of the given \a point.
+ The \a stateChange (verb) tells what happened.
+ The \a point (object) is the point that was grabbed or ungrabbed.
*/
/*!
@@ -430,4 +517,20 @@ void QQuickPointerHandler::handlePointerEventImpl(QQuickPointerEvent *event)
emitted when the grab is stolen by a different Pointer Handler or Item.
*/
+QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
+ : grabPermissions(QQuickPointerHandler::CanTakeOverFromItems |
+ QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType |
+ QQuickPointerHandler::ApprovesTakeOverByAnything)
+ , enabled(true)
+ , active(false)
+ , targetExplicitlySet(false)
+ , hadKeepMouseGrab(false)
+ , hadKeepTouchGrab(false)
+{
+}
+
+QQuickPointerHandlerPrivate::~QQuickPointerHandlerPrivate()
+{
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h
index e2bcce8fc9..9644bb959f 100644
--- a/src/quick/handlers/qquickpointerhandler_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p.h
@@ -51,8 +51,6 @@
// We mean it.
//
-#include "qevent.h"
-
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQuick/private/qquickitem_p.h>
@@ -60,6 +58,8 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcPointerHandlerDispatch)
+class QQuickPointerHandlerPrivate;
+
class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandler : public QObject, public QQmlParserStatus
{
Q_OBJECT
@@ -70,6 +70,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandler : public QObject, public QQmlP
Q_PROPERTY(QQuickItem * target READ target WRITE setTarget NOTIFY targetChanged)
Q_PROPERTY(QQuickItem * parent READ parentItem CONSTANT)
Q_PROPERTY(GrabPermissions grabPermissions READ grabPermissions WRITE setGrabPermissions NOTIFY grabPermissionChanged)
+ Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged)
public:
explicit QQuickPointerHandler(QObject *parent = nullptr);
@@ -91,35 +92,42 @@ public:
Q_FLAG(GrabPermissions)
public:
- bool enabled() const { return m_enabled; }
+ bool enabled() const;
void setEnabled(bool enabled);
- bool active() const { return m_active; }
+ bool active() const;
QQuickItem *target() const;
void setTarget(QQuickItem *target);
- QQuickItem * parentItem() const { return static_cast<QQuickItem *>(QObject::parent()); }
+ QQuickItem * parentItem() const;
void handlePointerEvent(QQuickPointerEvent *event);
- GrabPermissions grabPermissions() const { return static_cast<GrabPermissions>(m_grabPermissions); }
+ GrabPermissions grabPermissions() const;
void setGrabPermissions(GrabPermissions grabPermissions);
+ qreal margin() const;
+ void setMargin(qreal pointDistanceThreshold);
+
Q_SIGNALS:
void enabledChanged();
void activeChanged();
void targetChanged();
- void grabChanged(QQuickEventPoint *point);
+ void marginChanged();
+ void grabChanged(QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point);
void grabPermissionChanged();
void canceled(QQuickEventPoint *point);
protected:
+ QQuickPointerHandler(QQuickPointerHandlerPrivate &dd, QObject *parent);
+
void classBegin() override;
void componentComplete() override;
- QQuickPointerEvent *currentEvent() { return m_currentEvent; }
+ QQuickPointerEvent *currentEvent();
virtual bool wantsPointerEvent(QQuickPointerEvent *event);
+ virtual bool wantsEventPoint(QQuickEventPoint *point);
virtual void handlePointerEventImpl(QQuickPointerEvent *event);
void setActive(bool active);
virtual void onTargetChanged(QQuickItem *oldTarget) { Q_UNUSED(oldTarget); }
@@ -133,19 +141,11 @@ protected:
QPointF eventPos(const QQuickEventPoint *point) const;
bool parentContains(const QQuickEventPoint *point) const;
-private:
- QQuickPointerEvent *m_currentEvent;
- QQuickItem *m_target;
- bool m_enabled : 1;
- bool m_active : 1;
- bool m_targetExplicitlySet : 1;
- bool m_hadKeepMouseGrab : 1; // some handlers override target()->setKeepMouseGrab(); this remembers previous state
- bool m_hadKeepTouchGrab : 1; // some handlers override target()->setKeepTouchGrab(); this remembers previous state
- uint m_reserved : 19;
- uint8_t m_grabPermissions : 8;
-
friend class QQuickEventPoint;
+ friend class QQuickItemPrivate;
friend class QQuickWindowPrivate;
+
+ Q_DECLARE_PRIVATE(QQuickPointerHandler)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPointerHandler::GrabPermissions)
diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h
new file mode 100644
index 0000000000..c0b2b84a66
--- /dev/null
+++ b/src/quick/handlers/qquickpointerhandler_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOINTERHANDLER_P_H
+#define QQUICKPOINTERHANDLER_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 "qevent.h"
+
+#include <QtQuick/private/qquickevents_p_p.h>
+#include <QtQuick/private/qquickpointerhandler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandlerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickPointerHandler)
+
+public:
+ static QQuickPointerHandlerPrivate* get(QQuickPointerHandler *q) { return q->d_func(); }
+ static const QQuickPointerHandlerPrivate* get(const QQuickPointerHandler *q) { return q->d_func(); }
+
+ QQuickPointerHandlerPrivate();
+ virtual ~QQuickPointerHandlerPrivate() override;
+
+ QQuickPointerEvent *currentEvent = nullptr;
+ QQuickItem *target = nullptr;
+ qreal m_margin = 0;
+ uint8_t grabPermissions : 8;
+ bool enabled : 1;
+ bool active : 1;
+ bool targetExplicitlySet : 1;
+ bool hadKeepMouseGrab : 1; // some handlers override target()->setKeepMouseGrab(); this remembers previous state
+ bool hadKeepTouchGrab : 1; // some handlers override target()->setKeepTouchGrab(); this remembers previous state
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOINTERHANDLER_P_H
diff --git a/src/quick/handlers/qquickpointhandler.cpp b/src/quick/handlers/qquickpointhandler.cpp
index 7e2d40452c..7cf37969cc 100644
--- a/src/quick/handlers/qquickpointhandler.cpp
+++ b/src/quick/handlers/qquickpointhandler.cpp
@@ -97,7 +97,7 @@ QT_BEGIN_NAMESPACE
\snippet pointerHandlers/pointHandler.qml 0
- Like all pointer handlers, a PointHandler has a \l target property, which
+ Like all input handlers, a PointHandler has a \l target property, which
may be used as a convenient place to put a point-tracking Item; but
PointHandler will not automatically manipulate the \c target item in any way.
You need to use bindings to make it react to the \l point.
diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp
index 9df20390e4..71c05891d4 100644
--- a/src/quick/handlers/qquicksinglepointhandler.cpp
+++ b/src/quick/handlers/qquicksinglepointhandler.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -61,7 +61,6 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH_TARGET)
QQuickSinglePointHandler::QQuickSinglePointHandler(QObject *parent)
: QQuickPointerDeviceHandler(parent)
- , m_acceptedButtons(Qt::LeftButton)
, m_ignoreAdditionalPoints(false)
{
}
@@ -71,7 +70,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
if (!QQuickPointerDeviceHandler::wantsPointerEvent(event))
return false;
if (event->device()->pointerType() != QQuickPointerDevice::Finger &&
- (event->buttons() & m_acceptedButtons) == 0 && (event->button() & m_acceptedButtons) == 0)
+ (event->buttons() & acceptedButtons()) == 0 && (event->button() & acceptedButtons()) == 0)
return false;
if (m_pointInfo.m_id) {
@@ -79,16 +78,23 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
// It's expected to be an update or a release.
// If we no longer want it, cancel the grab.
int candidatePointCount = 0;
+ bool missing = true;
QQuickEventPoint *point = nullptr;
int c = event->pointCount();
for (int i = 0; i < c; ++i) {
QQuickEventPoint *p = event->point(i);
+ const bool found = (p->pointId() == m_pointInfo.m_id);
+ if (found)
+ missing = false;
if (wantsEventPoint(p)) {
++candidatePointCount;
- if (p->pointId() == m_pointInfo.m_id)
+ if (found)
point = p;
}
}
+ if (missing)
+ qCWarning(DBG_TOUCH_TARGET) << this << "pointId" << hex << m_pointInfo.m_id
+ << "is missing from current event, but was neither canceled nor released";
if (point) {
if (candidatePointCount == 1 || (candidatePointCount > 1 && m_ignoreAdditionalPoints)) {
point->setAccepted();
@@ -97,8 +103,6 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
point->cancelAllGrabs(this);
}
} else {
- qCWarning(DBG_TOUCH_TARGET) << this << "pointId" << hex << m_pointInfo.m_id
- << "is missing from current event, but was neither canceled nor released";
return false;
}
} else {
@@ -115,7 +119,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
}
}
if (chosen && candidatePointCount == 1) {
- m_pointInfo.m_id = chosen->pointId();
+ setPointId(chosen->pointId());
chosen->setAccepted();
}
}
@@ -130,48 +134,16 @@ void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
if (!m_pointInfo.m_id || !currentPoint->isAccepted()) {
reset();
} else {
- if (event->asPointerTouchEvent()) {
- QQuickEventTouchPoint *tp = static_cast<QQuickEventTouchPoint *>(currentPoint);
- m_pointInfo.m_uniqueId = tp->uniqueId();
- m_pointInfo.m_rotation = tp->rotation();
- m_pointInfo.m_pressure = tp->pressure();
- m_pointInfo.m_ellipseDiameters = tp->ellipseDiameters();
- } else if (event->asPointerTabletEvent()) {
- // TODO
- } else {
- m_pointInfo.m_uniqueId = event->device()->uniqueId();
- m_pointInfo.m_rotation = 0;
- m_pointInfo.m_pressure = event->buttons() ? 1 : 0;
- m_pointInfo.m_ellipseDiameters = QSizeF();
- }
- m_pointInfo.m_position = currentPoint->position();
- m_pointInfo.m_scenePosition = currentPoint->scenePosition();
- if (currentPoint->state() == QQuickEventPoint::Updated)
- m_pointInfo.m_velocity = currentPoint->velocity();
+ m_pointInfo.reset(currentPoint);
handleEventPoint(currentPoint);
- switch (currentPoint->state()) {
- case QQuickEventPoint::Pressed:
- m_pointInfo.m_pressPosition = currentPoint->position();
- m_pointInfo.m_scenePressPosition = currentPoint->scenePosition();
- m_pointInfo.m_pressedButtons = event->buttons();
- break;
- case QQuickEventPoint::Released:
+ if (currentPoint->state() == QQuickEventPoint::Released) {
setExclusiveGrab(currentPoint, false);
reset();
- break;
- default:
- m_pointInfo.m_pressedButtons = event->buttons();
- break;
}
emit pointChanged();
}
}
-bool QQuickSinglePointHandler::wantsEventPoint(QQuickEventPoint *point)
-{
- return parentContains(point);
-}
-
void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point)
{
if (grabber != this)
@@ -212,42 +184,9 @@ void QQuickSinglePointHandler::moveTarget(QPointF pos, QQuickEventPoint *point)
m_pointInfo.m_position = target()->mapFromScene(m_pointInfo.m_scenePosition);
}
-/*!
- \qmlproperty int QtQuick::SinglePointHandler::acceptedButtons
-
- The mouse buttons which can activate this Pointer Handler.
-
- By default, this property is set to \l {QtQuick::MouseEvent::button} {Qt.LeftButton}.
- It can be set to an OR combination of mouse buttons, and will ignore events
- from other buttons.
-
- For example, a control could be made to respond to left and right clicks
- in different ways, with two handlers:
-
- \qml
- Item {
- TapHandler {
- onTapped: console.log("left clicked")
- }
- TapHandler {
- acceptedButtons: Qt.RightButton
- onTapped: console.log("right clicked")
- }
- }
- \endqml
-
- \note Tapping on a touchscreen or tapping the stylus on a graphics tablet
- emulates clicking the left mouse button. This behavior can be altered via
- \l {PointerDeviceHandler::acceptedDevices}{acceptedDevices} or
- \l {PointerDeviceHandler::acceptedPointerTypes}{acceptedPointerTypes}.
-*/
-void QQuickSinglePointHandler::setAcceptedButtons(Qt::MouseButtons buttons)
+void QQuickSinglePointHandler::setPointId(int id)
{
- if (m_acceptedButtons == buttons)
- return;
-
- m_acceptedButtons = buttons;
- emit acceptedButtonsChanged();
+ m_pointInfo.m_id = id;
}
void QQuickSinglePointHandler::reset()
@@ -264,213 +203,4 @@ void QQuickSinglePointHandler::reset()
handled, this object is reset to default values (all coordinates are 0).
*/
-/*!
- \qmltype HandlerPoint
- \instantiates QQuickHandlerPoint
- \inqmlmodule Qt.labs.handlers
- \ingroup qtquick-handlers
- \brief An event point.
-
- A QML representation of a QQuickEventPoint.
-
- It's possible to make bindings to properties of a \l SinglePointHandler's
- current point. For example:
-
- \snippet pointerHandlers/dragHandlerNullTarget.qml 0
-
- The point is kept up-to-date when the DragHandler is actively responding to
- an EventPoint; but when the point is released, or the current point is
- being handled by a different handler, \c position.x and \c position.y are 0.
-
- \note This is practically identical to QtQuick::EventPoint; however an
- EventPoint is a long-lived QObject which is invalidated between gestures
- and reused for subsequent event deliveries. Continuous bindings to its
- properties are not possible, and an individual handler cannot rely on it
- outside the period when that point is part of an active gesture which that
- handler is handling. HandlerPoint is a Q_GADGET that the handler owns.
- This allows you to make lifetime bindings to its properties.
-
- \sa SinglePointHandler::point
-*/
-
-QQuickHandlerPoint::QQuickHandlerPoint()
- : m_id(0)
- , m_rotation(0)
- , m_pressure(0)
-{}
-
-void QQuickHandlerPoint::reset()
-{
- m_id = 0;
- m_uniqueId = QPointingDeviceUniqueId();
- m_position = QPointF();
- m_scenePosition = QPointF();
- m_pressPosition = QPointF();
- m_scenePressPosition = QPointF();
- m_sceneGrabPosition = QPointF();
- m_velocity = QVector2D();
- m_rotation = 0;
- m_pressure = 0;
- m_ellipseDiameters = QSizeF();
- m_pressedButtons = Qt::NoButton;
-}
-
-/*!
- \readonly
- \qmlproperty int QtQuick::HandlerPoint::id
- \brief The ID number of the point
-
- During a touch gesture, from the time that the first finger is pressed
- until the last finger is released, each touchpoint will have a unique ID
- number. Likewise, if input from multiple devices occurs (for example
- simultaneous mouse and touch presses), all the current event points from
- all the devices will have unique IDs.
-
- \note Do not assume that id numbers start at zero or that they are
- sequential. Such an assumption is often false due to the way the underlying
- drivers work.
-
- \sa QTouchEvent::TouchPoint::id
-*/
-
-/*!
- \readonly
- \qmlproperty PointingDeviceUniqueId QtQuick::HandlerPoint::uniqueId
- \brief The unique ID of the point, if any
-
- This is normally empty, because touchscreens cannot uniquely identify fingers.
-
- On some types of touchscreens, especially those using TUIO drivers,
- it's possible to use recognizable physical tokens (fiducial objects)
- in addition to fingers. So if this point is a touch point, and
- uniqueId is set, it is the identifier for such an object.
-
- On a graphics tablet, each type of stylus or other tool often has a unique
- ID or serial number, which can be useful to respond in different ways to
- different tools.
-
- Interpreting the contents of this ID requires knowledge of the hardware and
- drivers in use.
-
- \sa QTabletEvent::uniqueId, QtQuick::TouchPoint::uniqueId, QtQuick::EventTouchPoint::uniqueId
-*/
-
-/*!
- \readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::position
- \brief The position within the \c parent Item
-
- This is the position of the event point relative to the bounds of
- the \l {PointerHandler::parent} {parent}.
-*/
-
-/*!
- \readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::scenePosition
- \brief The position within the scene
-
- This is the position of the event point relative to the bounds of the Qt
- Quick scene (typically the whole window).
-*/
-
-/*!
- \readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::pressPosition
- \brief The pressed position within the \c parent Item
-
- This is the position at which this point was pressed, relative to the
- bounds of the \l {PointerHandler::parent} {parent}.
-*/
-
-/*!
- \readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::scenePressPosition
- \brief The pressed position within the scene
-
- This is the position at which this point was pressed, in the coordinate
- system of the \l {Qt Quick Scene Graph}{scene graph}.
-*/
-
-/*!
- \readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::sceneGrabPosition
- \brief The grabbed position within the scene
-
- If this point has been grabbed by a Pointer Handler or an Item, it means
- that object has taken sole responsibility for handling the movement and the
- release if this point. In that case, this is the position at which the grab
- occurred, in the coordinate system of the \l {Qt Quick Scene Graph}{scene graph}.
-*/
-
-/*!
- \readonly
- \qmlproperty enum QtQuick::HandlerPoint::pressedButtons
- \brief Which mouse or stylus buttons are currently pressed
-
- \sa MouseArea::pressedButtons
-*/
-
-/*!
- \readonly
- \qmlproperty QVector2D QtQuick::HandlerPoint::velocity
- \brief A vector representing the average speed and direction of movement
-
- This is a velocity vector pointing in the direction of movement, in logical
- pixels per second. It has x and y components, at least one of which will be
- nonzero when this point is in motion. It holds the average recent velocity:
- how fast and in which direction the event point has been moving recently.
-
- \sa QtQuick::EventPoint::velocity, QtQuick::TouchPoint::velocity, QTouchEvent::TouchPoint::velocity
-*/
-
-/*!
- \readonly
- \qmlproperty qreal QtQuick::HandlerPoint::rotation
-
- This property holds the rotation angle of the stylus on a graphics tablet
- or the contact patch of a touchpoint on a touchscreen.
-
- It is valid only with certain tablet stylus devices and touchscreens that
- can measure the rotation angle. Otherwise, it will be zero.
-*/
-
-/*!
- \readonly
- \qmlproperty qreal QtQuick::HandlerPoint::pressure
-
- This property tells how hard the user is pressing the stylus on a graphics
- tablet or the finger against a touchscreen, in the range from \c 0 (no
- measurable pressure) to \c 1.0 (maximum pressure which the device can
- measure).
-
- It is valid only with certain tablets and touchscreens that can measure
- pressure. Otherwise, it will be zero.
-*/
-
-/*!
- \readonly
- \qmlproperty size QtQuick::HandlerPoint::ellipseDiameters
-
- This property holds the diameters of the contact patch, if the event
- comes from a touchpoint and the device provides this information.
-
- A touchpoint is modeled as an elliptical area where the finger is pressed
- against the touchscreen. (In fact, it could also be modeled as a bitmap;
- but in that case we expect an elliptical bounding estimate to be fitted to
- the contact patch before the event is sent.) The harder the user presses,
- the larger the contact patch; so, these diameters provide an alternate way
- of detecting pressure, in case the device does not include a separate
- pressure sensor. The ellipse is centered on \l scenePosition (\l position
- in the PointerHandler's Item's local coordinates). The \l rotation property
- provides the rotation of the ellipse, if known. It is expected that if the
- \l rotation is zero, the \l {QSize::height}{height} is the larger dimension
- (the major axis), because of the usual hand position, reaching upward or
- outward across the surface.
-
- If the contact patch is unknown, or the device is not a touchscreen,
- these values will be zero.
-
- \sa QtQuick::EventTouchPoint::ellipseDiameters, QtQuick::TouchPoint::ellipseDiameters, QTouchEvent::TouchPoint::ellipseDiameters
-*/
-
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquicksinglepointhandler_p.h b/src/quick/handlers/qquicksinglepointhandler_p.h
index 7606b4f7ba..7c225aab46 100644
--- a/src/quick/handlers/qquicksinglepointhandler_p.h
+++ b/src/quick/handlers/qquicksinglepointhandler_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -51,82 +51,27 @@
// We mean it.
//
+#include "qquickhandlerpoint_p.h"
#include "qquickpointerdevicehandler_p.h"
QT_BEGIN_NAMESPACE
-class QQuickSinglePointHandler;
-
-class Q_QUICK_PRIVATE_EXPORT QQuickHandlerPoint {
- Q_GADGET
- Q_PROPERTY(int id READ id)
- Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId)
- Q_PROPERTY(QPointF position READ position)
- Q_PROPERTY(QPointF scenePosition READ scenePosition)
- Q_PROPERTY(QPointF pressPosition READ pressPosition)
- Q_PROPERTY(QPointF scenePressPosition READ scenePressPosition)
- Q_PROPERTY(QPointF sceneGrabPosition READ sceneGrabPosition)
- Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons)
- Q_PROPERTY(QVector2D velocity READ velocity)
- Q_PROPERTY(qreal rotation READ rotation)
- Q_PROPERTY(qreal pressure READ pressure)
- Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters)
-
-public:
- QQuickHandlerPoint();
-
- int id() const { return m_id; }
- Qt::MouseButtons pressedButtons() const { return m_pressedButtons; }
- QPointF pressPosition() const { return m_pressPosition; }
- QPointF scenePressPosition() const { return m_scenePressPosition; }
- QPointF sceneGrabPosition() const { return m_sceneGrabPosition; }
- QPointF position() const { return m_position; }
- QPointF scenePosition() const { return m_scenePosition; }
- QVector2D velocity() const { return m_velocity; }
- qreal rotation() const { return m_rotation; }
- qreal pressure() const { return m_pressure; }
- QSizeF ellipseDiameters() const { return m_ellipseDiameters; }
- QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; }
-
-private:
- void reset();
- int m_id;
- QPointingDeviceUniqueId m_uniqueId;
- Qt::MouseButtons m_pressedButtons;
- QPointF m_position;
- QPointF m_scenePosition;
- QPointF m_pressPosition;
- QPointF m_scenePressPosition;
- QPointF m_sceneGrabPosition;
- QVector2D m_velocity;
- qreal m_rotation;
- qreal m_pressure;
- QSizeF m_ellipseDiameters;
- friend class QQuickSinglePointHandler;
-};
-
class Q_QUICK_PRIVATE_EXPORT QQuickSinglePointHandler : public QQuickPointerDeviceHandler
{
Q_OBJECT
- Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
Q_PROPERTY(QQuickHandlerPoint point READ point NOTIFY pointChanged)
public:
explicit QQuickSinglePointHandler(QObject *parent = nullptr);
virtual ~QQuickSinglePointHandler() { }
- Qt::MouseButtons acceptedButtons() const { return m_acceptedButtons; }
- void setAcceptedButtons(Qt::MouseButtons buttons);
-
QQuickHandlerPoint point() const { return m_pointInfo; }
Q_SIGNALS:
void pointChanged();
void singlePointGrabChanged(); // QQuickPointerHandler::grabChanged signal can't be a property notifier here
- void acceptedButtonsChanged();
protected:
bool wantsPointerEvent(QQuickPointerEvent *event) override;
- virtual bool wantsEventPoint(QQuickEventPoint *point);
void handlePointerEventImpl(QQuickPointerEvent *event) override;
virtual void handleEventPoint(QQuickEventPoint *point) = 0;
@@ -137,18 +82,18 @@ protected:
void moveTarget(QPointF pos, QQuickEventPoint *point);
+ void setPointId(int id);
+
private:
void reset();
private:
QQuickHandlerPoint m_pointInfo;
- Qt::MouseButtons m_acceptedButtons;
bool m_ignoreAdditionalPoints : 1;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickHandlerPoint)
QML_DECLARE_TYPE(QQuickSinglePointHandler)
#endif // QQUICKPOINTERSINGLEHANDLER_H
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 902ff0df10..255059b9bd 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -65,7 +65,7 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
value is DragThreshold, which requires the press and release to be close
together in both space and time. In this case, DragHandler is able to
function using only a passive grab, and therefore does not interfere with
- event delivery to any other Items or Pointer Handlers. So the default
+ event delivery to any other Items or Input Handlers. So the default
gesturePolicy is useful when you want to modify behavior of an existing
control or Item by adding a TapHandler with bindings and/or JavaScript
callbacks.
@@ -107,7 +107,7 @@ QQuickTapHandler::~QQuickTapHandler()
{
}
-static bool dragOverThreshold(QQuickEventPoint *point)
+static bool dragOverThreshold(const QQuickEventPoint *point)
{
QPointF delta = point->scenePosition() - point->scenePressPosition();
return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) ||
@@ -237,7 +237,7 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
threshold (QStyleHints::startDragDistance), the tap gesture is
canceled, even if the button or finger is still pressed. This policy
can be useful whenever TapHandler needs to cooperate with other
- pointer handlers (for example \l DragHandler) or event-handling Items
+ input handlers (for example \l DragHandler) or event-handling Items
(for example QtQuick Controls), because in this case TapHandler
will not take the exclusive grab, but merely a passive grab.
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 2c115f4d3c..e4012941cd 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -563,6 +563,8 @@ struct QQuickJSContext2D : public QV4::Object
static QV4::ReturnedValue method_set_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
static QV4::ReturnedValue method_get_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
static QV4::ReturnedValue method_set_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
+ static QV4::ReturnedValue method_set_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
+ static QV4::ReturnedValue method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
static QV4::ReturnedValue method_get_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
static QV4::ReturnedValue method_set_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
@@ -596,7 +598,7 @@ public:
static QV4::Heap::QQuickJSContext2DPrototype *create(QV4::ExecutionEngine *engine)
{
QV4::Scope scope(engine);
- QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->allocObject<QQuickJSContext2DPrototype>());
+ QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->allocate<QQuickJSContext2DPrototype>());
o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0);
@@ -641,6 +643,8 @@ public:
o->defineDefaultProperty(QStringLiteral("createLinearGradient"), method_createLinearGradient, 0);
o->defineDefaultProperty(QStringLiteral("strokeRect"), method_strokeRect, 0);
o->defineDefaultProperty(QStringLiteral("closePath"), method_closePath, 0);
+ o->defineDefaultProperty(QStringLiteral("setLineDash"), method_setLineDash, 0);
+ o->defineDefaultProperty(QStringLiteral("getLineDash"), method_getLineDash, 0);
o->defineAccessorProperty(QStringLiteral("canvas"), QQuickJSContext2DPrototype::method_get_canvas, nullptr);
return o->d();
@@ -690,6 +694,8 @@ public:
static QV4::ReturnedValue method_createImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
static QV4::ReturnedValue method_getImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
static QV4::ReturnedValue method_putImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
+ static QV4::ReturnedValue method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
+ static QV4::ReturnedValue method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
};
@@ -908,8 +914,8 @@ struct QQuickJSContext2DPixelData : public QV4::Object
V4_OBJECT2(QQuickJSContext2DPixelData, QV4::Object)
V4_NEEDS_DESTROY
- static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty);
- static bool putIndexed(QV4::Managed *m, uint index, const QV4::Value &value);
+ static QV4::ReturnedValue virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty);
+ static bool virtualPut(QV4::Managed *m, QV4::PropertyKey id, const QV4::Value &value, Value *receiver);
static QV4::ReturnedValue proto_get_length(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
};
@@ -954,19 +960,19 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
{
QV4::Scope scope(v4);
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DPixelData>());
+ QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->allocate<QQuickJSContext2DPixelData>());
QV4::ScopedObject p(scope, ed->pixelArrayProto.value());
- pixelData->setPrototype(p);
+ pixelData->setPrototypeOf(p);
if (image.isNull()) {
*pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32);
pixelData->d()->image->fill(0x00000000);
} else {
- Q_ASSERT(image.width()== qRound(w * image.devicePixelRatio()) && image.height() == qRound(h * image.devicePixelRatio()));
+ Q_ASSERT(image.width()== qRound(w * image.devicePixelRatioF()) && image.height() == qRound(h * image.devicePixelRatioF()));
*pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
}
- QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DImageData>());
+ QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->allocate<QQuickJSContext2DImageData>());
imageData->d()->pixelData = pixelData.asReturnedValue();
return imageData.asReturnedValue();
}
@@ -1582,9 +1588,9 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(const
}
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocate<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
- gradient->setPrototype(p);
+ gradient->setPrototypeOf(p);
*gradient->d()->brush = QLinearGradient(x0, y0, x1, y1);
RETURN_RESULT(*gradient);
}
@@ -1634,9 +1640,9 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(const
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocate<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
- gradient->setPrototype(p);
+ gradient->setPrototypeOf(p);
*gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r1, QPointF(x0, y0), r0);
RETURN_RESULT(*gradient);
}
@@ -1678,9 +1684,9 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(cons
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocate<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
- gradient->setPrototype(p);
+ gradient->setPrototypeOf(p);
*gradient->d()->brush = QConicalGradient(x, y, angle);
RETURN_RESULT(*gradient);
}
@@ -1738,7 +1744,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(const QV4::F
CHECK_CONTEXT(r)
if (argc >= 2) {
- QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
+ QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->allocate<QQuickContext2DStyle>());
QColor color = scope.engine->toVariant(argv[0], qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
@@ -1963,6 +1969,122 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(const QV4::FunctionO
RETURN_UNDEFINED();
}
+/*!
+ \qmlmethod array QtQuick::Context2D::getLineDash()
+ \since QtQuick 2.11
+ Returns an array of qreals representing the dash pattern of the line.
+
+ \sa setLineDash()
+ */
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
+{
+ QV4::Scope scope(b);
+ QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
+ CHECK_CONTEXT(r)
+
+ const QVector<qreal> pattern = r->d()->context->state.lineDash;
+ QV4::ScopedArrayObject array(scope, scope.engine->newArrayObject(pattern.size()));
+ array->arrayReserve(pattern.size());
+ for (int i = 0; i < pattern.size(); i++)
+ array->put(i, QV4::Primitive::fromDouble(pattern[i]));
+
+ array->setArrayLengthUnchecked(pattern.size());
+
+ RETURN_RESULT(*array);
+}
+
+/*!
+ \qmlmethod QtQuick::Context2D::setLineDash(array pattern)
+ \since QtQuick 2.11
+ Sets the dash pattern to the given pattern
+
+ \a pattern a list of numbers that specifies distances to alternately draw a line and a gap.
+
+ If the number of elements in the array is odd, the elements of the array get copied
+ and concatenated. For example, [5, 15, 25] will become [5, 15, 25, 5, 15, 25].
+
+ \table 100%
+ \row
+ \li \inlineimage qml-item-canvas-lineDash.png
+ \li
+ \code
+ var space = 4
+ ctx.setLineDash([1, space, 3, space, 9, space, 27, space, 9, space])
+ ...
+ ctx.stroke();
+ \endcode
+ \endtable
+
+ \sa setLineDash
+ */
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
+{
+ QV4::Scope scope(b);
+ QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
+ CHECK_CONTEXT_SETTER(r)
+
+ if (!argc)
+ RETURN_UNDEFINED();
+
+ QV4::ScopedArrayObject array(scope, argv[0]);
+ if (!array)
+ RETURN_UNDEFINED();
+
+ QV4::ScopedValue v(scope);
+ const uint arrayLength = array->getLength();
+ QVector<qreal> dashes;
+ dashes.reserve(arrayLength);
+ for (uint i = 0; i < arrayLength; ++i) {
+ v = array->get(i);
+ const double number = v->toNumber();
+
+ if (!qt_is_finite(number) || (number < 0))
+ RETURN_UNDEFINED();
+
+ dashes.append(v->toNumber());
+ }
+ if (dashes.size() % 2 != 0) {
+ dashes += dashes;
+ }
+
+ r->d()->context->state.lineDash = dashes;
+ r->d()->context->buffer()->setLineDash(dashes);
+
+ RETURN_UNDEFINED();
+}
+
+/*!
+ \qmlproperty real QtQuick::Context2D::lineDashOffset
+ \since QtQuick 2.11
+
+ Holds the current line dash offset
+ The default line dash ofset value is 0
+ */
+QV4::ReturnedValue QQuickJSContext2D::method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
+{
+ QV4::Scope scope(b);
+ QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
+ CHECK_CONTEXT(r)
+
+ RETURN_RESULT(QV4::Encode(r->d()->context->state.lineDashOffset));
+}
+
+QV4::ReturnedValue QQuickJSContext2D::method_set_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
+{
+ QV4::Scope scope(b);
+ QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
+ CHECK_CONTEXT_SETTER(r)
+
+ const qreal offset = argc ? argv[0].toNumber() : -1;
+
+ if (qt_is_finite(offset) && offset != r->d()->context->state.lineDashOffset) {
+ r->d()->context->state.lineDashOffset = offset;
+ r->d()->context->buffer()->setLineDashOffset(offset);
+ }
+ RETURN_UNDEFINED();
+}
+
+
// shadows
/*!
\qmlproperty real QtQuick::Context2D::shadowBlur
@@ -3130,8 +3252,12 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(const QV4::Funct
RETURN_RESULT(QV4::Encode(r->d()->image->width() * r->d()->image->height() * 4));
}
-QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
+QV4::ReturnedValue QQuickJSContext2DPixelData::virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty)
{
+ if (!id.isArrayIndex())
+ return QV4::Object::virtualGet(m, id, receiver, hasProperty);
+
+ uint index = id.asArrayIndex();
Q_ASSERT(m->as<QQuickJSContext2DPixelData>());
QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine();
QV4::Scope scope(v4);
@@ -3156,19 +3282,24 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m,
return QV4::Encode(qAlpha(*pixel));
}
}
+
if (hasProperty)
*hasProperty = false;
return QV4::Encode::undefined();
}
-bool QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const QV4::Value &value)
+bool QQuickJSContext2DPixelData::virtualPut(QV4::Managed *m, QV4::PropertyKey id, const QV4::Value &value, QV4::Value *receiver)
{
+ if (!id.isArrayIndex())
+ return Object::virtualPut(m, id, value, receiver);
+
Q_ASSERT(m->as<QQuickJSContext2DPixelData>());
QV4::ExecutionEngine *v4 = static_cast<QQuickJSContext2DPixelData *>(m)->engine();
QV4::Scope scope(v4);
if (scope.hasException())
return false;
+ uint index = id.asArrayIndex();
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m));
const int v = value.toInt32();
@@ -4303,6 +4434,7 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV4::ExecutionEngine *v4)
proto->defineAccessorProperty(QStringLiteral("lineWidth"), QQuickJSContext2D::method_get_lineWidth, QQuickJSContext2D::method_set_lineWidth);
proto->defineAccessorProperty(QStringLiteral("textAlign"), QQuickJSContext2D::method_get_textAlign, QQuickJSContext2D::method_set_textAlign);
proto->defineAccessorProperty(QStringLiteral("shadowBlur"), QQuickJSContext2D::method_get_shadowBlur, QQuickJSContext2D::method_set_shadowBlur);
+ proto->defineAccessorProperty(QStringLiteral("lineDashOffset"), QQuickJSContext2D::method_get_lineDashOffset, QQuickJSContext2D::method_set_lineDashOffset);
contextPrototype = proto;
proto = scope.engine->newObject();
@@ -4366,6 +4498,10 @@ void QQuickContext2D::popState()
if (newState.shadowOffsetY != state.shadowOffsetY)
buffer()->setShadowOffsetY(newState.shadowOffsetY);
+
+ if (newState.lineDash != state.lineDash)
+ buffer()->setLineDash(newState.lineDash);
+
m_path = state.matrix.map(m_path);
state = newState;
m_path = state.matrix.inverted().map(m_path);
@@ -4399,9 +4535,9 @@ void QQuickContext2D::setV4Engine(QV4::ExecutionEngine *engine)
QQuickContext2DEngineData *ed = engineData(engine);
QV4::Scope scope(engine);
- QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocObject<QQuickJSContext2D>());
+ QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocate<QQuickJSContext2D>());
QV4::ScopedObject p(scope, ed->contextPrototype.value());
- wrapper->setPrototype(p);
+ wrapper->setPrototypeOf(p);
wrapper->d()->context = this;
m_v4value = wrapper;
}
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 4cc07027b1..1ece6796f3 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -112,6 +112,8 @@ public:
LineWidth,
LineCap,
LineJoin,
+ LineDash,
+ LineDashOffset,
MiterLimit,
ShadowOffsetX,
ShadowOffsetY,
@@ -142,6 +144,7 @@ public:
, lineWidth(1)
, lineCap(Qt::FlatCap)
, lineJoin(Qt::MiterJoin)
+ , lineDashOffset(0)
, miterLimit(10)
, shadowOffsetX(0)
, shadowOffsetY(0)
@@ -170,6 +173,8 @@ public:
qreal lineWidth;
Qt::PenCapStyle lineCap;
Qt::PenJoinStyle lineJoin;
+ QVector<qreal> lineDash;
+ qreal lineDashOffset;
qreal miterLimit;
qreal shadowOffsetX;
qreal shadowOffsetY;
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 30895d9b0e..55ebbe907c 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -192,6 +192,10 @@ QPen QQuickContext2DCommandBuffer::makePen(const QQuickContext2D::State& state)
pen.setJoinStyle(state.lineJoin);
pen.setMiterLimit(state.miterLimit);
pen.setBrush(state.strokeStyle);
+ if (!state.lineDash.isEmpty()) {
+ pen.setDashPattern(state.lineDash);
+ }
+ pen.setDashOffset(state.lineDashOffset);
return pen;
}
@@ -361,6 +365,28 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
p->setPen(nPen);
break;
}
+ case QQuickContext2D::LineDash:
+ {
+ const qreal count = takeReal();
+ QVector<qreal> pattern;
+ pattern.reserve(count);
+ for (uint i = 0; i < count; i++) {
+ pattern.append(takeReal());
+ }
+ state.lineDash = pattern;
+ QPen nPen = p->pen();
+ nPen.setDashPattern(pattern);
+ p->setPen(nPen);
+ break;
+ }
+ case QQuickContext2D::LineDashOffset:
+ {
+ state.lineDashOffset = takeReal();
+ QPen nPen = p->pen();
+ nPen.setDashOffset(state.lineDashOffset);
+ p->setPen(nPen);
+ break;
+ }
case QQuickContext2D::MiterLimit:
{
state.miterLimit = takeMiterLimit();
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index 2a1ac7304e..c3e844c929 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -201,6 +201,20 @@ public:
ints << join;
}
+ inline void setLineDash(const QVector<qreal> &pattern)
+ {
+ commands << QQuickContext2D::LineDash;
+ reals << pattern.length();
+ for (qreal r : pattern)
+ reals << r;
+ }
+
+ inline void setLineDashOffset( qreal offset)
+ {
+ commands << QQuickContext2D::LineDashOffset;
+ reals << offset;
+ }
+
inline void setMiterLimit( qreal limit)
{
commands << QQuickContext2D::MiterLimit;
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index 1acb3b5265..e649b5429d 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -122,9 +122,11 @@ qtConfig(quick-gridview) {
qtConfig(quick-itemview) {
HEADERS += \
+ $$PWD/qquickitemviewfxitem_p_p.h \
$$PWD/qquickitemview_p.h \
$$PWD/qquickitemview_p_p.h
SOURCES += \
+ $$PWD/qquickitemviewfxitem.cpp \
$$PWD/qquickitemview.cpp
}
@@ -142,6 +144,14 @@ qtConfig(quick-listview) {
$$PWD/qquicklistview.cpp
}
+qtConfig(quick-tableview) {
+ HEADERS += \
+ $$PWD/qquicktableview_p.h \
+ $$PWD/qquicktableview_p_p.h
+ SOURCES += \
+ $$PWD/qquicktableview.cpp
+}
+
qtConfig(quick-pathview) {
HEADERS += \
$$PWD/qquickpathview_p.h \
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 603d5a3120..18adb4e992 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -268,6 +268,16 @@ QT_BEGIN_NAMESPACE
Stops, then starts the sprite animation.
*/
+/*!
+ \qmlsignal QtQuick::AnimatedSprite::finished()
+ \since 5.12
+
+ This signal is emitted when the sprite has finished animating.
+
+ It is not emitted when running is set to \c false, nor for sprites whose
+ \l loops property is set to \c AnimatedSprite.Infinite.
+*/
+
QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) :
QQuickItem(*(new QQuickAnimatedSpritePrivate), parent)
{
@@ -806,6 +816,7 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node)
frameAt = 0;
d->m_running = false;
emit runningChanged(false);
+ emit finished();
maybeUpdate();
}
} else {
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index d7e60b909c..ff59591c9f 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -135,6 +135,8 @@ Q_SIGNALS:
void loopsChanged(int arg);
void currentFrameChanged(int arg);
+ Q_REVISION(12) void finished();
+
public Q_SLOTS:
void start();
void stop();
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index d4aba31e28..31c56b7cb7 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -642,6 +642,11 @@ QQuickPointerDevice *QQuickPointerDevice::touchDevice(const QTouchDevice *d)
return dev;
}
+const QTouchDevice *QQuickPointerDevice::qTouchDevice() const
+{
+ return g_touchDevices->key(const_cast<QQuickPointerDevice *>(this));
+}
+
QList<QQuickPointerDevice*> QQuickPointerDevice::touchDevices()
{
return g_touchDevices->values();
@@ -901,7 +906,7 @@ void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, b
if (grabber) {
grabber->onGrabChanged(grabber, GrabExclusive, this);
for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers) {
- if (passiveGrabber != grabber)
+ if (!passiveGrabber.isNull() && passiveGrabber != grabber)
passiveGrabber->onGrabChanged(grabber, OverrideGrabPassive, this);
}
}
@@ -1291,7 +1296,7 @@ QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event)
Qt::TouchPointState state = Qt::TouchPointStationary;
switch (ev->type()) {
case QEvent::MouseButtonPress:
- m_mousePoint->clearPassiveGrabbers();
+ m_point->clearPassiveGrabbers();
Q_FALLTHROUGH();
case QEvent::MouseButtonDblClick:
state = Qt::TouchPointPressed;
@@ -1305,13 +1310,13 @@ QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event)
default:
break;
}
- m_mousePoint->reset(state, ev->windowPos(), quint64(1) << 24, ev->timestamp()); // mouse has device ID 1
+ m_point->reset(state, ev->windowPos(), quint64(1) << 24, ev->timestamp()); // mouse has device ID 1
return this;
}
-void QQuickPointerMouseEvent::localize(QQuickItem *target)
+void QQuickSinglePointEvent::localize(QQuickItem *target)
{
- m_mousePoint->localizePosition(target);
+ m_point->localizePosition(target);
}
QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
@@ -1412,35 +1417,54 @@ QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event)
break;
}
quint64 deviceId = QTouchDevicePrivate::get(const_cast<QTouchDevice *>(ev->device()))->id; // a bit roundabout since QTouchDevice::mTouchDeviceId is protected
- m_gesturePoint->reset(state, ev->windowPos(), deviceId << 24, ev->timestamp());
+ m_point->reset(state, ev->windowPos(), deviceId << 24, ev->timestamp());
return this;
}
-
-void QQuickPointerNativeGestureEvent::localize(QQuickItem *target)
-{
- m_gesturePoint->localizePosition(target);
-}
#endif // QT_CONFIG(gestures)
-QQuickEventPoint *QQuickPointerMouseEvent::point(int i) const {
+QQuickEventPoint *QQuickSinglePointEvent::point(int i) const
+{
if (i == 0)
- return m_mousePoint;
+ return m_point;
return nullptr;
}
-QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const {
- if (i >= 0 && i < m_pointCount)
- return m_touchPoints.at(i);
- return nullptr;
+QQuickPointerEvent *QQuickPointerScrollEvent::reset(QEvent *event)
+{
+ m_event = static_cast<QInputEvent*>(event);
+ if (!event)
+ return this;
+#if QT_CONFIG(wheelevent)
+ if (event->type() == QEvent::Wheel) {
+ auto ev = static_cast<QWheelEvent*>(event);
+ m_device = QQuickPointerDevice::genericMouseDevice();
+ m_device->eventDeliveryTargets().clear();
+ // m_button = Qt::NoButton;
+ m_pressedButtons = ev->buttons();
+ m_angleDelta = QVector2D(ev->angleDelta());
+ m_pixelDelta = QVector2D(ev->pixelDelta());
+ m_phase = ev->phase();
+ m_synthSource = ev->source();
+ m_inverted = ev->inverted();
+
+ m_point->reset(Qt::TouchPointMoved, ev->posF(), quint64(1) << 24, ev->timestamp()); // mouse has device ID 1
+ }
+#endif
+ // TODO else if (event->type() == QEvent::Scroll) ...
+ return this;
}
-#if QT_CONFIG(gestures)
-QQuickEventPoint *QQuickPointerNativeGestureEvent::point(int i) const {
- if (i == 0)
- return m_gesturePoint;
+void QQuickPointerScrollEvent::localize(QQuickItem *target)
+{
+ m_point->localizePosition(target);
+}
+
+QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const
+{
+ if (i >= 0 && i < m_pointCount)
+ return m_touchPoints.at(i);
return nullptr;
}
-#endif // QT_CONFIG(gestures)
QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent)
: QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0),
@@ -1454,17 +1478,19 @@ QQuickPointerEvent *QQuickEventPoint::pointerEvent() const
return static_cast<QQuickPointerEvent *>(parent());
}
-bool QQuickPointerMouseEvent::allPointsAccepted() const {
- return m_mousePoint->isAccepted();
+bool QQuickSinglePointEvent::allPointsAccepted() const
+{
+ return m_point->isAccepted();
}
-bool QQuickPointerMouseEvent::allUpdatedPointsAccepted() const {
- return m_mousePoint->state() == QQuickEventPoint::Pressed || m_mousePoint->isAccepted();
+bool QQuickSinglePointEvent::allUpdatedPointsAccepted() const
+{
+ return m_point->state() == QQuickEventPoint::Pressed || m_point->isAccepted();
}
-bool QQuickPointerMouseEvent::allPointsGrabbed() const
+bool QQuickSinglePointEvent::allPointsGrabbed() const
{
- return m_mousePoint->exclusiveGrabber() != nullptr;
+ return m_point->exclusiveGrabber() != nullptr;
}
QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const
@@ -1477,10 +1503,10 @@ QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) cons
/*!
Returns the exclusive grabber of this event, if any, in a vector.
*/
-QVector<QObject *> QQuickPointerMouseEvent::exclusiveGrabbers() const
+QVector<QObject *> QQuickSinglePointEvent::exclusiveGrabbers() const
{
QVector<QObject *> result;
- if (QObject *grabber = m_mousePoint->exclusiveGrabber())
+ if (QObject *grabber = m_point->exclusiveGrabber())
result << grabber;
return result;
}
@@ -1488,17 +1514,18 @@ QVector<QObject *> QQuickPointerMouseEvent::exclusiveGrabbers() const
/*!
Remove all passive and exclusive grabbers of this event, without notifying.
*/
-void QQuickPointerMouseEvent::clearGrabbers() const {
- m_mousePoint->setGrabberItem(nullptr);
- m_mousePoint->clearPassiveGrabbers();
+void QQuickSinglePointEvent::clearGrabbers() const
+{
+ m_point->setGrabberItem(nullptr);
+ m_point->clearPassiveGrabbers();
}
/*!
Returns whether the given \a handler is the exclusive grabber of this event.
*/
-bool QQuickPointerMouseEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
+bool QQuickSinglePointEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
{
- return m_mousePoint->exclusiveGrabber() == handler;
+ return handler && (m_point->exclusiveGrabber() == handler);
}
bool QQuickPointerMouseEvent::isPressEvent() const
@@ -1526,7 +1553,8 @@ bool QQuickPointerMouseEvent::isReleaseEvent() const
return me && me->type() == QEvent::MouseButtonRelease;
}
-bool QQuickPointerTouchEvent::allPointsAccepted() const {
+bool QQuickPointerTouchEvent::allPointsAccepted() const
+{
for (int i = 0; i < m_pointCount; ++i) {
if (!m_touchPoints.at(i)->isAccepted())
return false;
@@ -1534,7 +1562,8 @@ bool QQuickPointerTouchEvent::allPointsAccepted() const {
return true;
}
-bool QQuickPointerTouchEvent::allUpdatedPointsAccepted() const {
+bool QQuickPointerTouchEvent::allUpdatedPointsAccepted() const
+{
for (int i = 0; i < m_pointCount; ++i) {
auto point = m_touchPoints.at(i);
if (point->state() != QQuickEventPoint::Pressed && !point->isAccepted())
@@ -1571,7 +1600,8 @@ QVector<QObject *> QQuickPointerTouchEvent::exclusiveGrabbers() const
Remove all passive and exclusive grabbers of all touchpoints in this event,
without notifying.
*/
-void QQuickPointerTouchEvent::clearGrabbers() const {
+void QQuickPointerTouchEvent::clearGrabbers() const
+{
for (auto point: m_touchPoints) {
point->setGrabberItem(nullptr);
point->clearPassiveGrabbers();
@@ -1629,7 +1659,8 @@ QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() cons
If the touchpoint cannot be found, this returns nullptr.
Ownership of the event is NOT transferred to the caller.
*/
-QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const {
+QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const
+{
const QTouchEvent::TouchPoint *p = touchPointById(pointID);
if (!p)
return nullptr;
@@ -1669,33 +1700,6 @@ QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickIte
}
#if QT_CONFIG(gestures)
-/*!
- Returns the exclusive grabber of this event, if any, in a vector.
-*/
-QVector<QObject *> QQuickPointerNativeGestureEvent::exclusiveGrabbers() const
-{
- QVector<QObject *> result;
- if (QObject *grabber = m_gesturePoint->exclusiveGrabber())
- result << grabber;
- return result;
-}
-
-/*!
- Remove all passive and exclusive grabbers of this event, without notifying.
-*/
-void QQuickPointerNativeGestureEvent::clearGrabbers() const {
- m_gesturePoint->setGrabberItem(nullptr);
- m_gesturePoint->clearPassiveGrabbers();
-}
-
-/*!
- Returns whether the given \a handler is the exclusive grabber of this event.
-*/
-bool QQuickPointerNativeGestureEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
-{
- return m_gesturePoint->exclusiveGrabber() == handler;
-}
-
bool QQuickPointerNativeGestureEvent::isPressEvent() const
{
return type() == Qt::BeginNativeGesture;
@@ -1729,6 +1733,39 @@ qreal QQuickPointerNativeGestureEvent::value() const
#endif // QT_CONFIG(gestures)
/*!
+ Returns whether the scroll event has Qt::ScrollBegin phase. On touchpads
+ which provide phase information, this is true when the fingers are placed
+ on the touchpad and scrolling begins. On other devices where this
+ information is not available, it remains false.
+*/
+bool QQuickPointerScrollEvent::isPressEvent() const
+{
+ return phase() == Qt::ScrollBegin;
+}
+
+/*!
+ Returns true when the scroll event has Qt::ScrollUpdate phase, or when the
+ phase is unknown. Some multi-touch-capable touchpads and trackpads provide
+ phase information; whereas ordinary mouse wheels and other types of
+ trackpads do not, and in such cases this is always true.
+*/
+bool QQuickPointerScrollEvent::isUpdateEvent() const
+{
+ return phase() == Qt::ScrollUpdate || phase() == Qt::NoScrollPhase;
+}
+
+/*!
+ Returns whether the scroll event has Qt::ScrollBegin phase. On touchpads
+ which provide phase information, this is true when the fingers are lifted
+ from the touchpad. On other devices where this information is not
+ available, it remains false.
+*/
+bool QQuickPointerScrollEvent::isReleaseEvent() const
+{
+ return phase() == Qt::ScrollEnd;
+}
+
+/*!
\internal
Returns a pointer to the QQuickEventPoint which has the \a pointId as
\l {QQuickEventPoint::pointId}{pointId}.
@@ -1736,13 +1773,15 @@ qreal QQuickPointerNativeGestureEvent::value() const
\fn QQuickPointerEvent::pointById(int pointId) const
*/
-QQuickEventPoint *QQuickPointerMouseEvent::pointById(int pointId) const {
- if (m_mousePoint && pointId == m_mousePoint->pointId())
- return m_mousePoint;
+QQuickEventPoint *QQuickSinglePointEvent::pointById(int pointId) const
+{
+ if (m_point && pointId == m_point->pointId())
+ return m_point;
return nullptr;
}
-QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const {
+QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const
+{
auto it = std::find_if(m_touchPoints.constBegin(), m_touchPoints.constEnd(),
[pointId](const QQuickEventTouchPoint *tp) { return tp->pointId() == pointId; } );
if (it != m_touchPoints.constEnd())
@@ -1750,21 +1789,14 @@ QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const {
return nullptr;
}
-#if QT_CONFIG(gestures)
-QQuickEventPoint *QQuickPointerNativeGestureEvent::pointById(int pointId) const {
- if (m_gesturePoint && pointId == m_gesturePoint->pointId())
- return m_gesturePoint;
- return nullptr;
-}
-#endif
-
/*!
\internal
Returns a pointer to the original TouchPoint which has the same
\l {QTouchEvent::TouchPoint::id}{id} as \a pointId, if the original event is a
QTouchEvent, and if that point is found. Otherwise, returns nullptr.
*/
-const QTouchEvent::TouchPoint *QQuickPointerTouchEvent::touchPointById(int pointId) const {
+const QTouchEvent::TouchPoint *QQuickPointerTouchEvent::touchPointById(int pointId) const
+{
const QTouchEvent *ev = asTouchEvent();
if (!ev)
return nullptr;
@@ -1875,24 +1907,10 @@ QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const
return static_cast<QTouchEvent *>(m_event);
}
-#if QT_CONFIG(gestures)
-bool QQuickPointerNativeGestureEvent::allPointsAccepted() const {
- return m_gesturePoint->isAccepted();
-}
-
-bool QQuickPointerNativeGestureEvent::allUpdatedPointsAccepted() const {
- return m_gesturePoint->state() == QQuickEventPoint::Pressed || m_gesturePoint->isAccepted();
-}
-
-bool QQuickPointerNativeGestureEvent::allPointsGrabbed() const
-{
- return m_gesturePoint->exclusiveGrabber() != nullptr;
-}
-#endif // QT_CONFIG(gestures)
-
#ifndef QT_NO_DEBUG_STREAM
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerDevice *dev) {
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerDevice *dev)
+{
QDebugStateSaver saver(dbg);
dbg.nospace();
if (!dev) {
@@ -1914,7 +1932,8 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerDevice *
return dbg;
}
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *event) {
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *event)
+{
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QQuickPointerEvent(";
@@ -1933,7 +1952,8 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *e
return dbg;
}
-Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *event) {
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *event)
+{
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QQuickEventPoint(accepted:" << event->isAccepted()
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index bb6726706d..c67c386676 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -69,6 +69,7 @@ class QQuickPointerMouseEvent;
#if QT_CONFIG(gestures)
class QQuickPointerNativeGestureEvent;
#endif
+class QQuickPointerScrollEvent;
class QQuickPointerTabletEvent;
class QQuickPointerTouchEvent;
class QQuickPointerHandler;
@@ -419,17 +420,19 @@ public: // helpers for C++ only (during event delivery)
#if QT_CONFIG(gestures)
virtual QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() { return nullptr; }
#endif
+ virtual QQuickPointerScrollEvent *asPointerScrollEvent() { return nullptr; }
virtual const QQuickPointerMouseEvent *asPointerMouseEvent() const { return nullptr; }
virtual const QQuickPointerTouchEvent *asPointerTouchEvent() const { return nullptr; }
virtual const QQuickPointerTabletEvent *asPointerTabletEvent() const { return nullptr; }
#if QT_CONFIG(gestures)
virtual const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const { return nullptr; }
#endif
+ virtual const QQuickPointerScrollEvent *asPointerScrollEvent() const { return nullptr; }
virtual bool allPointsAccepted() const = 0;
virtual bool allUpdatedPointsAccepted() const = 0;
virtual bool allPointsGrabbed() const = 0;
- bool isAccepted() { return m_event->isAccepted(); }
- void setAccepted(bool accepted) { m_event->setAccepted(accepted); }
+ bool isAccepted() { return m_event ? m_event->isAccepted() : false; }
+ void setAccepted(bool accepted) { if (m_event) m_event->setAccepted(accepted); }
QVector<QPointF> unacceptedPressedPointScenePositions() const;
virtual int pointCount() const = 0;
@@ -439,7 +442,7 @@ public: // helpers for C++ only (during event delivery)
virtual void clearGrabbers() const = 0;
virtual bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const = 0;
- ulong timestamp() const { return m_event->timestamp(); }
+ ulong timestamp() const { return m_event ? m_event->timestamp() : 0; }
protected:
QQuickPointerDevice *m_device;
@@ -450,21 +453,14 @@ protected:
Q_DISABLE_COPY(QQuickPointerEvent)
};
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickPointerEvent
+class Q_QUICK_PRIVATE_EXPORT QQuickSinglePointEvent : public QQuickPointerEvent
{
Q_OBJECT
public:
- QQuickPointerMouseEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
- : QQuickPointerEvent(parent, device), m_mousePoint(new QQuickEventPoint(this)) { }
+ QQuickSinglePointEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
+ : QQuickPointerEvent(parent, device), m_point(new QQuickEventPoint(this)) { }
- QQuickPointerEvent *reset(QEvent *) override;
void localize(QQuickItem *target) override;
- bool isPressEvent() const override;
- bool isDoubleClickEvent() const override;
- bool isUpdateEvent() const override;
- bool isReleaseEvent() const override;
- QQuickPointerMouseEvent *asPointerMouseEvent() override { return this; }
- const QQuickPointerMouseEvent *asPointerMouseEvent() const override { return this; }
int pointCount() const override { return 1; }
QQuickEventPoint *point(int i) const override;
QQuickEventPoint *pointById(int pointId) const override;
@@ -475,10 +471,28 @@ public:
void clearGrabbers() const override;
bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override;
- QMouseEvent *asMouseEvent(const QPointF& localPos) const;
+protected:
+ QQuickEventPoint *m_point;
-private:
- QQuickEventPoint *m_mousePoint;
+ Q_DISABLE_COPY(QQuickSinglePointEvent)
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickSinglePointEvent
+{
+ Q_OBJECT
+public:
+ QQuickPointerMouseEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
+ : QQuickSinglePointEvent(parent, device) { }
+
+ QQuickPointerEvent *reset(QEvent *) override;
+ bool isPressEvent() const override;
+ bool isDoubleClickEvent() const override;
+ bool isUpdateEvent() const override;
+ bool isReleaseEvent() const override;
+ QQuickPointerMouseEvent *asPointerMouseEvent() override { return this; }
+ const QQuickPointerMouseEvent *asPointerMouseEvent() const override { return this; }
+
+ QMouseEvent *asMouseEvent(const QPointF& localPos) const;
Q_DISABLE_COPY(QQuickPointerMouseEvent)
};
@@ -526,7 +540,7 @@ private:
};
#if QT_CONFIG(gestures)
-class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickPointerEvent
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickSinglePointEvent
{
Q_OBJECT
Q_PROPERTY(Qt::NativeGestureType type READ type CONSTANT)
@@ -534,34 +548,65 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickPoin
public:
QQuickPointerNativeGestureEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
- : QQuickPointerEvent(parent, device), m_gesturePoint(new QQuickEventPoint(this)) { }
+ : QQuickSinglePointEvent(parent, device) { }
QQuickPointerEvent *reset(QEvent *) override;
- void localize(QQuickItem *target) override;
bool isPressEvent() const override;
bool isUpdateEvent() const override;
bool isReleaseEvent() const override;
QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() override { return this; }
const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const override { return this; }
- int pointCount() const override { return 1; }
- QQuickEventPoint *point(int i) const override;
- QQuickEventPoint *pointById(int pointId) const override;
- bool allPointsAccepted() const override;
- bool allUpdatedPointsAccepted() const override;
- bool allPointsGrabbed() const override;
- QVector<QObject *> exclusiveGrabbers() const override;
- void clearGrabbers() const override;
- bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override;
Qt::NativeGestureType type() const;
qreal value() const;
-private:
- QQuickEventPoint *m_gesturePoint;
-
Q_DISABLE_COPY(QQuickPointerNativeGestureEvent)
};
#endif // QT_CONFIG(gestures)
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerScrollEvent : public QQuickSinglePointEvent
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector2D angleDelta READ angleDelta CONSTANT)
+ Q_PROPERTY(QVector2D pixelDelta READ pixelDelta CONSTANT)
+ Q_PROPERTY(bool hasAngleDelta READ hasAngleDelta CONSTANT)
+ Q_PROPERTY(bool hasPixelDelta READ hasPixelDelta CONSTANT)
+ Q_PROPERTY(bool inverted READ isInverted CONSTANT)
+
+public:
+ QQuickPointerScrollEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
+ : QQuickSinglePointEvent(parent, device) { }
+
+ QQuickPointerEvent *reset(QEvent *) override;
+ void localize(QQuickItem *target) override;
+ bool isPressEvent() const override;
+ bool isUpdateEvent() const override;
+ bool isReleaseEvent() const override;
+ QQuickPointerScrollEvent *asPointerScrollEvent() override { return this; }
+ const QQuickPointerScrollEvent *asPointerScrollEvent() const override { return this; }
+ QVector2D angleDelta() const { return m_angleDelta; }
+ QVector2D pixelDelta() const { return m_pixelDelta; }
+ bool hasAngleDelta() const { return !angleDelta().isNull(); }
+ bool hasPixelDelta() const { return !pixelDelta().isNull(); }
+ bool isInverted() const { return m_inverted; }
+ Qt::ScrollPhase phase() const { return m_phase; }
+
+private:
+ // TODO add QQuickPointerDevice source() whenever QInputEvent is extended to have a source device
+ // then maybe Qt::MouseEventSource synthSource() will be obsolete... that's why it's not public now
+ Qt::MouseEventSource synthSource() const { return m_synthSource; }
+
+private:
+ QVector2D m_angleDelta;
+ QVector2D m_pixelDelta;
+ Qt::ScrollPhase m_phase = Qt::NoScrollPhase;
+ Qt::MouseEventSource m_synthSource = Qt::MouseEventNotSynthesized;
+ bool m_inverted = false;
+
+ friend class QQuickWindowPrivate;
+
+ Q_DISABLE_COPY(QQuickPointerScrollEvent)
+};
+
// ### Qt 6: move this to qtbase, replace QTouchDevice and the enums in QTabletEvent
class Q_QUICK_PRIVATE_EXPORT QQuickPointerDevice : public QObject
@@ -627,6 +672,7 @@ public:
int buttonCount() const { return m_buttonCount; }
QString name() const { return m_name; }
QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; }
+ const QTouchDevice *qTouchDevice() const;
static QQuickPointerDevice *touchDevice(const QTouchDevice *d);
static QList<QQuickPointerDevice *> touchDevices();
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index cc35630fff..b47d055ca4 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -248,6 +248,7 @@ QQuickFlickablePrivate::QQuickFlickablePrivate()
, stealMouse(false), pressed(false)
, scrollingPhase(false), interactive(true), calcVelocity(false)
, pixelAligned(false)
+ , syncDrag(false)
, lastPosTime(-1)
, lastPressTime(0)
, deceleration(QML_FLICK_DEFAULTDECELERATION)
@@ -984,6 +985,33 @@ void QQuickFlickable::setPixelAligned(bool align)
}
}
+/*!
+ \qmlproperty bool QtQuick::Flickable::synchronousDrag
+ \since 5.12
+
+ If this property is set to true, then when the mouse or touchpoint moves
+ far enough to begin dragging the content, the content will jump, such that
+ the content pixel which was under the cursor or touchpoint when pressed
+ remains under that point.
+
+ The default is \c false, which provides a smoother experience (no jump)
+ at the cost that some of the drag distance is "lost" at the beginning.
+*/
+bool QQuickFlickable::synchronousDrag() const
+{
+ Q_D(const QQuickFlickable);
+ return d->syncDrag;
+}
+
+void QQuickFlickable::setSynchronousDrag(bool v)
+{
+ Q_D(QQuickFlickable);
+ if (v != d->syncDrag) {
+ d->syncDrag = v;
+ emit synchronousDragChanged();
+ }
+}
+
qint64 QQuickFlickablePrivate::computeCurrentTime(QInputEvent *event) const
{
if (0 != event->timestamp())
@@ -1100,7 +1128,7 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
if (overThreshold || elapsedSincePress > 200) {
if (!vMoved)
vData.dragStartOffset = dy;
- qreal newY = dy + vData.pressPos - vData.dragStartOffset;
+ qreal newY = dy + vData.pressPos - (syncDrag ? 0 : vData.dragStartOffset);
// Recalculate bounds in case margins have changed, but use the content
// size estimate taken at the start of the drag in case the drag causes
// the estimate to be altered
@@ -1176,7 +1204,7 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp
if (overThreshold || elapsedSincePress > 200) {
if (!hMoved)
hData.dragStartOffset = dx;
- qreal newX = dx + hData.pressPos - hData.dragStartOffset;
+ qreal newX = dx + hData.pressPos - (syncDrag ? 0 : hData.dragStartOffset);
const qreal minX = hData.dragMinBound + hData.startMargin;
const qreal maxX = hData.dragMaxBound - hData.endMargin;
if (!(boundsBehavior & QQuickFlickable::DragOverBounds)) {
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 939e3af698..45921c8b86 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -106,6 +106,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem
Q_PROPERTY(QQuickFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
+ Q_PROPERTY(bool synchronousDrag READ synchronousDrag WRITE setSynchronousDrag NOTIFY synchronousDragChanged REVISION 12)
Q_PROPERTY(qreal horizontalOvershoot READ horizontalOvershoot NOTIFY horizontalOvershootChanged REVISION 9)
Q_PROPERTY(qreal verticalOvershoot READ verticalOvershoot NOTIFY verticalOvershootChanged REVISION 9)
@@ -213,6 +214,9 @@ public:
bool pixelAligned() const;
void setPixelAligned(bool align);
+ bool synchronousDrag() const;
+ void setSynchronousDrag(bool v);
+
qreal horizontalOvershoot() const;
qreal verticalOvershoot() const;
@@ -259,6 +263,7 @@ Q_SIGNALS:
void dragStarted();
void dragEnded();
void pixelAlignedChanged();
+ Q_REVISION(12) void synchronousDragChanged();
Q_REVISION(9) void horizontalOvershootChanged();
Q_REVISION(9) void verticalOvershootChanged();
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 08f069e830..dfb943d710 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -221,6 +221,7 @@ public:
bool interactive : 1;
bool calcVelocity : 1;
bool pixelAligned : 1;
+ bool syncDrag : 1;
QElapsedTimer timer;
QBasicTimer movementEndingTimer;
qint64 lastPosTime;
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index f2fa66332c..6fcd846423 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -914,7 +914,7 @@ void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
if (snapMode == QQuickGridView::SnapOneRow && moveReason == Mouse) {
// if we've been dragged < rowSize()/2 then bias towards the next row
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = 0;
if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2)
bias = rowSize()/2;
@@ -925,13 +925,13 @@ void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (strictHighlightRange && currentItem && (!topItem || topItem->index != currentIndex)) {
+ if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (strictHighlightRange && currentItem && (!bottomItem || bottomItem->index != currentIndex)) {
+ if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
@@ -1013,7 +1013,7 @@ bool QQuickGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
if (data.move.value() < minExtent) {
if (snapMode == QQuickGridView::SnapOneRow) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0;
if (isContentFlowReversed())
bias = -bias;
@@ -1030,7 +1030,7 @@ bool QQuickGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
if (data.move.value() > maxExtent) {
if (snapMode == QQuickGridView::SnapOneRow) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0;
if (isContentFlowReversed())
bias = -bias;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 29b0ed10e6..c1e625ef95 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -67,6 +67,7 @@
#include <QtQuick/private/qquickstate_p.h>
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
+#include <QtQuick/private/qquickhoverhandler_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <private/qv4engine_p.h>
@@ -5150,6 +5151,17 @@ void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
}
}
+bool QQuickItemPrivate::anyPointerHandlerWants(QQuickEventPoint *point) const
+{
+ if (!hasPointerHandlers())
+ return false;
+ for (QQuickPointerHandler *handler : extra->pointerHandlers) {
+ if (handler->wantsEventPoint(point))
+ return true;
+ }
+ return false;
+}
+
/*!
\internal
Deliver the \a event to all PointerHandlers which are in the pre-determined
@@ -7353,6 +7365,8 @@ void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled)
return; // nope! sorry, something else wants it kept on.
+ if (otherChildPrivate->hasHoverHandlers())
+ return; // nope! sorry, we have pointer handlers which are interested.
}
}
@@ -8126,6 +8140,16 @@ bool QQuickItemPrivate::hasPointerHandlers() const
return extra.isAllocated() && !extra->pointerHandlers.isEmpty();
}
+bool QQuickItemPrivate::hasHoverHandlers() const
+{
+ if (!hasPointerHandlers())
+ return false;
+ for (QQuickPointerHandler *h : extra->pointerHandlers)
+ if (qmlobject_cast<QQuickHoverHandler *>(h))
+ return true;
+ return false;
+}
+
#if QT_CONFIG(quick_shadereffect)
QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
: m_item(item)
@@ -8711,7 +8735,7 @@ void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkS
quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine)
{
- return (engine->memoryManager->allocObject<QQuickItemWrapper>(q_func()))->asReturnedValue();
+ return (engine->memoryManager->allocate<QQuickItemWrapper>(q_func()))->asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 93287cf0aa..bb63bc1ee4 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -280,6 +280,7 @@ public:
QQuickItemLayer *layer() const;
bool hasPointerHandlers() const;
+ bool hasHoverHandlers() const;
// data property
static void data_append(QQmlListProperty<QObject> *, QObject *);
@@ -581,6 +582,7 @@ public:
#endif
void deliverShortcutOverrideEvent(QKeyEvent *);
+ bool anyPointerHandlerWants(QQuickEventPoint *point) const;
virtual bool handlePointerEvent(QQuickPointerEvent *, bool avoidExclusiveGrabber = false);
virtual void setVisible(bool visible);
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 51a91e1f7a..806fd9e465 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -422,6 +422,10 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickAnimatedImage, 11>(uri, 2, 11,"AnimatedImage");
#endif
qmlRegisterType<QQuickItem, 11>(uri, 2, 11,"Item");
+
+ qmlRegisterType<QQuickAnimatedSprite, 12>("QtQuick", 2, 12, "AnimatedSprite");
+ qmlRegisterType<QQuickGradient, 12>(uri, 2, 12, "Gradient");
+ qmlRegisterType<QQuickFlickable, 12>(uri, 2, 12, "Flickable");
}
static void initResources()
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index f2e055e874..4e4881ce19 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qquickitemview_p_p.h"
+#include "qquickitemviewfxitem_p_p.h"
#include <QtQuick/private/qquicktransition_p.h>
#include <QtQml/QQmlInfo>
#include "qplatformdefs.h"
@@ -52,117 +53,14 @@ Q_LOGGING_CATEGORY(lcItemViewDelegateLifecycle, "qt.quick.itemview.lifecycle")
#endif
FxViewItem::FxViewItem(QQuickItem *i, QQuickItemView *v, bool own, QQuickItemViewAttached *attached)
- : item(i)
+ : QQuickItemViewFxItem(i, own, QQuickItemViewPrivate::get(v))
, view(v)
- , transitionableItem(nullptr)
, attached(attached)
- , ownItem(own)
- , releaseAfterTransition(false)
- , trackGeom(false)
{
if (attached) // can be null for default components (see createComponentItem)
attached->setView(view);
}
-FxViewItem::~FxViewItem()
-{
- delete transitionableItem;
- if (ownItem && item) {
- trackGeometry(false);
- item->setParentItem(nullptr);
- item->deleteLater();
- item = nullptr;
- }
-}
-
-qreal FxViewItem::itemX() const
-{
- return transitionableItem ? transitionableItem->itemX() : (item ? item->x() : 0);
-}
-
-qreal FxViewItem::itemY() const
-{
- return transitionableItem ? transitionableItem->itemY() : (item ? item->y() : 0);
-}
-
-void FxViewItem::moveTo(const QPointF &pos, bool immediate)
-{
- if (transitionableItem)
- transitionableItem->moveTo(pos, immediate);
- else if (item)
- item->setPosition(pos);
-}
-
-void FxViewItem::setVisible(bool visible)
-{
- if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning())
- return;
- if (item)
- QQuickItemPrivate::get(item)->setCulled(!visible);
-}
-
-void FxViewItem::trackGeometry(bool track)
-{
- if (track) {
- if (!trackGeom) {
- if (item) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
- }
- trackGeom = true;
- }
- } else {
- if (trackGeom) {
- if (item) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
- }
- trackGeom = false;
- }
- }
-}
-
-QQuickItemViewTransitioner::TransitionType FxViewItem::scheduledTransitionType() const
-{
- return transitionableItem ? transitionableItem->nextTransitionType : QQuickItemViewTransitioner::NoTransition;
-}
-
-bool FxViewItem::transitionScheduledOrRunning() const
-{
- return transitionableItem ? transitionableItem->transitionScheduledOrRunning() : false;
-}
-
-bool FxViewItem::transitionRunning() const
-{
- return transitionableItem ? transitionableItem->transitionRunning() : false;
-}
-
-bool FxViewItem::isPendingRemoval() const
-{
- return transitionableItem ? transitionableItem->isPendingRemoval() : false;
-}
-
-void FxViewItem::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
-{
- if (!transitioner)
- return;
- if (!transitionableItem)
- transitionableItem = new QQuickItemViewTransitionableItem(item);
- transitioner->transitionNextReposition(transitionableItem, type, asTarget);
-}
-
-bool FxViewItem::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
-{
- return transitionableItem ? transitionableItem->prepareTransition(transitioner, index, viewBounds) : false;
-}
-
-void FxViewItem::startTransition(QQuickItemViewTransitioner *transitioner)
-{
- if (transitionableItem)
- transitionableItem->startTransition(transitioner, index);
-}
-
-
QQuickItemViewChangeSet::QQuickItemViewChangeSet()
: active(false)
{
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index e250cf0ccb..ea5b5df9c6 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -56,6 +56,7 @@
QT_REQUIRE_CONFIG(quick_itemview);
#include "qquickitemview_p.h"
+#include "qquickitemviewfxitem_p_p.h"
#include "qquickitemviewtransition_p.h"
#include "qquickflickable_p_p.h"
#include <QtQml/private/qqmlobjectmodel_p.h>
@@ -65,47 +66,13 @@ QT_REQUIRE_CONFIG(quick_itemview);
QT_BEGIN_NAMESPACE
-
-class Q_AUTOTEST_EXPORT FxViewItem
+class Q_AUTOTEST_EXPORT FxViewItem : public QQuickItemViewFxItem
{
public:
FxViewItem(QQuickItem *, QQuickItemView *, bool own, QQuickItemViewAttached *attached);
- virtual ~FxViewItem();
-
- qreal itemX() const;
- qreal itemY() const;
- inline qreal itemWidth() const { return item ? item->width() : 0; }
- inline qreal itemHeight() const { return item ? item->height() : 0; }
-
- void moveTo(const QPointF &pos, bool immediate);
- void setVisible(bool visible);
- void trackGeometry(bool track);
-
- QQuickItemViewTransitioner::TransitionType scheduledTransitionType() const;
- bool transitionScheduledOrRunning() const;
- bool transitionRunning() const;
- bool isPendingRemoval() const;
-
- void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
- bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
- void startTransition(QQuickItemViewTransitioner *transitioner);
-
- // these are positions and sizes along the current direction of scrolling/flicking
- virtual qreal position() const = 0;
- virtual qreal endPosition() const = 0;
- virtual qreal size() const = 0;
- virtual qreal sectionSize() const = 0;
-
- virtual bool contains(qreal x, qreal y) const = 0;
- QPointer<QQuickItem> item;
QQuickItemView *view;
- QQuickItemViewTransitionableItem *transitionableItem;
QQuickItemViewAttached *attached;
- int index;
- bool ownItem;
- bool releaseAfterTransition;
- bool trackGeom;
};
diff --git a/src/quick/items/qquickitemviewfxitem.cpp b/src/quick/items/qquickitemviewfxitem.cpp
new file mode 100644
index 0000000000..f9c65967ea
--- /dev/null
+++ b/src/quick/items/qquickitemviewfxitem.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickitemviewfxitem_p_p.h"
+#include "qquickitem_p.h"
+#include "qquickitemview_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQuickItemViewFxItem::QQuickItemViewFxItem(QQuickItem *item, bool ownItem, QQuickItemChangeListener* changeListener)
+ : item(item)
+ , ownItem(ownItem)
+ , changeListener(changeListener)
+ , transitionableItem(nullptr)
+ , releaseAfterTransition(false)
+ , trackGeom(false)
+{
+}
+
+QQuickItemViewFxItem::~QQuickItemViewFxItem()
+{
+ delete transitionableItem;
+ if (ownItem && item) {
+ trackGeometry(false);
+ item->setParentItem(0);
+ item->deleteLater();
+ }
+}
+
+qreal QQuickItemViewFxItem::itemX() const
+{
+ return transitionableItem ? transitionableItem->itemX() : (item ? item->x() : 0);
+}
+
+qreal QQuickItemViewFxItem::itemY() const
+{
+ return transitionableItem ? transitionableItem->itemY() : (item ? item->y() : 0);
+}
+
+void QQuickItemViewFxItem::moveTo(const QPointF &pos, bool immediate)
+{
+ if (transitionableItem)
+ transitionableItem->moveTo(pos, immediate);
+ else if (item)
+ item->setPosition(pos);
+}
+
+void QQuickItemViewFxItem::setVisible(bool visible)
+{
+ if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning())
+ return;
+ if (item)
+ QQuickItemPrivate::get(item)->setCulled(!visible);
+}
+
+void QQuickItemViewFxItem::trackGeometry(bool track)
+{
+ if (track) {
+ if (!trackGeom) {
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->addItemChangeListener(changeListener, QQuickItemPrivate::Geometry);
+ }
+ trackGeom = true;
+ }
+ } else {
+ if (trackGeom) {
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->removeItemChangeListener(changeListener, QQuickItemPrivate::Geometry);
+ }
+ trackGeom = false;
+ }
+ }
+}
+
+QRectF QQuickItemViewFxItem::geometry() const
+{
+ return QRectF(item->position(), item->size());
+}
+
+void QQuickItemViewFxItem::setGeometry(const QRectF &geometry)
+{
+ item->setPosition(geometry.topLeft());
+ item->setSize(geometry.size());
+}
+
+QQuickItemViewTransitioner::TransitionType QQuickItemViewFxItem::scheduledTransitionType() const
+{
+ return transitionableItem ? transitionableItem->nextTransitionType : QQuickItemViewTransitioner::NoTransition;
+}
+
+bool QQuickItemViewFxItem::transitionScheduledOrRunning() const
+{
+ return transitionableItem ? transitionableItem->transitionScheduledOrRunning() : false;
+}
+
+bool QQuickItemViewFxItem::transitionRunning() const
+{
+ return transitionableItem ? transitionableItem->transitionRunning() : false;
+}
+
+bool QQuickItemViewFxItem::isPendingRemoval() const
+{
+ return transitionableItem ? transitionableItem->isPendingRemoval() : false;
+}
+
+void QQuickItemViewFxItem::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
+{
+ if (!transitioner)
+ return;
+ if (!transitionableItem)
+ transitionableItem = new QQuickItemViewTransitionableItem(item);
+ transitioner->transitionNextReposition(transitionableItem, type, asTarget);
+}
+
+bool QQuickItemViewFxItem::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
+{
+ return transitionableItem ? transitionableItem->prepareTransition(transitioner, index, viewBounds) : false;
+}
+
+void QQuickItemViewFxItem::startTransition(QQuickItemViewTransitioner *transitioner)
+{
+ if (transitionableItem)
+ transitionableItem->startTransition(transitioner, index);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/items/qquickitemviewfxitem_p_p.h b/src/quick/items/qquickitemviewfxitem_p_p.h
new file mode 100644
index 0000000000..48ffe248bc
--- /dev/null
+++ b/src/quick/items/qquickitemviewfxitem_p_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKFXVIEWITEM_P_P_H
+#define QQUICKFXVIEWITEM_P_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 <QtQuick/private/qtquickglobal_p.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickitemviewtransition_p.h>
+
+QT_REQUIRE_CONFIG(quick_itemview);
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QQuickItemViewFxItem
+{
+public:
+ QQuickItemViewFxItem(QQuickItem *item, bool ownItem, QQuickItemChangeListener *changeListener);
+ virtual ~QQuickItemViewFxItem();
+
+ qreal itemX() const;
+ qreal itemY() const;
+ inline qreal itemWidth() const { return item ? item->width() : 0; }
+ inline qreal itemHeight() const { return item ? item->height() : 0; }
+
+ void moveTo(const QPointF &pos, bool immediate);
+ void setVisible(bool visible);
+ void trackGeometry(bool track);
+
+ QRectF geometry() const;
+ void setGeometry(const QRectF &geometry);
+
+ QQuickItemViewTransitioner::TransitionType scheduledTransitionType() const;
+ bool transitionScheduledOrRunning() const;
+ bool transitionRunning() const;
+ bool isPendingRemoval() const;
+
+ void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
+ bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
+ void startTransition(QQuickItemViewTransitioner *transitioner);
+
+ // these are positions and sizes along the current direction of scrolling/flicking
+ virtual qreal position() const = 0;
+ virtual qreal endPosition() const = 0;
+ virtual qreal size() const = 0;
+ virtual qreal sectionSize() const = 0;
+
+ virtual bool contains(qreal x, qreal y) const = 0;
+
+ int index = -1;
+ QPointer<QQuickItem> item;
+ bool ownItem;
+ QQuickItemChangeListener *changeListener;
+ QQuickItemViewTransitionableItem *transitionableItem;
+ bool releaseAfterTransition;
+ bool trackGeom;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKFXVIEWITEM_P_P_H
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 19033e03f1..7c364692c2 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1501,7 +1501,7 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
if (snapMode == QQuickListView::SnapOneItem && moveReason == Mouse) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = 0;
if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2)
bias = averageSize/2;
@@ -1512,13 +1512,13 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (strictHighlightRange && currentItem && (!topItem || topItem->index != currentIndex)) {
+ if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (strictHighlightRange && currentItem && (!bottomItem || bottomItem->index != currentIndex)) {
+ if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
@@ -1599,7 +1599,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
if (data.move.value() < minExtent) {
if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
if (isContentFlowReversed())
bias = -bias;
@@ -1616,7 +1616,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
if (data.move.value() > maxExtent) {
if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
// if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal dist = data.move.value() - data.pressPos;
qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
if (isContentFlowReversed())
bias = -bias;
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index b5ae41daef..f32f25a42f 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -54,7 +54,7 @@ static const QQuickItemPrivate::ChangeTypes watchedChanges
= QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
QQuickLoaderPrivate::QQuickLoaderPrivate()
- : item(nullptr), object(nullptr), component(nullptr), itemContext(nullptr), incubator(nullptr), updatingSize(false),
+ : item(nullptr), object(nullptr), itemContext(nullptr), incubator(nullptr), updatingSize(false),
active(true), loadingFromSource(false), asynchronous(false)
{
}
@@ -111,11 +111,10 @@ void QQuickLoaderPrivate::clear()
QObject::disconnect(component, SIGNAL(progressChanged(qreal)),
q, SIGNAL(progressChanged()));
component->deleteLater();
- component = nullptr;
+ component.setObject(nullptr, q);
} else if (component) {
- component = nullptr;
+ component.setObject(nullptr, q);
}
- componentStrongReference.clear();
source = QUrl();
if (item) {
@@ -441,7 +440,7 @@ void QQuickLoader::loadFromSource()
if (isComponentComplete()) {
QQmlComponent::CompilationMode mode = d->asynchronous ? QQmlComponent::Asynchronous : QQmlComponent::PreferSynchronous;
if (!d->component)
- d->component = new QQmlComponent(qmlEngine(this), d->source, mode, this);
+ d->component.setObject(new QQmlComponent(qmlEngine(this), d->source, mode, this), this);
d->load();
}
}
@@ -484,11 +483,7 @@ void QQuickLoader::setSourceComponent(QQmlComponent *comp)
d->clear();
- d->component = comp;
- if (comp) {
- if (QQmlData *ddata = QQmlData::get(comp))
- d->componentStrongReference = ddata->jsWrapper;
- }
+ d->component.setObject(comp, this);
d->loadingFromSource = false;
if (d->active)
@@ -832,7 +827,7 @@ void QQuickLoader::componentComplete()
if (d->loadingFromSource) {
QQmlComponent::CompilationMode mode = d->asynchronous ? QQmlComponent::Asynchronous : QQmlComponent::PreferSynchronous;
if (!d->component)
- d->component = new QQmlComponent(qmlEngine(this), d->source, mode, this);
+ d->component.setObject(new QQmlComponent(qmlEngine(this), d->source, mode, this), this);
}
d->load();
}
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 7492527401..349b5c6c06 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -103,8 +103,7 @@ public:
QUrl source;
QQuickItem *item;
QObject *object;
- QQmlComponent *component;
- QV4::PersistentValue componentStrongReference; // To ensure GC doesn't delete components created by Qt.createComponent
+ QQmlStrongJSQObjectReference<QQmlComponent> component;
QQmlContext *itemContext;
QQuickLoaderIncubator *incubator;
QV4::PersistentValue initialPropertyValues;
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index bf030b9d80..5e217dcd0c 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -40,9 +40,13 @@
#include "qquickrectangle_p.h"
#include "qquickrectangle_p_p.h"
+#include <QtQml/qqmlinfo.h>
+
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qsgadaptationlayer_p.h>
+#include <private/qqmlmetatype_p.h>
+
#include <QtGui/qpixmapcache.h>
#include <QtCore/qmath.h>
#include <QtCore/qmetaobject.h>
@@ -219,10 +223,11 @@ void QQuickGradientStop::updateGradient()
of solid color fills or images. Consider using gradients for static items
in a user interface.
- In Qt 5.0, only vertical, linear gradients can be applied to items. If you
- need to apply different orientations of gradients, a combination of rotation
- and clipping will need to be applied to the relevant items. This can
- introduce additional performance requirements for your application.
+ Since Qt 5.12, vertical and horizontal linear gradients can be applied to items.
+ If you need to apply angled gradients, a combination of rotation and clipping
+ can be applied to the relevant items. Alternatively, consider using
+ QtQuick.Shapes::LinearGradient or QtGraphicalEffects::LinearGradient. These
+ approaches can all introduce additional performance requirements for your application.
The use of animations involving gradient stops may not give the desired
result. An alternative way to animate gradients is to use pre-generated
@@ -255,6 +260,28 @@ QQmlListProperty<QQuickGradientStop> QQuickGradient::stops()
return QQmlListProperty<QQuickGradientStop>(this, m_stops);
}
+/*!
+ \qmlproperty enumeration QtQuick::Gradient::orientation
+ \since 5.12
+
+ Set this property to define the direction of the gradient.
+ \list
+ \li Gradient.Vertical - a vertical gradient
+ \li Gradient.Horizontal - a horizontal gradient
+ \endlist
+
+ The default is Gradient.Vertical.
+*/
+void QQuickGradient::setOrientation(Orientation orientation)
+{
+ if (m_orientation == orientation)
+ return;
+
+ m_orientation = orientation;
+ emit orientationChanged();
+ emit updated();
+}
+
QGradientStops QQuickGradient::gradientStops() const
{
QGradientStops stops;
@@ -370,11 +397,11 @@ QQuickPen *QQuickRectangle::border()
}
/*!
- \qmlproperty Gradient QtQuick::Rectangle::gradient
+ \qmlproperty any QtQuick::Rectangle::gradient
The gradient to use to fill the rectangle.
- This property allows for the construction of simple vertical gradients.
+ This property allows for the construction of simple vertical or horizontal gradients.
Other gradients may be formed by adding rotation to the rectangle.
\div {class="float-left"}
@@ -384,37 +411,66 @@ QQuickPen *QQuickRectangle::border()
\snippet qml/rectangle/rectangle-gradient.qml rectangles
\clearfloat
+ The property also accepts gradient presets from QGradient::Preset. Note however
+ that due to Rectangle only supporting simple vertical or horizontal gradients,
+ any preset with an unsupported angle will revert to the closest representation.
+
+ \snippet qml/rectangle/rectangle-gradient.qml presets
+ \clearfloat
+
If both a gradient and a color are specified, the gradient will be used.
\sa Gradient, color
*/
-QQuickGradient *QQuickRectangle::gradient() const
+QJSValue QQuickRectangle::gradient() const
{
Q_D(const QQuickRectangle);
return d->gradient;
}
-void QQuickRectangle::setGradient(QQuickGradient *gradient)
+void QQuickRectangle::setGradient(const QJSValue &gradient)
{
Q_D(QQuickRectangle);
- if (d->gradient == gradient)
+ if (d->gradient.equals(gradient))
return;
- static int updatedSignalIdx = -1;
- if (updatedSignalIdx < 0)
- updatedSignalIdx = QMetaMethod::fromSignal(&QQuickGradient::updated).methodIndex();
+
+ static int updatedSignalIdx = QMetaMethod::fromSignal(&QQuickGradient::updated).methodIndex();
if (d->doUpdateSlotIdx < 0)
d->doUpdateSlotIdx = QQuickRectangle::staticMetaObject.indexOfSlot("doUpdate()");
- if (d->gradient)
- QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
- d->gradient = gradient;
- if (d->gradient)
- QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+
+ if (auto oldGradient = qobject_cast<QQuickGradient*>(d->gradient.toQObject()))
+ QMetaObject::disconnect(oldGradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+
+ if (gradient.isQObject()) {
+ if (auto newGradient = qobject_cast<QQuickGradient*>(gradient.toQObject())) {
+ d->gradient = gradient;
+ QMetaObject::connect(newGradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+ } else {
+ qmlWarning(this) << "Can't assign "
+ << QQmlMetaType::prettyTypeName(gradient.toQObject()) << " to gradient property";
+ d->gradient = QJSValue();
+ }
+ } else if (gradient.isNumber() || gradient.isString()) {
+ QGradient preset(gradient.toVariant().value<QGradient::Preset>());
+ if (preset.type() != QGradient::NoGradient) {
+ d->gradient = gradient;
+ } else {
+ qmlWarning(this) << "No such gradient preset '" << gradient.toString() << "'";
+ d->gradient = QJSValue();
+ }
+ } else if (gradient.isNull() || gradient.isUndefined()) {
+ d->gradient = gradient;
+ } else {
+ qmlWarning(this) << "Unknown gradient type. Expected int, string, or Gradient";
+ d->gradient = QJSValue();
+ }
+
update();
}
void QQuickRectangle::resetGradient()
{
- setGradient(nullptr);
+ setGradient(QJSValue());
}
/*!
@@ -510,10 +566,35 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
rectangle->setAntialiasing(antialiasing());
QGradientStops stops;
- if (d->gradient) {
- stops = d->gradient->gradientStops();
+ bool vertical = true;
+ if (d->gradient.isQObject()) {
+ auto gradient = qobject_cast<QQuickGradient*>(d->gradient.toQObject());
+ Q_ASSERT(gradient);
+ stops = gradient->gradientStops();
+ vertical = gradient->orientation() == QQuickGradient::Vertical;
+ } else if (d->gradient.isNumber() || d->gradient.isString()) {
+ QGradient preset(d->gradient.toVariant().value<QGradient::Preset>());
+ if (preset.type() == QGradient::LinearGradient) {
+ auto linearGradient = static_cast<QLinearGradient&>(preset);
+ const QPointF start = linearGradient.start();
+ const QPointF end = linearGradient.finalStop();
+ vertical = qAbs(start.y() - end.y()) >= qAbs(start.x() - end.x());
+ stops = linearGradient.stops();
+ if ((vertical && start.y() > end.y()) || (!vertical && start.x() > end.x())) {
+ // QSGInternalRectangleNode doesn't support stops in the wrong order,
+ // so we need to manually reverse them here.
+ QGradientStops reverseStops;
+ for (auto it = stops.rbegin(); it != stops.rend(); ++it) {
+ auto stop = *it;
+ stop.first = 1 - stop.first;
+ reverseStops.append(stop);
+ }
+ stops = reverseStops;
+ }
+ }
}
rectangle->setGradientStops(stops);
+ rectangle->setGradientVertical(vertical);
rectangle->update();
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index c07ad835fb..d56a03d22d 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -119,24 +119,35 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGradient : public QObject
Q_OBJECT
Q_PROPERTY(QQmlListProperty<QQuickGradientStop> stops READ stops)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged REVISION 12)
Q_CLASSINFO("DefaultProperty", "stops")
+ Q_ENUMS(QGradient::Preset)
public:
QQuickGradient(QObject *parent=nullptr);
~QQuickGradient() override;
+ enum Orientation { Vertical = Qt::Vertical,
+ Horizontal = Qt::Horizontal };
+ Q_ENUM(Orientation)
+
QQmlListProperty<QQuickGradientStop> stops();
+ Orientation orientation() const { return m_orientation; }
+ void setOrientation(Orientation orientation);
+
QGradientStops gradientStops() const;
Q_SIGNALS:
void updated();
+ void orientationChanged();
private:
void doUpdate();
private:
QList<QQuickGradientStop *> m_stops;
+ Orientation m_orientation = Vertical;
friend class QQuickRectangle;
friend class QQuickGradientStop;
};
@@ -147,7 +158,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QQuickGradient *gradient READ gradient WRITE setGradient RESET resetGradient)
+ Q_PROPERTY(QJSValue gradient READ gradient WRITE setGradient RESET resetGradient)
Q_PROPERTY(QQuickPen * border READ border CONSTANT)
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
public:
@@ -158,8 +169,8 @@ public:
QQuickPen *border();
- QQuickGradient *gradient() const;
- void setGradient(QQuickGradient *gradient);
+ QJSValue gradient() const;
+ void setGradient(const QJSValue &gradient);
void resetGradient();
qreal radius() const;
diff --git a/src/quick/items/qquickrectangle_p_p.h b/src/quick/items/qquickrectangle_p_p.h
index 3c1aaf7661..c7c5293f9b 100644
--- a/src/quick/items/qquickrectangle_p_p.h
+++ b/src/quick/items/qquickrectangle_p_p.h
@@ -73,7 +73,7 @@ public:
}
QColor color;
- QQuickGradient *gradient;
+ QJSValue gradient;
QQuickPen *pen;
qreal radius;
static int doUpdateSlotIdx;
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index fb1c6366f2..86a64cdeeb 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -187,7 +187,6 @@ void QQuickRenderControlPrivate::windowDestroyed()
{
if (window) {
rc->invalidate();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
delete QQuickWindowPrivate::get(window)->animationController;
QQuickWindowPrivate::get(window)->animationController = nullptr;
diff --git a/src/quick/items/qquickscalegrid.cpp b/src/quick/items/qquickscalegrid.cpp
index d7a0f1b681..23f179be1d 100644
--- a/src/quick/items/qquickscalegrid.cpp
+++ b/src/quick/items/qquickscalegrid.cpp
@@ -66,6 +66,7 @@ void QQuickScaleGrid::setLeft(int pos)
{
if (_left != pos) {
_left = pos;
+ emit leftBorderChanged();
emit borderChanged();
}
}
@@ -74,6 +75,7 @@ void QQuickScaleGrid::setTop(int pos)
{
if (_top != pos) {
_top = pos;
+ emit topBorderChanged();
emit borderChanged();
}
}
@@ -82,6 +84,7 @@ void QQuickScaleGrid::setRight(int pos)
{
if (_right != pos) {
_right = pos;
+ emit rightBorderChanged();
emit borderChanged();
}
}
@@ -90,6 +93,7 @@ void QQuickScaleGrid::setBottom(int pos)
{
if (_bottom != pos) {
_bottom = pos;
+ emit bottomBorderChanged();
emit borderChanged();
}
}
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
index 5752f61e3f..f5187a8eea 100644
--- a/src/quick/items/qquickscalegrid_p_p.h
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -65,10 +65,10 @@ class Q_AUTOTEST_EXPORT QQuickScaleGrid : public QObject
{
Q_OBJECT
- Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
- Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
- Q_PROPERTY(int right READ right WRITE setRight NOTIFY borderChanged)
- Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY borderChanged)
+ Q_PROPERTY(int left READ left WRITE setLeft NOTIFY leftBorderChanged)
+ Q_PROPERTY(int top READ top WRITE setTop NOTIFY topBorderChanged)
+ Q_PROPERTY(int right READ right WRITE setRight NOTIFY rightBorderChanged)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomBorderChanged)
public:
QQuickScaleGrid(QObject *parent=nullptr);
@@ -90,6 +90,10 @@ public:
Q_SIGNALS:
void borderChanged();
+ void leftBorderChanged();
+ void topBorderChanged();
+ void rightBorderChanged();
+ void bottomBorderChanged();
private:
int _left;
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
new file mode 100644
index 0000000000..26aa409cec
--- /dev/null
+++ b/src/quick/items/qquicktableview.cpp
@@ -0,0 +1,1463 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicktableview_p.h"
+#include "qquicktableview_p_p.h"
+
+#include <QtCore/qtimer.h>
+#include <QtCore/qdir.h>
+#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <QtQml/private/qqmldelegatemodel_p_p.h>
+#include <QtQml/private/qqmlincubator_p.h>
+#include <QtQml/private/qqmlchangeset_p.h>
+#include <QtQml/qqmlinfo.h>
+
+#include <QtQuick/private/qquickflickable_p_p.h>
+#include <QtQuick/private/qquickitemviewfxitem_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcTableViewDelegateLifecycle, "qt.quick.tableview.lifecycle")
+
+#define Q_TABLEVIEW_UNREACHABLE(output) { dumpTable(); qWarning() << "output:" << output; Q_UNREACHABLE(); }
+#define Q_TABLEVIEW_ASSERT(cond, output) Q_ASSERT(cond || [&](){ dumpTable(); qWarning() << "output:" << output; return false;}())
+
+static const Qt::Edge allTableEdges[] = { Qt::LeftEdge, Qt::RightEdge, Qt::TopEdge, Qt::BottomEdge };
+static const int kBufferTimerInterval = 300;
+
+static QLine rectangleEdge(const QRect &rect, Qt::Edge tableEdge)
+{
+ switch (tableEdge) {
+ case Qt::LeftEdge:
+ return QLine(rect.topLeft(), rect.bottomLeft());
+ case Qt::RightEdge:
+ return QLine(rect.topRight(), rect.bottomRight());
+ case Qt::TopEdge:
+ return QLine(rect.topLeft(), rect.topRight());
+ case Qt::BottomEdge:
+ return QLine(rect.bottomLeft(), rect.bottomRight());
+ }
+ return QLine();
+}
+
+static QRect expandedRect(const QRect &rect, Qt::Edge edge, int increment)
+{
+ switch (edge) {
+ case Qt::LeftEdge:
+ return rect.adjusted(-increment, 0, 0, 0);
+ case Qt::RightEdge:
+ return rect.adjusted(0, 0, increment, 0);
+ case Qt::TopEdge:
+ return rect.adjusted(0, -increment, 0, 0);
+ case Qt::BottomEdge:
+ return rect.adjusted(0, 0, 0, increment);
+ }
+ return QRect();
+}
+
+const QPoint QQuickTableViewPrivate::kLeft = QPoint(-1, 0);
+const QPoint QQuickTableViewPrivate::kRight = QPoint(1, 0);
+const QPoint QQuickTableViewPrivate::kUp = QPoint(0, -1);
+const QPoint QQuickTableViewPrivate::kDown = QPoint(0, 1);
+
+QQuickTableViewPrivate::QQuickTableViewPrivate()
+ : QQuickFlickablePrivate()
+{
+ cacheBufferDelayTimer.setSingleShot(true);
+ QObject::connect(&cacheBufferDelayTimer, &QTimer::timeout, [=]{ loadBuffer(); });
+}
+
+QQuickTableViewPrivate::~QQuickTableViewPrivate()
+{
+ clear();
+}
+
+QString QQuickTableViewPrivate::tableLayoutToString() const
+{
+ return QString(QLatin1String("table cells: (%1,%2) -> (%3,%4), item count: %5, table rect: %6,%7 x %8,%9"))
+ .arg(loadedTable.topLeft().x()).arg(loadedTable.topLeft().y())
+ .arg(loadedTable.bottomRight().x()).arg(loadedTable.bottomRight().y())
+ .arg(loadedItems.count())
+ .arg(loadedTableOuterRect.x())
+ .arg(loadedTableOuterRect.y())
+ .arg(loadedTableOuterRect.width())
+ .arg(loadedTableOuterRect.height());
+}
+
+void QQuickTableViewPrivate::dumpTable() const
+{
+ auto listCopy = loadedItems.values();
+ std::stable_sort(listCopy.begin(), listCopy.end(),
+ [](const FxTableItem *lhs, const FxTableItem *rhs)
+ { return lhs->index < rhs->index; });
+
+ qWarning() << QStringLiteral("******* TABLE DUMP *******");
+ for (int i = 0; i < listCopy.count(); ++i)
+ qWarning() << static_cast<FxTableItem *>(listCopy.at(i))->cell;
+ qWarning() << tableLayoutToString();
+
+ const QString filename = QStringLiteral("QQuickTableView_dumptable_capture.png");
+ const QString path = QDir::current().absoluteFilePath(filename);
+ if (q_func()->window()->grabWindow().save(path))
+ qWarning() << "Window capture saved to:" << path;
+}
+
+QQuickTableViewAttached *QQuickTableViewPrivate::getAttachedObject(const QObject *object) const
+{
+ QObject *attachedObject = qmlAttachedPropertiesObject<QQuickTableView>(object);
+ return static_cast<QQuickTableViewAttached *>(attachedObject);
+}
+
+int QQuickTableViewPrivate::modelIndexAtCell(const QPoint &cell) const
+{
+ int availableRows = tableSize.height();
+ int modelIndex = cell.y() + (cell.x() * availableRows);
+ Q_TABLEVIEW_ASSERT(modelIndex < model->count(),
+ "modelIndex:" << modelIndex << "cell:" << cell << "count:" << model->count());
+ return modelIndex;
+}
+
+QPoint QQuickTableViewPrivate::cellAtModelIndex(int modelIndex) const
+{
+ int availableRows = tableSize.height();
+ Q_TABLEVIEW_ASSERT(availableRows > 0, availableRows);
+ int column = int(modelIndex / availableRows);
+ int row = modelIndex % availableRows;
+ return QPoint(column, row);
+}
+
+void QQuickTableViewPrivate::updateContentWidth()
+{
+ Q_Q(QQuickTableView);
+
+ const qreal thresholdBeforeAdjust = 0.1;
+ int currentRightColumn = loadedTable.right();
+
+ if (currentRightColumn > contentSizeBenchMarkPoint.x()) {
+ contentSizeBenchMarkPoint.setX(currentRightColumn);
+
+ qreal currentWidth = loadedTableOuterRect.right();
+ qreal averageCellSize = currentWidth / (currentRightColumn + 1);
+ qreal averageSize = averageCellSize + cellSpacing.width();
+ qreal estimatedWith = (tableSize.width() * averageSize) - cellSpacing.width();
+
+ // loadedTableOuterRect has already been adjusted for left margin
+ currentWidth += tableMargins.right();
+ estimatedWith += tableMargins.right();
+
+ if (currentRightColumn >= tableSize.width() - 1) {
+ // We are at the last column, and can set the exact width
+ if (currentWidth != q->implicitWidth())
+ q->setContentWidth(currentWidth);
+ } else if (currentWidth >= q->implicitWidth()) {
+ // We are at the estimated width, but there are still more columns
+ q->setContentWidth(estimatedWith);
+ } else {
+ // Only set a new width if the new estimate is substantially different
+ qreal diff = 1 - (estimatedWith / q->implicitWidth());
+ if (qAbs(diff) > thresholdBeforeAdjust)
+ q->setContentWidth(estimatedWith);
+ }
+ }
+}
+
+void QQuickTableViewPrivate::updateContentHeight()
+{
+ Q_Q(QQuickTableView);
+
+ const qreal thresholdBeforeAdjust = 0.1;
+ int currentBottomRow = loadedTable.bottom();
+
+ if (currentBottomRow > contentSizeBenchMarkPoint.y()) {
+ contentSizeBenchMarkPoint.setY(currentBottomRow);
+
+ qreal currentHeight = loadedTableOuterRect.bottom();
+ qreal averageCellSize = currentHeight / (currentBottomRow + 1);
+ qreal averageSize = averageCellSize + cellSpacing.height();
+ qreal estimatedHeight = (tableSize.height() * averageSize) - cellSpacing.height();
+
+ // loadedTableOuterRect has already been adjusted for top margin
+ currentHeight += tableMargins.bottom();
+ estimatedHeight += tableMargins.bottom();
+
+ if (currentBottomRow >= tableSize.height() - 1) {
+ // We are at the last row, and can set the exact height
+ if (currentHeight != q->implicitHeight())
+ q->setContentHeight(currentHeight);
+ } else if (currentHeight >= q->implicitHeight()) {
+ // We are at the estimated height, but there are still more rows
+ q->setContentHeight(estimatedHeight);
+ } else {
+ // Only set a new height if the new estimate is substantially different
+ qreal diff = 1 - (estimatedHeight / q->implicitHeight());
+ if (qAbs(diff) > thresholdBeforeAdjust)
+ q->setContentHeight(estimatedHeight);
+ }
+ }
+}
+
+void QQuickTableViewPrivate::enforceFirstRowColumnAtOrigo()
+{
+ // Gaps before the first row/column can happen if rows/columns
+ // changes size while flicking e.g because of spacing changes or
+ // changes to a column maxWidth/row maxHeight. Check for this, and
+ // move the whole table rect accordingly.
+ bool layoutNeeded = false;
+ const qreal flickMargin = 50;
+
+ if (loadedTable.x() == 0 && loadedTableOuterRect.x() != tableMargins.left()) {
+ // The table is at the beginning, but not at the edge of the
+ // content view. So move the table to origo.
+ loadedTableOuterRect.moveLeft(tableMargins.left());
+ layoutNeeded = true;
+ } else if (loadedTableOuterRect.x() < 0) {
+ // The table is outside the beginning of the content view. Move
+ // the whole table inside, and make some room for flicking.
+ loadedTableOuterRect.moveLeft(tableMargins.left() + loadedTable.x() == 0 ? 0 : flickMargin);
+ layoutNeeded = true;
+ }
+
+ if (loadedTable.y() == 0 && loadedTableOuterRect.y() != tableMargins.top()) {
+ loadedTableOuterRect.moveTop(tableMargins.top());
+ layoutNeeded = true;
+ } else if (loadedTableOuterRect.y() < 0) {
+ loadedTableOuterRect.moveTop(tableMargins.top() + loadedTable.y() == 0 ? 0 : flickMargin);
+ layoutNeeded = true;
+ }
+
+ if (layoutNeeded)
+ relayoutTableItems();
+}
+
+void QQuickTableViewPrivate::syncLoadedTableRectFromLoadedTable()
+{
+ QRectF topLeftRect = loadedTableItem(loadedTable.topLeft())->geometry();
+ QRectF bottomRightRect = loadedTableItem(loadedTable.bottomRight())->geometry();
+ loadedTableOuterRect = topLeftRect.united(bottomRightRect);
+ loadedTableInnerRect = QRectF(topLeftRect.bottomRight(), bottomRightRect.topLeft());
+}
+
+void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest()
+{
+ switch (loadRequest.edge()) {
+ case Qt::LeftEdge:
+ case Qt::TopEdge:
+ loadedTable.setTopLeft(loadRequest.firstCell());
+ break;
+ case Qt::RightEdge:
+ case Qt::BottomEdge:
+ loadedTable.setBottomRight(loadRequest.lastCell());
+ break;
+ default:
+ loadedTable = QRect(loadRequest.firstCell(), loadRequest.lastCell());
+ }
+}
+
+FxTableItem *QQuickTableViewPrivate::itemNextTo(const FxTableItem *fxTableItem, const QPoint &direction) const
+{
+ return loadedTableItem(fxTableItem->cell + direction);
+}
+
+FxTableItem *QQuickTableViewPrivate::loadedTableItem(const QPoint &cell) const
+{
+ const int modelIndex = modelIndexAtCell(cell);
+ Q_TABLEVIEW_ASSERT(loadedItems.contains(modelIndex), modelIndex << cell);
+ return loadedItems.value(modelIndex);
+}
+
+FxTableItem *QQuickTableViewPrivate::createFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode)
+{
+ Q_Q(QQuickTableView);
+
+ bool ownItem = false;
+ int modelIndex = modelIndexAtCell(cell);
+
+ QObject* object = model->object(modelIndex, incubationMode);
+ if (!object) {
+ if (model->incubationStatus(modelIndex) == QQmlIncubator::Loading) {
+ // Item is incubating. Return nullptr for now, and let the table call this
+ // function again once we get a callback to itemCreatedCallback().
+ return nullptr;
+ }
+
+ qWarning() << "TableView: failed loading index:" << modelIndex;
+ object = new QQuickItem();
+ ownItem = true;
+ }
+
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ if (!item) {
+ // The model could not provide an QQuickItem for the
+ // given index, so we create a placeholder instead.
+ qWarning() << "TableView: delegate is not an item:" << modelIndex;
+ model->release(object);
+ item = new QQuickItem();
+ ownItem = true;
+ }
+
+ item->setParentItem(q->contentItem());
+
+ FxTableItem *fxTableItem = new FxTableItem(item, q, ownItem);
+ fxTableItem->setVisible(false);
+ fxTableItem->cell = cell;
+ fxTableItem->index = modelIndex;
+ return fxTableItem;
+}
+
+FxTableItem *QQuickTableViewPrivate::loadFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode)
+{
+#ifdef QT_DEBUG
+ // Since TableView needs to work flawlessly when e.g incubating inside an async
+ // loader, being able to override all loading to async while debugging can be helpful.
+ static const bool forcedAsync = forcedIncubationMode == QLatin1String("async");
+ if (forcedAsync)
+ incubationMode = QQmlIncubator::Asynchronous;
+#endif
+
+ // Note that even if incubation mode is asynchronous, the item might
+ // be ready immediately since the model has a cache of items.
+ QBoolBlocker guard(blockItemCreatedCallback);
+ auto item = createFxTableItem(cell, incubationMode);
+ qCDebug(lcTableViewDelegateLifecycle) << cell << "ready?" << bool(item);
+ return item;
+}
+
+void QQuickTableViewPrivate::releaseLoadedItems() {
+ // Make a copy and clear the list of items first to avoid destroyed
+ // items being accessed during the loop (QTBUG-61294)
+ auto const tmpList = loadedItems;
+ loadedItems.clear();
+ for (FxTableItem *item : tmpList)
+ releaseItem(item);
+}
+
+void QQuickTableViewPrivate::releaseItem(FxTableItem *fxTableItem)
+{
+ if (fxTableItem->item) {
+ if (fxTableItem->ownItem)
+ delete fxTableItem->item;
+ else if (model->release(fxTableItem->item) != QQmlInstanceModel::Destroyed)
+ fxTableItem->item->setParentItem(nullptr);
+ }
+
+ delete fxTableItem;
+}
+
+void QQuickTableViewPrivate::clear()
+{
+ tableInvalid = true;
+ tableRebuilding = false;
+ if (loadRequest.isActive())
+ cancelLoadRequest();
+
+ releaseLoadedItems();
+ loadedTable = QRect();
+ loadedTableOuterRect = QRect();
+ loadedTableInnerRect = QRect();
+ columnWidths.clear();
+ rowHeights.clear();
+ contentSizeBenchMarkPoint = QPoint(-1, -1);
+
+ updateContentWidth();
+ updateContentHeight();
+}
+
+void QQuickTableViewPrivate::unloadItem(const QPoint &cell)
+{
+ const int modelIndex = modelIndexAtCell(cell);
+ Q_TABLEVIEW_ASSERT(loadedItems.contains(modelIndex), modelIndex << cell);
+ releaseItem(loadedItems.take(modelIndex));
+}
+
+void QQuickTableViewPrivate::unloadItems(const QLine &items)
+{
+ qCDebug(lcTableViewDelegateLifecycle) << items;
+
+ if (items.dx()) {
+ int y = items.p1().y();
+ for (int x = items.p1().x(); x <= items.p2().x(); ++x)
+ unloadItem(QPoint(x, y));
+ } else {
+ int x = items.p1().x();
+ for (int y = items.p1().y(); y <= items.p2().y(); ++y)
+ unloadItem(QPoint(x, y));
+ }
+}
+
+bool QQuickTableViewPrivate::canLoadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const
+{
+ switch (tableEdge) {
+ case Qt::LeftEdge:
+ if (loadedTable.topLeft().x() == 0)
+ return false;
+ return loadedTableOuterRect.left() > fillRect.left() + cellSpacing.width();
+ case Qt::RightEdge:
+ if (loadedTable.bottomRight().x() >= tableSize.width() - 1)
+ return false;
+ return loadedTableOuterRect.right() < fillRect.right() - cellSpacing.width();
+ case Qt::TopEdge:
+ if (loadedTable.topLeft().y() == 0)
+ return false;
+ return loadedTableOuterRect.top() > fillRect.top() + cellSpacing.height();
+ case Qt::BottomEdge:
+ if (loadedTable.bottomRight().y() >= tableSize.height() - 1)
+ return false;
+ return loadedTableOuterRect.bottom() < fillRect.bottom() - cellSpacing.height();
+ }
+
+ return false;
+}
+
+bool QQuickTableViewPrivate::canUnloadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const
+{
+ // Note: if there is only one row or column left, we cannot unload, since
+ // they are needed as anchor point for further layouting.
+ switch (tableEdge) {
+ case Qt::LeftEdge:
+ if (loadedTable.width() <= 1)
+ return false;
+ return loadedTableInnerRect.left() < fillRect.left();
+ case Qt::RightEdge:
+ if (loadedTable.width() <= 1)
+ return false;
+ return loadedTableInnerRect.right() > fillRect.right();
+ case Qt::TopEdge:
+ if (loadedTable.height() <= 1)
+ return false;
+ return loadedTableInnerRect.top() < fillRect.top();
+ case Qt::BottomEdge:
+ if (loadedTable.height() <= 1)
+ return false;
+ return loadedTableInnerRect.bottom() > fillRect.bottom();
+ }
+ Q_TABLEVIEW_UNREACHABLE(tableEdge);
+ return false;
+}
+
+Qt::Edge QQuickTableViewPrivate::nextEdgeToLoad(const QRectF rect)
+{
+ for (Qt::Edge edge : allTableEdges) {
+ if (canLoadTableEdge(edge, rect))
+ return edge;
+ }
+ return Qt::Edge(0);
+}
+
+Qt::Edge QQuickTableViewPrivate::nextEdgeToUnload(const QRectF rect)
+{
+ for (Qt::Edge edge : allTableEdges) {
+ if (canUnloadTableEdge(edge, rect))
+ return edge;
+ }
+ return Qt::Edge(0);
+}
+
+qreal QQuickTableViewPrivate::cellWidth(const QPoint& cell)
+{
+ // If a delegate item has TableView.cellWidth set, then
+ // we prefer that. Otherwise we fall back to use implicitWidth.
+ // Using an items width directly is not an option, since we change
+ // it during layout (which would also cause problems when recycling items).
+ auto const cellItem = loadedTableItem(cell)->item;
+ if (auto const attached = getAttachedObject(cellItem)) {
+ if (!attached->m_cellWidth.isNull)
+ return attached->m_cellWidth;
+ }
+ return cellItem->implicitWidth();
+}
+
+qreal QQuickTableViewPrivate::cellHeight(const QPoint& cell)
+{
+ // If a delegate item has TableView.cellHeight set, then
+ // we prefer that. Otherwise we fall back to use implicitHeight.
+ // Using an items height directly is not an option, since we change
+ // it during layout (which would also cause problems when recycling items).
+ auto const cellItem = loadedTableItem(cell)->item;
+ if (auto const attached = getAttachedObject(cellItem)) {
+ if (!attached->m_cellHeight.isNull)
+ return attached->m_cellHeight;
+ }
+ return cellItem->implicitHeight();
+}
+
+void QQuickTableViewPrivate::calculateColumnWidthsAfterRebuilding()
+{
+ qreal prevColumnWidth = 0;
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ qreal columnWidth = 0;
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row)
+ columnWidth = qMax(columnWidth, cellWidth(QPoint(column, row)));
+
+ if (columnWidth <= 0)
+ columnWidth = kDefaultColumnWidth;
+
+ if (columnWidth == prevColumnWidth)
+ continue;
+
+ columnWidths.append({column, columnWidth});
+ prevColumnWidth = columnWidth;
+ }
+
+ if (columnWidths.isEmpty()) {
+ // Add at least one column, wo we don't need
+ // to check if the vector is empty elsewhere.
+ columnWidths.append({0, 0});
+ }
+}
+
+void QQuickTableViewPrivate::calculateRowHeightsAfterRebuilding()
+{
+ qreal prevRowHeight = 0;
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ qreal rowHeight = 0;
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column)
+ rowHeight = qMax(rowHeight, cellHeight(QPoint(column, row)));
+
+ if (rowHeight <= 0)
+ rowHeight = kDefaultRowHeight;
+
+ if (rowHeight == prevRowHeight)
+ continue;
+
+ rowHeights.append({row, rowHeight});
+ prevRowHeight = rowHeight;
+ }
+
+ if (rowHeights.isEmpty()) {
+ // Add at least one row, wo we don't need
+ // to check if the vector is empty elsewhere.
+ rowHeights.append({0, 0});
+ }
+}
+
+void QQuickTableViewPrivate::calculateColumnWidth(int column)
+{
+ if (column < columnWidths.last().index) {
+ // We only do the calculation once, and then stick with the size.
+ // See comments inside ColumnRowSize struct.
+ return;
+ }
+
+ qreal columnWidth = 0;
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row)
+ columnWidth = qMax(columnWidth, cellWidth(QPoint(column, row)));
+
+ if (columnWidth <= 0)
+ columnWidth = kDefaultColumnWidth;
+
+ if (columnWidth == columnWidths.last().size)
+ return;
+
+ columnWidths.append({column, columnWidth});
+}
+
+void QQuickTableViewPrivate::calculateRowHeight(int row)
+{
+ if (row < rowHeights.last().index) {
+ // We only do the calculation once, and then stick with the size.
+ // See comments inside ColumnRowSize struct.
+ return;
+ }
+
+ qreal rowHeight = 0;
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column)
+ rowHeight = qMax(rowHeight, cellHeight(QPoint(column, row)));
+
+ if (rowHeight <= 0)
+ rowHeight = kDefaultRowHeight;
+
+ if (rowHeight == rowHeights.last().size)
+ return;
+
+ rowHeights.append({row, rowHeight});
+}
+
+void QQuickTableViewPrivate::calculateEdgeSizeFromLoadRequest()
+{
+ if (tableRebuilding)
+ return;
+
+ switch (loadRequest.edge()) {
+ case Qt::LeftEdge:
+ case Qt::TopEdge:
+ // Flicking left or up through "never loaded" rows/columns is currently
+ // not supported. You always need to start loading the table from the beginning.
+ return;
+ case Qt::RightEdge:
+ if (tableSize.height() > 1)
+ calculateColumnWidth(loadedTable.right());
+ break;
+ case Qt::BottomEdge:
+ if (tableSize.width() > 1)
+ calculateRowHeight(loadedTable.bottom());
+ break;
+ default:
+ Q_TABLEVIEW_UNREACHABLE("This function should not be called when loading top-left item");
+ }
+}
+
+void QQuickTableViewPrivate::calculateTableSize()
+{
+ // tableSize is the same as row and column count, and will always
+ // be the same as the number of rows and columns in the model.
+ Q_Q(QQuickTableView);
+ QSize prevTableSize = tableSize;
+
+ if (delegateModel)
+ tableSize = QSize(delegateModel->columns(), delegateModel->rows());
+ else if (model)
+ tableSize = QSize(1, model->count());
+ else
+ tableSize = QSize(0, 0);
+
+ if (prevTableSize.width() != tableSize.width())
+ emit q->columnsChanged();
+ if (prevTableSize.height() != tableSize.height())
+ emit q->rowsChanged();
+}
+
+qreal QQuickTableViewPrivate::columnWidth(int column)
+{
+ if (!columnWidths.isEmpty()) {
+ // Find the first ColumnRowSize with a column before, or at, the given column
+ auto iter = std::upper_bound(columnWidths.constBegin(), columnWidths.constEnd(),
+ ColumnRowSize{column, -1}, ColumnRowSize::lessThan);
+
+ if (iter == columnWidths.constEnd()) {
+ // If the table is not a list, return the size
+ // of the last recorded ColumnRowSize.
+ if (tableSize.height() > 1)
+ return columnWidths.last().size;
+ } else {
+ // Check if we got an explicit assignment for this column
+ if (iter->index == column)
+ return iter->size;
+
+ // If the table is not a list, return the size of
+ // ColumnRowSize element found before column. Since there
+ // is always an element stored for column 0, this is safe.
+ // Otherwise we continue, and return the size of the delegate
+ // item at the given column instead.
+ if (tableSize.height() > 1)
+ return (iter - 1)->size;
+ }
+ }
+
+ // If we have an item loaded at column, return the width of the item.
+ if (column >= loadedTable.left() && column <= loadedTable.right())
+ return cellWidth(QPoint(column, loadedTable.top()));
+
+ return -1;
+}
+
+qreal QQuickTableViewPrivate::rowHeight(int row)
+{
+ if (!rowHeights.isEmpty()) {
+ // Find the ColumnRowSize assignment before, or at, row
+ auto iter = std::lower_bound(rowHeights.constBegin(), rowHeights.constEnd(),
+ ColumnRowSize{row, -1}, ColumnRowSize::lessThan);
+
+ if (iter == rowHeights.constEnd()) {
+ // If the table is not a list, return the size
+ // of the last recorded ColumnRowSize.
+ if (tableSize.width() > 1)
+ return rowHeights.last().size;
+ } else {
+ // Check if we got an explicit assignment for this row
+ if (iter->index == row)
+ return iter->size;
+
+ // If the table is not a list, return the size of
+ // ColumnRowSize element found before row. Since there
+ // is always an element stored for row 0, this is safe.
+ // Otherwise we continue, and return the size of the delegate
+ // item at the given row instead.
+ if (tableSize.width() > 1)
+ return (iter - 1)->size;
+ }
+ }
+
+ // If we have an item loaded at row, return the height of the item.
+ if (row >= loadedTable.top() && row <= loadedTable.bottom())
+ return cellHeight(QPoint(loadedTable.left(), row));
+
+ return -1;
+}
+
+void QQuickTableViewPrivate::relayoutTable()
+{
+ relayoutTableItems();
+ columnRowPositionsInvalid = false;
+
+ syncLoadedTableRectFromLoadedTable();
+ contentSizeBenchMarkPoint = QPoint(-1, -1);
+ updateContentWidth();
+ updateContentHeight();
+}
+
+void QQuickTableViewPrivate::relayoutTableItems()
+{
+ qCDebug(lcTableViewDelegateLifecycle);
+ columnRowPositionsInvalid = false;
+
+ qreal nextColumnX = loadedTableOuterRect.x();
+ qreal nextRowY = loadedTableOuterRect.y();
+
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ // Adjust the geometry of all cells in the current column
+ qreal width = columnWidth(column);
+ if (width <= 0)
+ width = kDefaultColumnWidth;
+
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ auto item = loadedTableItem(QPoint(column, row));
+ QRectF geometry = item->geometry();
+ geometry.moveLeft(nextColumnX);
+ geometry.setWidth(width);
+ item->setGeometry(geometry);
+ }
+
+ nextColumnX += width + cellSpacing.width();
+ }
+
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ // Adjust the geometry of all cells in the current row
+ qreal height = rowHeight(row);
+ if (height <= 0)
+ height = kDefaultRowHeight;
+
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ auto item = loadedTableItem(QPoint(column, row));
+ QRectF geometry = item->geometry();
+ geometry.moveTop(nextRowY);
+ geometry.setHeight(height);
+ item->setGeometry(geometry);
+ }
+
+ nextRowY += height + cellSpacing.height();
+ }
+
+ if (Q_UNLIKELY(lcTableViewDelegateLifecycle().isDebugEnabled())) {
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ QPoint cell = QPoint(column, row);
+ qCDebug(lcTableViewDelegateLifecycle()) << "relayout item:" << cell << loadedTableItem(cell)->geometry();
+ }
+ }
+ }
+}
+
+void QQuickTableViewPrivate::layoutVerticalEdge(Qt::Edge tableEdge)
+{
+ int column = (tableEdge == Qt::LeftEdge) ? loadedTable.left() : loadedTable.right();
+ QPoint neighbourDirection = (tableEdge == Qt::LeftEdge) ? kRight : kLeft;
+ qreal left = -1;
+
+ qreal width = columnWidth(column);
+ if (width <= 0)
+ width = kDefaultColumnWidth;
+
+ for (int row = loadedTable.top(); row <= loadedTable.bottom(); ++row) {
+ auto fxTableItem = loadedTableItem(QPoint(column, row));
+ auto const neighbourItem = itemNextTo(fxTableItem, neighbourDirection);
+
+ QRectF geometry = fxTableItem->geometry();
+ geometry.setWidth(width);
+ geometry.setHeight(neighbourItem->geometry().height());
+
+ if (left == -1) {
+ // left will be the same for all items in the
+ // column, so do the calculation once.
+ left = tableEdge == Qt::LeftEdge ?
+ neighbourItem->geometry().left() - cellSpacing.width() - geometry.width() :
+ neighbourItem->geometry().right() + cellSpacing.width();
+ }
+
+ geometry.moveLeft(left);
+ geometry.moveTop(neighbourItem->geometry().top());
+
+ fxTableItem->setGeometry(geometry);
+ fxTableItem->setVisible(true);
+
+ qCDebug(lcTableViewDelegateLifecycle()) << "layout item:" << QPoint(column, row) << fxTableItem->geometry();
+ }
+}
+
+void QQuickTableViewPrivate::layoutHorizontalEdge(Qt::Edge tableEdge)
+{
+ int row = (tableEdge == Qt::TopEdge) ? loadedTable.top() : loadedTable.bottom();
+ QPoint neighbourDirection = (tableEdge == Qt::TopEdge) ? kDown : kUp;
+ qreal top = -1;
+
+ qreal height = rowHeight(row);
+ if (height <= 0)
+ height = kDefaultRowHeight;
+
+ for (int column = loadedTable.left(); column <= loadedTable.right(); ++column) {
+ auto fxTableItem = loadedTableItem(QPoint(column, row));
+ auto const neighbourItem = itemNextTo(fxTableItem, neighbourDirection);
+
+ QRectF geometry = fxTableItem->geometry();
+ geometry.setWidth(neighbourItem->geometry().width());
+ geometry.setHeight(height);
+
+ if (top == -1) {
+ // top will be the same for all items in the
+ // row, so do the calculation once.
+ top = tableEdge == Qt::TopEdge ?
+ neighbourItem->geometry().top() - cellSpacing.height() - geometry.height() :
+ neighbourItem->geometry().bottom() + cellSpacing.height();
+ }
+
+ geometry.moveTop(top);
+ geometry.moveLeft(neighbourItem->geometry().left());
+
+ fxTableItem->setGeometry(geometry);
+ fxTableItem->setVisible(true);
+
+ qCDebug(lcTableViewDelegateLifecycle()) << "layout item:" << QPoint(column, row) << fxTableItem->geometry();
+ }
+}
+
+void QQuickTableViewPrivate::layoutTopLeftItem()
+{
+ // ###todo: support starting with other top-left items than 0,0
+ const QPoint cell = loadRequest.firstCell();
+ Q_TABLEVIEW_ASSERT(cell == QPoint(0, 0), loadRequest.toString());
+ auto topLeftItem = loadedTableItem(cell);
+ auto item = topLeftItem->item;
+
+ qreal width = cellWidth(cell);
+ qreal height = cellHeight(cell);
+ if (width <= 0)
+ width = kDefaultColumnWidth;
+ if (height <= 0)
+ height = kDefaultRowHeight;
+
+ item->setPosition(QPoint(tableMargins.left(), tableMargins.top()));
+ item->setSize(QSizeF(width, height));
+ topLeftItem->setVisible(true);
+ qCDebug(lcTableViewDelegateLifecycle) << "geometry:" << topLeftItem->geometry();
+}
+
+void QQuickTableViewPrivate::layoutTableEdgeFromLoadRequest()
+{
+ switch (loadRequest.edge()) {
+ case Qt::LeftEdge:
+ case Qt::RightEdge:
+ layoutVerticalEdge(loadRequest.edge());
+ break;
+ case Qt::TopEdge:
+ case Qt::BottomEdge:
+ layoutHorizontalEdge(loadRequest.edge());
+ break;
+ default:
+ layoutTopLeftItem();
+ break;
+ }
+}
+
+void QQuickTableViewPrivate::cancelLoadRequest()
+{
+ loadRequest.markAsDone();
+ model->cancel(modelIndexAtCell(loadRequest.currentCell()));
+
+ if (tableInvalid) {
+ // No reason to rollback already loaded edge items
+ // since we anyway are about to reload all items.
+ return;
+ }
+
+ if (loadRequest.atBeginning()) {
+ // No items have yet been loaded, so nothing to unload
+ return;
+ }
+
+ QLine rollbackItems;
+ rollbackItems.setP1(loadRequest.firstCell());
+ rollbackItems.setP2(loadRequest.previousCell());
+ qCDebug(lcTableViewDelegateLifecycle()) << "rollback:" << rollbackItems << tableLayoutToString();
+ unloadItems(rollbackItems);
+}
+
+void QQuickTableViewPrivate::processLoadRequest()
+{
+ Q_TABLEVIEW_ASSERT(loadRequest.isActive(), "");
+
+ while (loadRequest.hasCurrentCell()) {
+ QPoint cell = loadRequest.currentCell();
+ FxTableItem *fxTableItem = loadFxTableItem(cell, loadRequest.incubationMode());
+
+ if (!fxTableItem) {
+ // Requested item is not yet ready. Just leave, and wait for this
+ // function to be called again when the item is ready.
+ return;
+ }
+
+ loadedItems.insert(modelIndexAtCell(cell), fxTableItem);
+ loadRequest.moveToNextCell();
+ }
+
+ qCDebug(lcTableViewDelegateLifecycle()) << "all items loaded!";
+
+ syncLoadedTableFromLoadRequest();
+ calculateEdgeSizeFromLoadRequest();
+ layoutTableEdgeFromLoadRequest();
+
+ syncLoadedTableRectFromLoadedTable();
+ enforceFirstRowColumnAtOrigo();
+ updateContentWidth();
+ updateContentHeight();
+
+ loadRequest.markAsDone();
+ qCDebug(lcTableViewDelegateLifecycle()) << "request completed! Table:" << tableLayoutToString();
+}
+
+void QQuickTableViewPrivate::beginRebuildTable()
+{
+ qCDebug(lcTableViewDelegateLifecycle());
+ clear();
+ tableInvalid = false;
+ tableRebuilding = true;
+ calculateTableSize();
+ loadInitialTopLeftItem();
+ loadAndUnloadVisibleEdges();
+}
+
+void QQuickTableViewPrivate::endRebuildTable()
+{
+ tableRebuilding = false;
+
+ if (loadedItems.isEmpty())
+ return;
+
+ // We don't calculate row/column sizes for lists.
+ // Instead we we use the sizes of the items directly
+ // unless for explicit row/column size assignments.
+ columnWidths.clear();
+ rowHeights.clear();
+ if (tableSize.height() > 1)
+ calculateColumnWidthsAfterRebuilding();
+ if (tableSize.width() > 1)
+ calculateRowHeightsAfterRebuilding();
+
+ relayoutTable();
+ qCDebug(lcTableViewDelegateLifecycle()) << tableLayoutToString();
+}
+
+void QQuickTableViewPrivate::loadInitialTopLeftItem()
+{
+ Q_TABLEVIEW_ASSERT(loadedItems.isEmpty(), "");
+
+ if (tableSize.isEmpty())
+ return;
+
+ if (model->count() == 0)
+ return;
+
+ // Load top-left item. After loaded, loadItemsInsideRect() will take
+ // care of filling out the rest of the table.
+ loadRequest.begin(QPoint(0, 0), QQmlIncubator::AsynchronousIfNested);
+ processLoadRequest();
+}
+
+void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
+{
+ unloadItems(rectangleEdge(loadedTable, edge));
+ loadedTable = expandedRect(loadedTable, edge, -1);
+ syncLoadedTableRectFromLoadedTable();
+ qCDebug(lcTableViewDelegateLifecycle) << tableLayoutToString();
+}
+
+void QQuickTableViewPrivate::loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode)
+{
+ QLine cellsToLoad = rectangleEdge(expandedRect(loadedTable, edge, 1), edge);
+ loadRequest.begin(cellsToLoad, edge, incubationMode);
+ processLoadRequest();
+}
+
+void QQuickTableViewPrivate::loadAndUnloadVisibleEdges()
+{
+ // Unload table edges that have been moved outside the visible part of the
+ // table (including buffer area), and load new edges that has been moved inside.
+ // Note: an important point is that we always keep the table rectangular
+ // and without holes to reduce complexity (we never leave the table in
+ // a half-loaded state, or keep track of multiple patches).
+ // We load only one edge (row or column) at a time. This is especially
+ // important when loading into the buffer, since we need to be able to
+ // cancel the buffering quickly if the user starts to flick, and then
+ // focus all further loading on the edges that are flicked into view.
+
+ if (loadRequest.isActive()) {
+ // Don't start loading more edges while we're
+ // already waiting for another one to load.
+ return;
+ }
+
+ if (loadedItems.isEmpty()) {
+ // We need at least the top-left item to be loaded before we can
+ // start loading edges around it. Not having a top-left item at
+ // this point means that the model is empty (or no delegate).
+ return;
+ }
+
+ const QRectF unloadRect = hasBufferedItems ? bufferRect() : viewportRect;
+ bool tableModified;
+
+ do {
+ tableModified = false;
+
+ if (Qt::Edge edge = nextEdgeToUnload(unloadRect)) {
+ tableModified = true;
+ unloadEdge(edge);
+ }
+
+ if (Qt::Edge edge = nextEdgeToLoad(viewportRect)) {
+ tableModified = true;
+ loadEdge(edge, QQmlIncubator::AsynchronousIfNested);
+ if (loadRequest.isActive())
+ return;
+ }
+ } while (tableModified);
+
+}
+
+void QQuickTableViewPrivate::loadBuffer()
+{
+ // Rather than making sure to stop the timer from all locations that can
+ // violate the "buffering allowed" state, we just check that we're in the
+ // right state here before we start buffering.
+ if (cacheBuffer <= 0 || loadRequest.isActive() || loadedItems.isEmpty())
+ return;
+
+ qCDebug(lcTableViewDelegateLifecycle());
+ const QRectF loadRect = bufferRect();
+ while (Qt::Edge edge = nextEdgeToLoad(loadRect)) {
+ loadEdge(edge, QQmlIncubator::Asynchronous);
+ if (loadRequest.isActive())
+ break;
+ }
+
+ hasBufferedItems = true;
+}
+
+void QQuickTableViewPrivate::unloadBuffer()
+{
+ if (!hasBufferedItems)
+ return;
+
+ qCDebug(lcTableViewDelegateLifecycle());
+ hasBufferedItems = false;
+ cacheBufferDelayTimer.stop();
+ if (loadRequest.isActive())
+ cancelLoadRequest();
+ while (Qt::Edge edge = nextEdgeToUnload(viewportRect))
+ unloadEdge(edge);
+}
+
+QRectF QQuickTableViewPrivate::bufferRect()
+{
+ return viewportRect.adjusted(-cacheBuffer, -cacheBuffer, cacheBuffer, cacheBuffer);
+}
+
+void QQuickTableViewPrivate::invalidateTable() {
+ tableInvalid = true;
+ if (loadRequest.isActive())
+ cancelLoadRequest();
+ q_func()->polish();
+}
+
+void QQuickTableViewPrivate::invalidateColumnRowPositions() {
+ columnRowPositionsInvalid = true;
+ q_func()->polish();
+}
+
+void QQuickTableViewPrivate::updatePolish()
+{
+ // Whenever something changes, e.g viewport moves, spacing is set to a
+ // new value, model changes etc, this function will end up being called. Here
+ // we check what needs to be done, and load/unload cells accordingly.
+ Q_Q(QQuickTableView);
+
+ if (loadRequest.isActive()) {
+ // We're currently loading items async to build a new edge in the table. We see the loading
+ // as an atomic operation, which means that we don't continue doing anything else until all
+ // items have been received and laid out. Note that updatePolish is then called once more
+ // after the loadRequest has completed to handle anything that might have occurred in-between.
+ return;
+ }
+
+ // viewportRect describes the part of the content view that is actually visible. Since a
+ // negative width/height can happen (e.g during start-up), we check for this to avoid rebuilding
+ // the table (and e.g calculate initial row/column sizes) based on a premature viewport rect.
+ viewportRect = QRectF(q->contentX(), q->contentY(), q->width(), q->height());
+ if (!viewportRect.isValid())
+ return;
+
+ if (tableInvalid) {
+ beginRebuildTable();
+ if (loadRequest.isActive())
+ return;
+ }
+
+ if (tableRebuilding)
+ endRebuildTable();
+
+ if (loadedItems.isEmpty()) {
+ qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded, meaning empty model or no delegate";
+ return;
+ }
+
+ if (columnRowPositionsInvalid)
+ relayoutTable();
+
+ if (hasBufferedItems && nextEdgeToLoad(viewportRect)) {
+ // We are about to load more edges, so trim down the table as much
+ // as possible to avoid loading cells that are outside the viewport.
+ unloadBuffer();
+ }
+
+ loadAndUnloadVisibleEdges();
+
+ if (loadRequest.isActive())
+ return;
+
+ if (cacheBuffer > 0) {
+ // When polish hasn't been called for a while (which means that the viewport
+ // rect hasn't changed), we start buffering items. We delay this operation by
+ // using a timer to increase performance (by not loading hidden items) while
+ // the user is flicking.
+ cacheBufferDelayTimer.start(kBufferTimerInterval);
+ }
+}
+
+void QQuickTableViewPrivate::createWrapperModel()
+{
+ Q_Q(QQuickTableView);
+
+ delegateModel = new QQmlDelegateModel(qmlContext(q), q);
+ if (q->isComponentComplete())
+ delegateModel->componentComplete();
+ model = delegateModel;
+}
+
+void QQuickTableViewPrivate::itemCreatedCallback(int modelIndex, QObject*)
+{
+ if (blockItemCreatedCallback)
+ return;
+
+ qCDebug(lcTableViewDelegateLifecycle) << "item done loading:"
+ << cellAtModelIndex(modelIndex);
+
+ // Since the item we waited for has finished incubating, we can
+ // continue with the load request. processLoadRequest will
+ // ask the model for the requested item once more, which will be
+ // quick since the model has cached it.
+ processLoadRequest();
+ loadAndUnloadVisibleEdges();
+ updatePolish();
+}
+
+void QQuickTableViewPrivate::initItemCallback(int modelIndex, QObject *object)
+{
+ Q_UNUSED(modelIndex);
+ auto attached = getAttachedObject(object);
+ if (!attached)
+ return;
+
+ attached->setTableView(q_func());
+}
+
+void QQuickTableViewPrivate::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
+{
+ Q_UNUSED(changeSet);
+ Q_UNUSED(reset);
+
+ // TODO: implement fine-grained support for model changes
+ invalidateTable();
+}
+
+QQuickTableView::QQuickTableView(QQuickItem *parent)
+ : QQuickFlickable(*(new QQuickTableViewPrivate), parent)
+{
+}
+
+int QQuickTableView::rows() const
+{
+ return d_func()->tableSize.height();
+}
+
+int QQuickTableView::columns() const
+{
+ return d_func()->tableSize.width();
+}
+
+qreal QQuickTableView::rowSpacing() const
+{
+ return d_func()->cellSpacing.height();
+}
+
+void QQuickTableView::setRowSpacing(qreal spacing)
+{
+ Q_D(QQuickTableView);
+ if (qFuzzyCompare(d->cellSpacing.height(), spacing))
+ return;
+
+ d->cellSpacing.setHeight(spacing);
+ d->invalidateColumnRowPositions();
+ emit rowSpacingChanged();
+}
+
+qreal QQuickTableView::columnSpacing() const
+{
+ return d_func()->cellSpacing.width();
+}
+
+void QQuickTableView::setColumnSpacing(qreal spacing)
+{
+ Q_D(QQuickTableView);
+ if (qFuzzyCompare(d->cellSpacing.width(), spacing))
+ return;
+
+ d->cellSpacing.setWidth(spacing);
+ d->invalidateColumnRowPositions();
+ emit columnSpacingChanged();
+}
+
+qreal QQuickTableView::topMargin() const
+{
+ return d_func()->tableMargins.top();
+}
+
+void QQuickTableView::setTopMargin(qreal margin)
+{
+ Q_D(QQuickTableView);
+ if (qt_is_nan(margin))
+ return;
+ if (qFuzzyCompare(d->tableMargins.top(), margin))
+ return;
+
+ d->tableMargins.setTop(margin);
+ d->invalidateColumnRowPositions();
+ emit topMarginChanged();
+}
+
+qreal QQuickTableView::bottomMargin() const
+{
+ return d_func()->tableMargins.bottom();
+}
+
+void QQuickTableView::setBottomMargin(qreal margin)
+{
+ Q_D(QQuickTableView);
+ if (qt_is_nan(margin))
+ return;
+ if (qFuzzyCompare(d->tableMargins.bottom(), margin))
+ return;
+
+ d->tableMargins.setBottom(margin);
+ d->invalidateColumnRowPositions();
+ emit bottomMarginChanged();
+}
+
+qreal QQuickTableView::leftMargin() const
+{
+ return d_func()->tableMargins.left();
+}
+
+void QQuickTableView::setLeftMargin(qreal margin)
+{
+ Q_D(QQuickTableView);
+ if (qt_is_nan(margin))
+ return;
+ if (qFuzzyCompare(d->tableMargins.left(), margin))
+ return;
+
+ d->tableMargins.setLeft(margin);
+ d->invalidateColumnRowPositions();
+ emit leftMarginChanged();
+}
+
+qreal QQuickTableView::rightMargin() const
+{
+ return d_func()->tableMargins.right();
+}
+
+void QQuickTableView::setRightMargin(qreal margin)
+{
+ Q_D(QQuickTableView);
+ if (qt_is_nan(margin))
+ return;
+ if (qFuzzyCompare(d->tableMargins.right(), margin))
+ return;
+
+ d->tableMargins.setRight(margin);
+ d->invalidateColumnRowPositions();
+ emit rightMarginChanged();
+}
+
+int QQuickTableView::cacheBuffer() const
+{
+ return d_func()->cacheBuffer;
+}
+
+void QQuickTableView::setCacheBuffer(int newBuffer)
+{
+ Q_D(QQuickTableView);
+ if (d->cacheBuffer == newBuffer || newBuffer < 0)
+ return;
+
+ d->cacheBuffer = newBuffer;
+
+ if (newBuffer == 0)
+ d->unloadBuffer();
+
+ emit cacheBufferChanged();
+ polish();
+}
+
+QVariant QQuickTableView::model() const
+{
+ return d_func()->modelVariant;
+}
+
+void QQuickTableView::setModel(const QVariant &newModel)
+{
+ Q_D(QQuickTableView);
+
+ d->modelVariant = newModel;
+ QVariant effectiveModelVariant = d->modelVariant;
+ if (effectiveModelVariant.userType() == qMetaTypeId<QJSValue>())
+ effectiveModelVariant = effectiveModelVariant.value<QJSValue>().toVariant();
+
+ if (d->model) {
+ QObjectPrivate::disconnect(d->model, &QQmlInstanceModel::createdItem, d, &QQuickTableViewPrivate::itemCreatedCallback);
+ QObjectPrivate::disconnect(d->model, &QQmlInstanceModel::initItem, d, &QQuickTableViewPrivate::initItemCallback);
+ QObjectPrivate::disconnect(d->model, &QQmlInstanceModel::modelUpdated, d, &QQuickTableViewPrivate::modelUpdated);
+ }
+
+ const auto instanceModel = qobject_cast<QQmlInstanceModel *>(qvariant_cast<QObject*>(effectiveModelVariant));
+
+ if (instanceModel) {
+ if (d->delegateModel)
+ delete d->delegateModel;
+ d->model = instanceModel;
+ d->delegateModel = qmlobject_cast<QQmlDelegateModel *>(instanceModel);
+ } else {
+ if (!d->delegateModel)
+ d->createWrapperModel();
+ QQmlDelegateModelPrivate::get(d->delegateModel)->m_useFirstColumnOnly = false;
+ d->delegateModel->setModel(effectiveModelVariant);
+ }
+
+ Q_ASSERT(d->model);
+ QObjectPrivate::connect(d->model, &QQmlInstanceModel::createdItem, d, &QQuickTableViewPrivate::itemCreatedCallback);
+ QObjectPrivate::connect(d->model, &QQmlInstanceModel::initItem, d, &QQuickTableViewPrivate::initItemCallback);
+ QObjectPrivate::connect(d->model, &QQmlInstanceModel::modelUpdated, d, &QQuickTableViewPrivate::modelUpdated);
+
+ d->invalidateTable();
+
+ emit modelChanged();
+}
+
+QQmlComponent *QQuickTableView::delegate() const
+{
+ Q_D(const QQuickTableView);
+ if (d->delegateModel)
+ return d->delegateModel->delegate();
+
+ return nullptr;
+}
+
+void QQuickTableView::setDelegate(QQmlComponent *newDelegate)
+{
+ Q_D(QQuickTableView);
+ if (newDelegate == delegate())
+ return;
+
+ if (!d->delegateModel)
+ d->createWrapperModel();
+
+ d->delegateModel->setDelegate(newDelegate);
+ d->invalidateTable();
+
+ emit delegateChanged();
+}
+
+QQuickTableViewAttached *QQuickTableView::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickTableViewAttached(obj);
+}
+
+void QQuickTableView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickTableView);
+ QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
+ // We update the viewport rect from within updatePolish to
+ // ensure that we update when we're ready to update, and not
+ // while we're in the middle of loading/unloading edges.
+ d->updatePolish();
+}
+
+void QQuickTableView::viewportMoved(Qt::Orientations orientation)
+{
+ Q_D(QQuickTableView);
+ QQuickFlickable::viewportMoved(orientation);
+ // We update the viewport rect from within updatePolish to
+ // ensure that we update when we're ready to update, and not
+ // while we're in the middle of loading/unloading edges.
+ d->updatePolish();
+}
+
+void QQuickTableView::componentComplete()
+{
+ Q_D(QQuickTableView);
+
+ if (!d->model)
+ setModel(QVariant());
+
+ if (d->delegateModel)
+ d->delegateModel->componentComplete();
+
+ QQuickFlickable::componentComplete();
+}
+
+#include "moc_qquicktableview_p.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
new file mode 100644
index 0000000000..d2c3f17bc4
--- /dev/null
+++ b/src/quick/items/qquicktableview_p.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKTABLEVIEW_P_H
+#define QQUICKTABLEVIEW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qpointer.h>
+#include <QtQuick/private/qtquickglobal_p.h>
+#include <QtQuick/private/qquickflickable_p.h>
+#include <QtQml/private/qqmlnullablevalue_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTableViewAttached;
+class QQuickTableViewPrivate;
+class QQmlChangeSet;
+
+class Q_QUICK_PRIVATE_EXPORT QQuickTableView : public QQuickFlickable
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int rows READ rows NOTIFY rowsChanged)
+ Q_PROPERTY(int columns READ columns NOTIFY columnsChanged)
+ Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
+ Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+
+public:
+ QQuickTableView(QQuickItem *parent = nullptr);
+
+ int rows() const;
+ int columns() const;
+
+ qreal rowSpacing() const;
+ void setRowSpacing(qreal spacing);
+
+ qreal columnSpacing() const;
+ void setColumnSpacing(qreal spacing);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal margin);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal margin);
+
+ qreal leftMargin() const;
+ void setLeftMargin(qreal margin);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal margin);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int newBuffer);
+
+ QVariant model() const;
+ void setModel(const QVariant &newModel);
+
+ QQmlComponent *delegate() const;
+ void setDelegate(QQmlComponent *);
+
+ static QQuickTableViewAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void rowsChanged();
+ void columnsChanged();
+ void rowSpacingChanged();
+ void columnSpacingChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void cacheBufferChanged();
+ void modelChanged();
+ void delegateChanged();
+
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
+ void viewportMoved(Qt::Orientations orientation) override;
+ void componentComplete() override;
+
+private:
+ Q_DISABLE_COPY(QQuickTableView)
+ Q_DECLARE_PRIVATE(QQuickTableView)
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickTableViewAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQuickTableView *tableView READ tableView NOTIFY tableViewChanged)
+ Q_PROPERTY(qreal cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
+ Q_PROPERTY(qreal cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
+
+public:
+ QQuickTableViewAttached(QObject *parent)
+ : QObject(parent) {}
+
+ QQuickTableView *tableView() const { return m_tableview; }
+ void setTableView(QQuickTableView *newTableView) {
+ if (newTableView == m_tableview)
+ return;
+ m_tableview = newTableView;
+ Q_EMIT tableViewChanged();
+ }
+
+ qreal cellWidth() const { return m_cellWidth; }
+ void setCellWidth(qreal newWidth) {
+ if (newWidth == m_cellWidth)
+ return;
+ m_cellWidth = newWidth;
+ Q_EMIT cellWidthChanged();
+ }
+
+ qreal cellHeight() const { return m_cellHeight; }
+ void setCellHeight(qreal newHeight) {
+ if (newHeight == m_cellHeight)
+ return;
+ m_cellHeight = newHeight;
+ Q_EMIT cellHeightChanged();
+ }
+
+Q_SIGNALS:
+ void tableViewChanged();
+ void cellWidthChanged();
+ void cellHeightChanged();
+
+private:
+ QPointer<QQuickTableView> m_tableview;
+ QQmlNullableValue<qreal> m_cellWidth;
+ QQmlNullableValue<qreal> m_cellHeight;
+
+ friend class QQuickTableViewPrivate;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickTableView)
+QML_DECLARE_TYPEINFO(QQuickTableView, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKTABLEVIEW_P_H
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
new file mode 100644
index 0000000000..9376ad386c
--- /dev/null
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -0,0 +1,342 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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 "qquicktableview_p.h"
+
+#include <QtCore/qtimer.h>
+#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <QtQml/private/qqmlincubator_p.h>
+#include <QtQml/private/qqmlchangeset_p.h>
+#include <QtQml/qqmlinfo.h>
+
+#include <QtQuick/private/qquickflickable_p_p.h>
+#include <QtQuick/private/qquickitemviewfxitem_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcTableViewDelegateLifecycle)
+
+static const int kDefaultCacheBuffer = 300;
+static const qreal kDefaultRowHeight = 50;
+static const qreal kDefaultColumnWidth = 50;
+
+class FxTableItem;
+
+class Q_QML_AUTOTEST_EXPORT QQuickTableViewPrivate : public QQuickFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QQuickTableView)
+
+public:
+ class TableEdgeLoadRequest
+ {
+ // Whenever we need to load new rows or columns in the
+ // table, we fill out a TableEdgeLoadRequest.
+ // TableEdgeLoadRequest is just a struct that keeps track
+ // of which cells that needs to be loaded, and which cell
+ // the table is currently loading. The loading itself is
+ // done by QQuickTableView.
+
+ public:
+ void begin(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode)
+ {
+ Q_ASSERT(!active);
+ active = true;
+ tableEdge = Qt::Edge(0);
+ tableCells = QLine(cell, cell);
+ mode = incubationMode;
+ cellCount = 1;
+ currentIndex = 0;
+ qCDebug(lcTableViewDelegateLifecycle()) << "begin top-left:" << toString();
+ }
+
+ void begin(const QLine cellsToLoad, Qt::Edge edgeToLoad, QQmlIncubator::IncubationMode incubationMode)
+ {
+ Q_ASSERT(!active);
+ active = true;
+ tableEdge = edgeToLoad;
+ tableCells = cellsToLoad;
+ mode = incubationMode;
+ cellCount = tableCells.x2() - tableCells.x1() + tableCells.y2() - tableCells.y1() + 1;
+ currentIndex = 0;
+ qCDebug(lcTableViewDelegateLifecycle()) << "begin:" << toString();
+ }
+
+ inline void markAsDone() { active = false; }
+ inline bool isActive() { return active; }
+
+ inline QPoint firstCell() { return tableCells.p1(); }
+ inline QPoint lastCell() { return tableCells.p2(); }
+ inline QPoint currentCell() { return cellAt(currentIndex); }
+ inline QPoint previousCell() { return cellAt(currentIndex - 1); }
+
+ inline bool atBeginning() { return currentIndex == 0; }
+ inline bool hasCurrentCell() { return currentIndex < cellCount; }
+ inline void moveToNextCell() { ++currentIndex; }
+
+ inline Qt::Edge edge() { return tableEdge; }
+ inline QQmlIncubator::IncubationMode incubationMode() { return mode; }
+
+ QString toString()
+ {
+ QString str;
+ QDebug dbg(&str);
+ dbg.nospace() << "TableSectionLoadRequest(" << "edge:"
+ << tableEdge << " cells:" << tableCells << " incubation:";
+
+ switch (mode) {
+ case QQmlIncubator::Asynchronous:
+ dbg << "Asynchronous";
+ break;
+ case QQmlIncubator::AsynchronousIfNested:
+ dbg << "AsynchronousIfNested";
+ break;
+ case QQmlIncubator::Synchronous:
+ dbg << "Synchronous";
+ break;
+ }
+
+ return str;
+ }
+
+ private:
+ Qt::Edge tableEdge = Qt::Edge(0);
+ QLine tableCells;
+ int currentIndex = 0;
+ int cellCount = 0;
+ bool active = false;
+ QQmlIncubator::IncubationMode mode = QQmlIncubator::AsynchronousIfNested;
+
+ QPoint cellAt(int index)
+ {
+ int x = tableCells.p1().x() + (tableCells.dx() ? index : 0);
+ int y = tableCells.p1().y() + (tableCells.dy() ? index : 0);
+ return QPoint(x, y);
+ }
+ };
+
+ struct ColumnRowSize
+ {
+ // ColumnRowSize is a helper class for storing row heights
+ // and column widths. We calculate the average width of a column
+ // the first time it's scrolled into view based on the size of
+ // the loaded items in the new column. Since we never load more items
+ // that what fits inside the viewport (cachebuffer aside), this calculation
+ // would be different depending on which row you were at when the column
+ // was scrolling in. To avoid that a column resizes when it's scrolled
+ // in and out and in again, we store its width. But to avoid storing
+ // the width for all columns, we choose to only store the width if it
+ // differs from the column(s) to the left. The same logic applies for row heights.
+ // 'index' translates to either 'row' or 'column'.
+ int index;
+ qreal size;
+
+ static bool lessThan(const ColumnRowSize& a, const ColumnRowSize& b)
+ {
+ return a.index < b.index;
+ }
+ };
+
+public:
+ QQuickTableViewPrivate();
+ ~QQuickTableViewPrivate() override;
+
+ static inline QQuickTableViewPrivate *get(QQuickTableView *q) { return q->d_func(); }
+
+ void updatePolish() override;
+
+public:
+ QHash<int, FxTableItem *> loadedItems;
+
+ // model, delegateModel and modelVariant all points to the same model. modelVariant
+ // is the model assigned by the user. And delegateModel is the wrapper model we create
+ // around it. But if the model is an instance model directly, we cannot wrap it, so
+ // we need a pointer for that case as well.
+ QQmlInstanceModel* model = nullptr;
+ QPointer<QQmlDelegateModel> delegateModel = nullptr;
+ QVariant modelVariant;
+
+ // loadedTable describes the table cells that are currently loaded (from top left
+ // row/column to bottom right row/column). loadedTableOuterRect describes the actual
+ // pixels that those cells cover, and is matched agains the viewport to determine when
+ // we need to fill up with more rows/columns. loadedTableInnerRect describes the pixels
+ // that the loaded table covers if you remove one row/column on each side of the table, and
+ // is used to determine rows/columns that are no longer visible and can be unloaded.
+ QRect loadedTable;
+ QRectF loadedTableOuterRect;
+ QRectF loadedTableInnerRect;
+
+ QRectF viewportRect = QRectF(0, 0, -1, -1);
+
+ QSize tableSize;
+
+ TableEdgeLoadRequest loadRequest;
+
+ QPoint contentSizeBenchMarkPoint = QPoint(-1, -1);
+ QSizeF cellSpacing;
+ QMarginsF tableMargins;
+
+ int cacheBuffer = kDefaultCacheBuffer;
+ QTimer cacheBufferDelayTimer;
+ bool hasBufferedItems = false;
+
+ bool blockItemCreatedCallback = false;
+ bool tableInvalid = false;
+ bool tableRebuilding = false;
+ bool columnRowPositionsInvalid = false;
+
+ QVector<ColumnRowSize> columnWidths;
+ QVector<ColumnRowSize> rowHeights;
+
+ const static QPoint kLeft;
+ const static QPoint kRight;
+ const static QPoint kUp;
+ const static QPoint kDown;
+
+#ifdef QT_DEBUG
+ QString forcedIncubationMode = qEnvironmentVariable("QT_TABLEVIEW_INCUBATION_MODE");
+#endif
+
+public:
+ QQuickTableViewAttached *getAttachedObject(const QObject *object) const;
+
+ int modelIndexAtCell(const QPoint &cell) const;
+ QPoint cellAtModelIndex(int modelIndex) const;
+
+ void calculateColumnWidthsAfterRebuilding();
+ void calculateRowHeightsAfterRebuilding();
+ void calculateColumnWidth(int column);
+ void calculateRowHeight(int row);
+ void calculateEdgeSizeFromLoadRequest();
+ void calculateTableSize();
+
+ qreal columnWidth(int column);
+ qreal rowHeight(int row);
+
+ void relayoutTable();
+ void relayoutTableItems();
+
+ void layoutVerticalEdge(Qt::Edge tableEdge);
+ void layoutHorizontalEdge(Qt::Edge tableEdge);
+ void layoutTopLeftItem();
+ void layoutTableEdgeFromLoadRequest();
+
+ void updateContentWidth();
+ void updateContentHeight();
+
+ void enforceFirstRowColumnAtOrigo();
+ void syncLoadedTableRectFromLoadedTable();
+ void syncLoadedTableFromLoadRequest();
+
+ bool canLoadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
+ bool canUnloadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
+ Qt::Edge nextEdgeToLoad(const QRectF rect);
+ Qt::Edge nextEdgeToUnload(const QRectF rect);
+
+ qreal cellWidth(const QPoint &cell);
+ qreal cellHeight(const QPoint &cell);
+
+ FxTableItem *loadedTableItem(const QPoint &cell) const;
+ FxTableItem *itemNextTo(const FxTableItem *fxTableItem, const QPoint &direction) const;
+ FxTableItem *createFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode);
+ FxTableItem *loadFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode);
+
+ void releaseItem(FxTableItem *fxTableItem);
+ void releaseLoadedItems();
+ void clear();
+
+ void unloadItem(const QPoint &cell);
+ void unloadItems(const QLine &items);
+
+ void loadInitialTopLeftItem();
+ void loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode);
+ void unloadEdge(Qt::Edge edge);
+ void loadAndUnloadVisibleEdges();
+ void cancelLoadRequest();
+ void processLoadRequest();
+ void beginRebuildTable();
+ void endRebuildTable();
+
+ void loadBuffer();
+ void unloadBuffer();
+ QRectF bufferRect();
+
+ void invalidateTable();
+ void invalidateColumnRowPositions();
+
+ void createWrapperModel();
+
+ void initItemCallback(int modelIndex, QObject *item);
+ void itemCreatedCallback(int modelIndex, QObject *object);
+ void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
+
+ inline QString tableLayoutToString() const;
+ void dumpTable() const;
+};
+
+class FxTableItem : public QQuickItemViewFxItem
+{
+public:
+ FxTableItem(QQuickItem *item, QQuickTableView *table, bool own)
+ : QQuickItemViewFxItem(item, own, QQuickTableViewPrivate::get(table))
+ {
+ }
+
+ qreal position() const override { return 0; }
+ qreal endPosition() const override { return 0; }
+ qreal size() const override { return 0; }
+ qreal sectionSize() const override { return 0; }
+ bool contains(qreal, qreal) const override { return false; }
+
+ QPoint cell;
+};
+
+Q_DECLARE_TYPEINFO(QQuickTableViewPrivate::ColumnRowSize, Q_PRIMITIVE_TYPE);
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 76720e5c5d..3c260165f7 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)
, polishSize(false)
+ , updateSizeRecursionGuard(false)
{
implicitAntialiasing = true;
}
@@ -442,6 +443,7 @@ void QQuickTextPrivate::updateSize()
//### need to confirm cost of always setting these for richText
internalWidthUpdate = true;
+ qreal oldWidth = q->width();
qreal iWidth = -1;
if (!q->widthValid())
iWidth = size.width();
@@ -449,24 +451,35 @@ void QQuickTextPrivate::updateSize()
q->setImplicitSize(iWidth + hPadding, size.height() + vPadding);
internalWidthUpdate = false;
- if (iWidth == -1)
- q->setImplicitHeight(size.height() + vPadding);
-
- QTextBlock firstBlock = extra->doc->firstBlock();
- while (firstBlock.layout()->lineCount() == 0)
- firstBlock = firstBlock.next();
-
- QTextBlock lastBlock = extra->doc->lastBlock();
- while (lastBlock.layout()->lineCount() == 0)
- lastBlock = lastBlock.previous();
-
- if (firstBlock.lineCount() > 0 && lastBlock.lineCount() > 0) {
- QTextLine firstLine = firstBlock.layout()->lineAt(0);
- QTextLine lastLine = lastBlock.layout()->lineAt(lastBlock.layout()->lineCount() - 1);
- advance = QSizeF(lastLine.horizontalAdvance(),
- (lastLine.y() + lastBlock.layout()->position().y()) - (firstLine.y() + firstBlock.layout()->position().y()));
+ // If the implicit width update caused a recursive change of the width,
+ // we will have skipped integral parts of the layout due to the
+ // internalWidthUpdate recursion guard. To make sure everything is up
+ // to date, we need to run a second pass over the layout when updateSize()
+ // is done.
+ if (!qFuzzyCompare(q->width(), oldWidth) && !updateSizeRecursionGuard) {
+ updateSizeRecursionGuard = true;
+ updateSize();
+ updateSizeRecursionGuard = false;
} else {
- advance = QSizeF();
+ if (iWidth == -1)
+ q->setImplicitHeight(size.height() + vPadding);
+
+ QTextBlock firstBlock = extra->doc->firstBlock();
+ while (firstBlock.layout()->lineCount() == 0)
+ firstBlock = firstBlock.next();
+
+ QTextBlock lastBlock = extra->doc->lastBlock();
+ while (lastBlock.layout()->lineCount() == 0)
+ lastBlock = lastBlock.previous();
+
+ if (firstBlock.lineCount() > 0 && lastBlock.lineCount() > 0) {
+ QTextLine firstLine = firstBlock.layout()->lineAt(0);
+ QTextLine lastLine = lastBlock.layout()->lineAt(lastBlock.layout()->lineCount() - 1);
+ advance = QSizeF(lastLine.horizontalAdvance(),
+ (lastLine.y() + lastBlock.layout()->position().y()) - (firstLine.y() + firstBlock.layout()->position().y()));
+ } else {
+ advance = QSizeF();
+ }
}
}
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index b0b1492d57..fd26d966c8 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -174,6 +174,7 @@ public:
bool needToUpdateLayout:1;
bool formatModifiesFontSize:1;
bool polishSize:1; // Workaround for problem with polish called after updateSize (QTBUG-42636)
+ bool updateSizeRecursionGuard:1;
static const QChar elideChar;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index d9db8b56b4..f921e3962b 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -46,6 +46,7 @@
#include "qquickevents_p_p.h"
#include <private/qquickdrag_p.h>
+#include <private/qquickhoverhandler_p.h>
#include <private/qquickpointerhandler_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
@@ -88,6 +89,8 @@ Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch")
Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target")
Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse")
Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target")
+Q_LOGGING_CATEGORY(lcWheelTarget, "qt.quick.wheel.target")
+Q_LOGGING_CATEGORY(lcGestureTarget, "qt.quick.gesture.target")
Q_LOGGING_CATEGORY(DBG_HOVER_TRACE, "qt.quick.hover.trace")
Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus")
Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty")
@@ -256,14 +259,16 @@ void QQuickWindow::hideEvent(QHideEvent *)
void QQuickWindow::focusOutEvent(QFocusEvent *ev)
{
Q_D(QQuickWindow);
- d->contentItem->setFocus(false, ev->reason());
+ if (d->contentItem)
+ d->contentItem->setFocus(false, ev->reason());
}
/*! \reimp */
void QQuickWindow::focusInEvent(QFocusEvent *ev)
{
Q_D(QQuickWindow);
- d->contentItem->setFocus(true, ev->reason());
+ if (d->contentItem)
+ d->contentItem->setFocus(true, ev->reason());
d->updateFocusItemTransform();
}
@@ -1315,7 +1320,9 @@ QQuickWindow::~QQuickWindow()
#if QT_CONFIG(draganddrop)
delete d->dragGrabber; d->dragGrabber = nullptr;
#endif
- delete d->contentItem; d->contentItem = nullptr;
+ QQuickRootItem *root = d->contentItem;
+ d->contentItem = nullptr;
+ delete root;
qDeleteAll(d->pointerEventInstances);
d->pointerEventInstances.clear();
@@ -1540,8 +1547,20 @@ bool QQuickWindowPrivate::clearHover(ulong timestamp)
QPointF pos = q->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint());
bool accepted = false;
- for (QQuickItem* item : qAsConst(hoverItems))
+ for (QQuickItem* item : qAsConst(hoverItems)) {
accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), timestamp, true) || accepted;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ if (itemPrivate->hasPointerHandlers()) {
+ pos = q->mapFromGlobal(QCursor::pos());
+ QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::genericMouseDevice(), QEvent::MouseMove);
+ pointerEvent->point(0)->reset(Qt::TouchPointMoved, pos, quint64(1) << 24 /* mouse has device ID 1 */, timestamp, QVector2D());
+ pointerEvent->point(0)->setAccepted(true);
+ pointerEvent->localize(item);
+ for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers)
+ if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h))
+ hh->handlePointerEvent(pointerEvent);
+ }
+ }
hoverItems.clear();
return accepted;
}
@@ -1571,6 +1590,8 @@ bool QQuickWindow::event(QEvent *e)
return d->deliverTouchCancelEvent(static_cast<QTouchEvent*>(e));
break;
case QEvent::Enter: {
+ if (!d->contentItem)
+ return false;
QEnterEvent *enter = static_cast<QEnterEvent*>(e);
bool accepted = enter->isAccepted();
bool delivered = d->deliverHoverEvent(d->contentItem, enter->windowPos(), d->lastMousePosition,
@@ -1592,7 +1613,8 @@ bool QQuickWindow::event(QEvent *e)
break;
#endif
case QEvent::WindowDeactivate:
- contentItem()->windowDeactivateEvent();
+ if (d->contentItem)
+ d->contentItem->windowDeactivateEvent();
break;
case QEvent::Close: {
// TOOD Qt 6 (binary incompatible)
@@ -1617,7 +1639,7 @@ bool QQuickWindow::event(QEvent *e)
}
#if QT_CONFIG(gestures)
case QEvent::NativeGesture:
- d->deliverNativeGestureEvent(d->contentItem, static_cast<QNativeGestureEvent*>(e));
+ d->deliverSinglePointEventUntilAccepted(d->pointerEventInstance(e));
break;
#endif
case QEvent::ShortcutOverride:
@@ -1684,6 +1706,7 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuic
{
const QVector<QQuickPointerHandler *> &eventDeliveryTargets = pointerEvent->device()->eventDeliveryTargets();
QVarLengthArray<QPair<QQuickItem *, bool>, 4> sendFilteredPointerEventResult;
+ hasFiltered.clear();
for (auto handler : passiveGrabbers) {
// a null pointer in passiveGrabbers is unlikely, unless the grabbing handler was deleted dynamically
if (Q_LIKELY(handler) && !eventDeliveryTargets.contains(handler)) {
@@ -1720,6 +1743,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
if (point->exclusiveGrabber()) {
if (auto grabber = point->grabberItem()) {
bool handled = false;
+ hasFiltered.clear();
if (sendFilteredPointerEvent(pointerEvent, grabber))
handled = true;
// if the grabber is an Item:
@@ -1748,6 +1772,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
// if the grabber is not an Item, it must be a PointerHandler
auto handler = point->grabberPointerHandler();
pointerEvent->localize(handler->parentItem());
+ hasFiltered.clear();
if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem()))
handler->handlePointerEvent(pointerEvent);
if (mouseIsReleased)
@@ -1767,12 +1792,13 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
// If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order
if (!pointerEvent->allPointsGrabbed() && pointerEvent->buttons()) {
- QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePosition(), false, false);
+ QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point, false, false);
for (QQuickItem *item : targetItems) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (!itemPrivate->extra.isAllocated() || itemPrivate->extra->pointerHandlers.isEmpty())
continue;
pointerEvent->localize(item);
+ hasFiltered.clear();
if (!sendFilteredPointerEvent(pointerEvent, item)) {
if (itemPrivate->handlePointerEvent(pointerEvent, true)) // avoid re-delivering to grabbers
delivered = true;
@@ -1834,6 +1860,16 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
}
}
+ if (itemPrivate->hasPointerHandlers()) {
+ QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::genericMouseDevice(), QEvent::MouseMove);
+ pointerEvent->point(0)->reset(Qt::TouchPointMoved, scenePos, quint64(1) << 24 /* mouse has device ID 1 */, timestamp, QVector2D());
+ pointerEvent->point(0)->setAccepted(true);
+ pointerEvent->localize(item);
+ for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers)
+ if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h))
+ hh->handlePointerEvent(pointerEvent);
+ }
+
if (itemPrivate->hoverEnabled) {
QPointF p = item->mapFromScene(scenePos);
if (item->contains(p)) {
@@ -1886,43 +1922,57 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
return false;
}
-#if QT_CONFIG(wheelevent)
-bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event)
+// Simple delivery of non-mouse, non-touch Pointer Events: visit the items and handlers
+// in the usual reverse-paint-order until propagation is stopped
+bool QQuickWindowPrivate::deliverSinglePointEventUntilAccepted(QQuickPointerEvent *event)
{
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ Q_ASSERT(event->pointCount() == 1);
+ QQuickEventPoint *point = event->point(0);
+ QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point, false, false);
- if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- QPointF p = item->mapFromScene(event->posF());
- if (!item->contains(p))
- return false;
- }
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
- continue;
- if (deliverWheelEvent(child, event))
- return true;
- }
-
- QPointF p = item->mapFromScene(event->posF());
-
- if (item->contains(p)) {
- QWheelEvent wheel(p, event->globalPosF(), event->pixelDelta(), event->angleDelta(), event->delta(),
- event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted());
- wheel.setTimestamp(event->timestamp());
- wheel.accept();
- QCoreApplication::sendEvent(item, &wheel);
- if (wheel.isAccepted()) {
- event->accept();
+ for (QQuickItem *item : targetItems) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ event->localize(item);
+ // Let Pointer Handlers have the first shot
+ itemPrivate->handlePointerEvent(event);
+ if (point->isAccepted())
return true;
+ QPointF g = item->window()->mapToGlobal(point->scenePosition().toPoint());
+#if QT_CONFIG(wheelevent)
+ // Let the Item have a chance to handle it
+ if (QQuickPointerScrollEvent *pse = event->asPointerScrollEvent()) {
+ QWheelEvent wheel(point->position(), g, pse->pixelDelta().toPoint(), pse->angleDelta().toPoint(),
+ pse->buttons(), pse->modifiers(), pse->phase(),
+ pse->isInverted(), pse->synthSource());
+ wheel.setTimestamp(pse->timestamp());
+ wheel.accept();
+ QCoreApplication::sendEvent(item, &wheel);
+ if (wheel.isAccepted()) {
+ qCDebug(lcWheelTarget) << &wheel << "->" << item;
+ event->setAccepted(true);
+ return true;
+ }
+ }
+#endif
+#if QT_CONFIG(gestures)
+ if (QQuickPointerNativeGestureEvent *pnge = event->asPointerNativeGestureEvent()) {
+ QNativeGestureEvent nge(pnge->type(), pnge->device()->qTouchDevice(), point->position(), point->scenePosition(), g,
+ pnge->value(), 0L, 0L); // TODO can't copy things I can't access
+ nge.accept();
+ QCoreApplication::sendEvent(item, &nge);
+ if (nge.isAccepted()) {
+ qCDebug(lcGestureTarget) << &nge << "->" << item;
+ event->setAccepted(true);
+ return true;
+ }
}
+#endif // gestures
}
- return false;
+ return false; // it wasn't handled
}
+#if QT_CONFIG(wheelevent)
/*! \reimp */
void QQuickWindow::wheelEvent(QWheelEvent *event)
{
@@ -1937,55 +1987,11 @@ void QQuickWindow::wheelEvent(QWheelEvent *event)
return;
event->ignore();
- d->deliverWheelEvent(d->contentItem, event);
+ d->deliverPointerEvent(d->pointerEventInstance(event));
d->lastWheelEventAccepted = event->isAccepted();
}
#endif // wheelevent
-#if QT_CONFIG(gestures)
-bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGestureEvent *event)
-{
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- QPointF p = item->mapFromScene(event->windowPos());
- if ((itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) && !item->contains(p))
- return false;
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
- continue;
- if (deliverNativeGestureEvent(child, event))
- return true;
- }
-
- // Try the Item's pointer handlers first
- QQuickPointerEvent *pointerEvent = pointerEventInstance(event);
- pointerEvent->localize(item);
- if (itemPrivate->handlePointerEvent(pointerEvent, false)) {
- if (pointerEvent->allPointsAccepted()) {
- event->accept();
- return true;
- }
- }
-
- // If still not accepted, try direct delivery to the item
- if (item->contains(p)) {
- QNativeGestureEvent copy(event->gestureType(), event->device(), p, event->windowPos(), event->screenPos(),
- event->value(), 0L, 0L); // TODO can't copy things I can't access
- event->accept();
- item->event(&copy);
- if (copy.isAccepted()) {
- event->accept();
- return true;
- }
- }
-
- return false;
-}
-#endif // gestures
-
bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
{
qCDebug(DBG_TOUCH) << event;
@@ -2229,6 +2235,8 @@ QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointer
if (eventType == QEvent::NativeGesture && !qobject_cast<QQuickPointerNativeGestureEvent*>(e))
continue;
#endif
+ if (eventType == QEvent::Wheel && !qobject_cast<QQuickPointerScrollEvent*>(e))
+ continue;
// Otherwise we assume there's only one event type per device.
// More disambiguation tests might need to be added above if that changes later.
if (e->device() == device)
@@ -2248,7 +2256,10 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic
// QWindowSystemInterface::handleMouseEvent() does not take a device parameter:
// we assume all mouse events come from one mouse (the "core pointer").
// So when the event is a mouse event, device == QQuickPointerDevice::genericMouseDevice()
- ev = new QQuickPointerMouseEvent(q, device);
+ if (eventType == QEvent::Wheel)
+ ev = new QQuickPointerScrollEvent(q, device);
+ else
+ ev = new QQuickPointerMouseEvent(q, device);
break;
case QQuickPointerDevice::TouchPad:
case QQuickPointerDevice::TouchScreen:
@@ -2282,6 +2293,7 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) con
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
+ case QEvent::Wheel:
dev = QQuickPointerDevice::genericMouseDevice();
break;
case QEvent::TouchBegin:
@@ -2324,7 +2336,7 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
} else if (event->asPointerTouchEvent()) {
deliverTouchEvent(event->asPointerTouchEvent());
} else {
- Q_ASSERT(false);
+ deliverSinglePointEventUntilAccepted(event);
}
event->reset(nullptr);
@@ -2332,16 +2344,16 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
--pointerEventRecursionGuard;
}
-// check if item or any of its child items contain the point
+// check if item or any of its child items contain the point, or if any pointer handler "wants" the point
// FIXME: should this be iterative instead of recursive?
// If checkMouseButtons is true, it means we are finding targets for a mouse event, so no item for which acceptedMouseButtons() is NoButton will be added.
// If checkAcceptsTouch is true, it means we are finding targets for a touch event, so either acceptTouchEvents() must return true OR
// it must accept a synth. mouse event, thus if acceptTouchEvents() returns false but acceptedMouseButtons() is true, gets added; if not, it doesn't.
-QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, const QPointF &scenePos, bool checkMouseButtons, bool checkAcceptsTouch) const
+QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const
{
QVector<QQuickItem *> targets;
auto itemPrivate = QQuickItemPrivate::get(item);
- QPointF itemPos = item->mapFromScene(scenePos);
+ QPointF itemPos = item->mapFromScene(point->scenePosition());
// if the item clips, we can potentially return early
if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
if (!item->contains(itemPos))
@@ -2355,11 +2367,15 @@ QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, cons
auto childPrivate = QQuickItemPrivate::get(child);
if (!child->isVisible() || !child->isEnabled() || childPrivate->culled)
continue;
- targets << pointerTargets(child, scenePos, checkMouseButtons, checkAcceptsTouch);
+ targets << pointerTargets(child, point, checkMouseButtons, checkAcceptsTouch);
}
bool relevant = item->contains(itemPos);
- if (!(itemPrivate->hasPointerHandlers())) {
+ if (itemPrivate->hasPointerHandlers()) {
+ if (!relevant)
+ if (itemPrivate->anyPointerHandlerWants(point))
+ relevant = true;
+ } else {
if (relevant && checkMouseButtons && item->acceptedMouseButtons() == Qt::NoButton)
relevant = false;
if (relevant && checkAcceptsTouch && !(item->acceptTouchEvents() || item->acceptedMouseButtons()))
@@ -2440,6 +2456,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
// The grabber is not an item? It's a handler then. Let it have the event first.
QQuickPointerHandler *handler = static_cast<QQuickPointerHandler *>(grabber);
receiver = static_cast<QQuickPointerHandler *>(grabber)->parentItem();
+ hasFiltered.clear();
if (sendFilteredPointerEvent(event, receiver))
done = true;
event->localize(receiver);
@@ -2469,7 +2486,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
QQuickEventPoint *point = event->point(i);
if (point->state() == QQuickEventPoint::Pressed)
continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, false, false);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
@@ -2499,7 +2516,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
point->setAccepted(false); // because otherwise touchEventForItem will ignore it
if (point->grabberPointerHandler() && point->state() == QQuickEventPoint::Released)
point->setGrabberPointerHandler(nullptr, true);
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), !isTouchEvent, isTouchEvent);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, !isTouchEvent, isTouchEvent);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
@@ -2508,6 +2525,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
}
for (QQuickItem *item : targetItems) {
+ hasFiltered.clear();
if (!handlersOnly && sendFilteredPointerEvent(event, item)) {
if (event->isAccepted()) {
for (int i = 0; i < event->pointCount(); ++i)
@@ -2559,7 +2577,6 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
// synthetic events - flickable sends one when setPressDelay is used.
auto oldMouseGrabber = q->mouseGrabberItem();
QPointF localPos = item->mapFromScene(point->scenePosition());
- Q_ASSERT(item->contains(localPos)); // transform is checked already
QMouseEvent *me = event->asMouseEvent(localPos);
me->accept();
QCoreApplication::sendEvent(item, me);
@@ -2587,6 +2604,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
bool eventAccepted = false;
// If any parent filters the event, we're done.
+ hasFiltered.clear();
if (sendFilteredPointerEvent(pointerEvent, item))
return;
@@ -2800,7 +2818,6 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF
bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
{
- hasFiltered.clear();
return sendFilteredPointerEventImpl(event, receiver, filteringParent ? filteringParent : receiver->parentItem());
}
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index b5e3a2c1eb..9a83e8523b 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -152,12 +152,7 @@ public:
bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
bool sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
-#if QT_CONFIG(wheelevent)
- bool deliverWheelEvent(QQuickItem *, QWheelEvent *);
-#endif
-#if QT_CONFIG(gestures)
- bool deliverNativeGestureEvent(QQuickItem *, QNativeGestureEvent *);
-#endif
+ bool deliverSinglePointEventUntilAccepted(QQuickPointerEvent *);
// entry point of events to the window
void handleTouchEvent(QTouchEvent *);
@@ -180,7 +175,7 @@ public:
void deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event);
void deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, bool handlersOnly = false);
- QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons, bool checkAcceptsTouch) const;
+ QVector<QQuickItem *> pointerTargets(QQuickItem *, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const;
QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
// hover delivery
diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp
index d715d900ba..2e5fdbbe6b 100644
--- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp
@@ -77,6 +77,11 @@ QSGSoftwareRenderableNode *QSGAbstractSoftwareRenderer::renderableNode(QSGNode *
return m_nodes.value(node, nullptr);
}
+const QLinkedList<QSGSoftwareRenderableNode*> &QSGAbstractSoftwareRenderer::renderableNodes() const
+{
+ return m_renderableNodes;
+}
+
void QSGAbstractSoftwareRenderer::addNodeMapping(QSGNode *node, QSGSoftwareRenderableNode *renderableNode)
{
m_nodes.insert(node, renderableNode);
diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h
index f6594d931a..99204ef25e 100644
--- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h
@@ -88,6 +88,7 @@ protected:
QRect backgroundRect();
// only known after calling optimizeRenderList()
bool isOpaque() const { return m_isOpaque; }
+ const QLinkedList<QSGSoftwareRenderableNode*> &renderableNodes() const;
private:
void nodeAdded(QSGNode *node);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp
index 21f20c66cd..7ab9c15d9b 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp
@@ -91,8 +91,8 @@ void QSGSoftwareGlyphNode::paint(QPainter *painter)
QPointF pos = m_position - QPointF(0, m_glyphRun.rawFont().ascent());
qreal offset = 1.0;
- if (painter->device()->devicePixelRatio() != 0)
- offset = 1.0 / painter->device()->devicePixelRatio();
+ if (painter->device()->devicePixelRatioF() > 0.0)
+ offset = 1.0 / painter->device()->devicePixelRatioF();
switch (m_style) {
case QQuickText::Normal: break;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
index bf3141bc32..2c361e03e2 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
@@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE
QSGSoftwareInternalRectangleNode::QSGSoftwareInternalRectangleNode()
: m_penWidth(0)
, m_radius(0)
+ , m_vertical(true)
, m_cornerPixmapIsDirty(true)
, m_devicePixelRatio(1)
{
@@ -186,6 +187,15 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
markDirty(DirtyMaterial);
}
+void QSGSoftwareInternalRectangleNode::setGradientVertical(bool vertical)
+{
+ if (m_vertical != vertical) {
+ m_vertical = vertical;
+ m_cornerPixmapIsDirty = true;
+ markDirty(DirtyMaterial);
+ }
+}
+
void QSGSoftwareInternalRectangleNode::setRadius(qreal radius)
{
if (m_radius != radius) {
@@ -209,7 +219,7 @@ void QSGSoftwareInternalRectangleNode::update()
}
if (!m_stops.isEmpty()) {
- QLinearGradient gradient(QPoint(0,0), QPoint(0,1));
+ QLinearGradient gradient(QPoint(0,0), QPoint(m_vertical ? 0 : 1, m_vertical ? 1 : 0));
gradient.setStops(m_stops);
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
m_brush = QBrush(gradient);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h
index 1f87424d2a..125520de26 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h
@@ -69,6 +69,7 @@ public:
void setPenColor(const QColor &color) override;
void setPenWidth(qreal width) override;
void setGradientStops(const QGradientStops &stops) override;
+ void setGradientVertical(bool vertical) override;
void setRadius(qreal radius) override;
void setAntialiasing(bool antialiasing) override { Q_UNUSED(antialiasing) }
void setAligned(bool aligned) override;
@@ -91,6 +92,7 @@ private:
double m_radius;
QPen m_pen;
QBrush m_brush;
+ bool m_vertical;
bool m_cornerPixmapIsDirty;
QPixmap m_cornerPixmap;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h
index 8fc87db179..b20d0a1828 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h
@@ -72,7 +72,7 @@ class QSGSoftwareNinePatchNode;
class QSGSoftwareSpriteNode;
class QSGRenderNode;
-class QSGSoftwareRenderableNode
+class Q_QUICK_PRIVATE_EXPORT QSGSoftwareRenderableNode
{
public:
enum NodeType {
@@ -104,6 +104,7 @@ public:
bool isOpaque() const { return m_isOpaque; }
bool isDirty() const { return m_isDirty; }
bool isDirtyRegionEmpty() const;
+ QSGNode *handle() const { return m_handle.node; }
void setTransform(const QTransform &transform);
void setClipRegion(const QRegion &clipRegion, bool hasClipRegion = true);
@@ -123,6 +124,7 @@ public:
private:
union RenderableNodeHandle {
+ QSGNode *node;
QSGSimpleRectNode *simpleRectNode;
QSGSimpleTextureNode *simpleTextureNode;
QSGSoftwareInternalImageNode *imageNode;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
index ffcee5f56e..e9ed52d428 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
@@ -113,8 +113,8 @@ void QSGSoftwareRenderer::render()
setBackgroundColor(clearColor());
setBackgroundRect(QRect(0, 0,
- m_paintDevice->width() / m_paintDevice->devicePixelRatio(),
- m_paintDevice->height() / m_paintDevice->devicePixelRatio()));
+ m_paintDevice->width() / m_paintDevice->devicePixelRatioF(),
+ m_paintDevice->height() / m_paintDevice->devicePixelRatioF()));
// Build Renderlist
// The renderlist is created by visiting each node in the tree and when a
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index c64360f955..46af0f28f0 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -234,10 +234,8 @@ void QSGDistanceFieldGlyphCache::setGlyphsPosition(const QList<GlyphPosition> &g
}
if (!invalidatedGlyphs.isEmpty()) {
- QLinkedList<QSGDistanceFieldGlyphConsumer *>::iterator it = m_registeredNodes.begin();
- while (it != m_registeredNodes.end()) {
- (*it)->invalidateGlyphs(invalidatedGlyphs);
- ++it;
+ for (QSGDistanceFieldGlyphConsumerList::iterator iter = m_registeredNodes.begin(); iter != m_registeredNodes.end(); ++iter) {
+ iter->invalidateGlyphs(invalidatedGlyphs);
}
}
}
@@ -280,10 +278,8 @@ void QSGDistanceFieldGlyphCache::setGlyphsTexture(const QVector<glyph_t> &glyphs
}
if (!invalidatedGlyphs.isEmpty()) {
- QLinkedList<QSGDistanceFieldGlyphConsumer*>::iterator it = m_registeredNodes.begin();
- while (it != m_registeredNodes.end()) {
- (*it)->invalidateGlyphs(invalidatedGlyphs);
- ++it;
+ for (QSGDistanceFieldGlyphConsumerList::iterator iter = m_registeredNodes.begin(); iter != m_registeredNodes.end(); ++iter) {
+ iter->invalidateGlyphs(invalidatedGlyphs);
}
}
}
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 9c88b8272c..5a465831cb 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -64,6 +64,7 @@
#include <QtGui/private/qdatabuffer_p.h>
#include <private/qopenglcontext_p.h>
#include <private/qdistancefield_p.h>
+#include <private/qintrusivelist_p.h>
// ### remove
#include <QtQuick/private/qquicktext_p.h>
@@ -136,6 +137,7 @@ public:
virtual void setPenColor(const QColor &color) = 0;
virtual void setPenWidth(qreal width) = 0;
virtual void setGradientStops(const QGradientStops &stops) = 0;
+ virtual void setGradientVertical(bool vertical) = 0;
virtual void setRadius(qreal radius) = 0;
virtual void setAntialiasing(bool antialiasing) { Q_UNUSED(antialiasing) }
virtual void setAligned(bool aligned) = 0;
@@ -403,7 +405,9 @@ public:
virtual ~QSGDistanceFieldGlyphConsumer() {}
virtual void invalidateGlyphs(const QVector<quint32> &glyphs) = 0;
+ QIntrusiveListNode node;
};
+typedef QIntrusiveList<QSGDistanceFieldGlyphConsumer, &QSGDistanceFieldGlyphConsumer::node> QSGDistanceFieldGlyphConsumerList;
class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache
{
@@ -464,8 +468,8 @@ public:
void update();
- void registerGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.append(node); }
- void unregisterGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.removeOne(node); }
+ void registerGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.insert(node); }
+ void unregisterGlyphNode(QSGDistanceFieldGlyphConsumer *node) { m_registeredNodes.remove(node); }
virtual void registerOwnerElement(QQuickItem *ownerElement);
virtual void unregisterOwnerElement(QQuickItem *ownerElement);
@@ -521,7 +525,7 @@ private:
QHash<glyph_t, GlyphData> m_glyphsData;
QDataBuffer<glyph_t> m_pendingGlyphs;
QSet<glyph_t> m_populatingGlyphs;
- QLinkedList<QSGDistanceFieldGlyphConsumer*> m_registeredNodes;
+ QSGDistanceFieldGlyphConsumerList m_registeredNodes;
static Texture s_emptyTexture;
};
diff --git a/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp b/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp
index df124cce35..91317ee2d7 100644
--- a/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp
+++ b/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp
@@ -68,19 +68,30 @@ namespace
{
float x, y;
Color4ub color;
- void set(float nx, float ny, Color4ub ncolor)
+
+ void set(float primary, float secondary, Color4ub ncolor, bool vertical)
{
- x = nx; y = ny; color = ncolor;
+ if (vertical) {
+ x = secondary; y = primary;
+ } else {
+ x = primary; y = secondary;
+ }
+ color = ncolor;
}
};
struct SmoothVertex : public Vertex
{
float dx, dy;
- void set(float nx, float ny, Color4ub ncolor, float ndx, float ndy)
+
+ void set(float primary, float secondary, Color4ub ncolor, float dPrimary, float dSecondary, bool vertical)
{
- Vertex::set(nx, ny, ncolor);
- dx = ndx; dy = ndy;
+ Vertex::set(primary, secondary, ncolor, vertical);
+ if (vertical) {
+ dx = dSecondary; dy = dPrimary;
+ } else {
+ dx = dPrimary; dy = dSecondary;
+ }
}
};
@@ -103,6 +114,7 @@ QSGBasicInternalRectangleNode::QSGBasicInternalRectangleNode()
, m_antialiasing(false)
, m_gradient_is_opaque(true)
, m_dirty_geometry(false)
+ , m_gradient_is_vertical(true)
, m_geometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0)
{
setGeometry(&m_geometry);
@@ -160,6 +172,15 @@ void QSGBasicInternalRectangleNode::setGradientStops(const QGradientStops &stops
m_dirty_geometry = true;
}
+void QSGBasicInternalRectangleNode::setGradientVertical(bool vertical)
+{
+ if (vertical == m_gradient_is_vertical)
+ return;
+ m_gradient_is_vertical = vertical;
+ m_dirty_geometry = true;
+}
+
+
void QSGBasicInternalRectangleNode::setRadius(qreal radius)
{
if (radius == m_radius)
@@ -230,12 +251,15 @@ void QSGBasicInternalRectangleNode::updateGeometry()
Color4ub transparent = { 0, 0, 0, 0 };
const QGradientStops &stops = m_gradient_stops;
+ float length = (m_gradient_is_vertical ? height : width);
+ float secondaryLength = (m_gradient_is_vertical ? width : height);
+
int nextGradientStop = 0;
- float gradientPos = penWidth / height;
+ float gradientPos = penWidth / length;
while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos)
++nextGradientStop;
int lastGradientStop = stops.size() - 1;
- float lastGradientPos = 1.0f - penWidth / height;
+ float lastGradientPos = 1.0f - penWidth / length;
while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos)
--lastGradientStop;
int gradientIntersections = (lastGradientStop - nextGradientStop + 1);
@@ -319,40 +343,46 @@ void QSGBasicInternalRectangleNode::updateGeometry()
quint16 *indices = g->indexDataAsUShort();
quint16 index = 0;
- float py = 0; // previous inner y-coordinate.
- float plx = 0; // previous inner left x-coordinate.
- float prx = 0; // previous inner right x-coordinate.
+ float pp = 0; // previous inner primary coordinate.
+ float pss = 0; // previous inner secondary start coordinate.
+ float pse = 0; // previous inner secondary end coordinate.
float angle = 0.5f * float(M_PI) / segments;
float cosStep = qFastCos(angle);
float sinStep = qFastSin(angle);
+ float innerStart = (m_gradient_is_vertical ? innerRect.top() : innerRect.left());
+ float innerEnd = (m_gradient_is_vertical ? innerRect.bottom() : innerRect.right());
+ float innerLength = (m_gradient_is_vertical ? innerRect.height() : innerRect.width());
+ float innerSecondaryStart = (m_gradient_is_vertical ? innerRect.left() : innerRect.top());
+ float innerSecondaryEnd = (m_gradient_is_vertical ? innerRect.right() : innerRect.bottom());
+
for (int part = 0; part < 2; ++part) {
float c = 1 - part;
float s = part;
for (int i = 0; i <= segments; ++i) {
- float y, lx, rx;
+ float p, ss, se;
if (innerRadius > 0) {
- y = (part ? innerRect.bottom() : innerRect.top()) - innerRadius * c; // current inner y-coordinate.
- lx = innerRect.left() - innerRadius * s; // current inner left x-coordinate.
- rx = innerRect.right() + innerRadius * s; // current inner right x-coordinate.
- gradientPos = ((part ? innerRect.height() : 0) + radius - innerRadius * c) / height;
+ p = (part ? innerEnd : innerStart) - innerRadius * c; // current inner primary coordinate.
+ ss = innerSecondaryStart - innerRadius * s; // current inner secondary start coordinate.
+ se = innerSecondaryEnd + innerRadius * s; // current inner secondary end coordinate.
+ gradientPos = ((part ? innerLength : 0) + radius - innerRadius * c) / length;
} else {
- y = (part ? innerRect.bottom() + innerRadius : innerRect.top() - innerRadius); // current inner y-coordinate.
- lx = innerRect.left() - innerRadius; // current inner left x-coordinate.
- rx = innerRect.right() + innerRadius; // current inner right x-coordinate.
- gradientPos = ((part ? innerRect.height() + innerRadius : -innerRadius) + radius) / height;
+ p = (part ? innerEnd + innerRadius : innerStart - innerRadius); // current inner primary coordinate.
+ ss = innerSecondaryStart - innerRadius; // current inner secondary start coordinate.
+ se = innerSecondaryEnd + innerRadius; // current inner secondary end coordinate.
+ gradientPos = ((part ? innerLength + innerRadius : -innerRadius) + radius) / length;
}
- float Y = (part ? innerRect.bottom() : innerRect.top()) - outerRadius * c; // current outer y-coordinate.
- float lX = innerRect.left() - outerRadius * s; // current outer left x-coordinate.
- float rX = innerRect.right() + outerRadius * s; // current outer right x-coordinate.
+ float outerEdge = (part ? innerEnd : innerStart) - outerRadius * c; // current outer primary coordinate.
+ float outerSecondaryStart = innerSecondaryStart - outerRadius * s; // current outer secondary start coordinate.
+ float outerSecondaryEnd = innerSecondaryEnd + outerRadius * s; // current outer secondary end coordinate.
while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
// Insert vertices at gradient stops.
- float gy = (innerRect.top() - radius) + stops.at(nextGradientStop).first * height;
- float t = (gy - py) / (y - py);
- float glx = plx * (1 - t) + t * lx;
- float grx = prx * (1 - t) + t * rx;
+ float gp = (innerStart - radius) + stops.at(nextGradientStop).first * length;
+ float t = (gp - pp) / (p - pp);
+ float gis = pss * (1 - t) + t * ss; // gradient inner start
+ float gie = pse * (1 - t) + t * se; // gradient inner end
fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
@@ -377,23 +407,23 @@ void QSGBasicInternalRectangleNode::updateGeometry()
indices[innerAATail++] = index + 3;
bool lower = stops.at(nextGradientStop).first > 0.5f;
- float dy = lower ? qMin(0.0f, height - gy - delta) : qMax(0.0f, delta - gy);
- smoothVertices[index++].set(grx, gy, fillColor, width - grx - delta, dy);
- smoothVertices[index++].set(glx, gy, fillColor, delta - glx, dy);
+ float dp = lower ? qMin(0.0f, length - gp - delta) : qMax(0.0f, delta - gp);
+ smoothVertices[index++].set(gp, gie, fillColor, dp, secondaryLength - gie - delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(gp, gis, fillColor, dp, delta - gis, m_gradient_is_vertical);
if (penWidth) {
- smoothVertices[index++].set(grx, gy, borderColor, 0.49f * penWidth * s, -0.49f * penWidth * c);
- smoothVertices[index++].set(glx, gy, borderColor, -0.49f * penWidth * s, -0.49f * penWidth * c);
+ smoothVertices[index++].set(gp, gie, borderColor, -0.49f * penWidth * c, 0.49f * penWidth * s, m_gradient_is_vertical);
+ smoothVertices[index++].set(gp, gis, borderColor, -0.49f * penWidth * c, -0.49f * penWidth * s, m_gradient_is_vertical);
} else {
- dy = lower ? delta : -delta;
- smoothVertices[index++].set(grx, gy, transparent, delta, dy);
- smoothVertices[index++].set(glx, gy, transparent, -delta, dy);
+ dp = lower ? delta : -delta;
+ smoothVertices[index++].set(gp, gie, transparent, dp, delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(gp, gis, transparent, dp, -delta, m_gradient_is_vertical);
}
} else {
- vertices[index++].set(grx, gy, fillColor);
- vertices[index++].set(glx, gy, fillColor);
+ vertices[index++].set(gp, gie, fillColor, m_gradient_is_vertical);
+ vertices[index++].set(gp, gis, fillColor, m_gradient_is_vertical);
if (penWidth) {
- vertices[index++].set(grx, gy, borderColor);
- vertices[index++].set(glx, gy, borderColor);
+ vertices[index++].set(gp, gie, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(gp, gis, borderColor, m_gradient_is_vertical);
}
}
++nextGradientStop;
@@ -430,41 +460,41 @@ void QSGBasicInternalRectangleNode::updateGeometry()
indices[innerAATail++] = index + 1;
indices[innerAATail++] = index + 3;
- float dy = part ? qMin(0.0f, height - y - delta) : qMax(0.0f, delta - y);
- smoothVertices[index++].set(rx, y, fillColor, width - rx - delta, dy);
- smoothVertices[index++].set(lx, y, fillColor, delta - lx, dy);
+ float dp = part ? qMin(0.0f, length - p - delta) : qMax(0.0f, delta - p);
+ smoothVertices[index++].set(p, se, fillColor, dp, secondaryLength - se - delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(p, ss, fillColor, dp, delta - ss, m_gradient_is_vertical);
- dy = part ? delta : -delta;
+ dp = part ? delta : -delta;
if (penWidth) {
- smoothVertices[index++].set(rx, y, borderColor, 0.49f * penWidth * s, -0.49f * penWidth * c);
- smoothVertices[index++].set(lx, y, borderColor, -0.49f * penWidth * s, -0.49f * penWidth * c);
- smoothVertices[index++].set(rX, Y, borderColor, -0.49f * penWidth * s, 0.49f * penWidth * c);
- smoothVertices[index++].set(lX, Y, borderColor, 0.49f * penWidth * s, 0.49f * penWidth * c);
- smoothVertices[index++].set(rX, Y, transparent, delta, dy);
- smoothVertices[index++].set(lX, Y, transparent, -delta, dy);
+ smoothVertices[index++].set(p, se, borderColor, -0.49f * penWidth * c, 0.49f * penWidth * s, m_gradient_is_vertical);
+ smoothVertices[index++].set(p, ss, borderColor, -0.49f * penWidth * c, -0.49f * penWidth * s, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, 0.49f * penWidth * c, -0.49f * penWidth * s, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryStart, borderColor, 0.49f * penWidth * c, 0.49f * penWidth * s, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryEnd, transparent, dp, delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryStart, transparent, dp, -delta, m_gradient_is_vertical);
indices[--outerAAHead] = index - 2;
indices[--outerAAHead] = index - 4;
indices[outerAATail++] = index - 3;
indices[outerAATail++] = index - 1;
} else {
- smoothVertices[index++].set(rx, y, transparent, delta, dy);
- smoothVertices[index++].set(lx, y, transparent, -delta, dy);
+ smoothVertices[index++].set(p, se, transparent, dp, delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(p, ss, transparent, dp, -delta, m_gradient_is_vertical);
}
} else {
- vertices[index++].set(rx, y, fillColor);
- vertices[index++].set(lx, y, fillColor);
+ vertices[index++].set(p, se, fillColor, m_gradient_is_vertical);
+ vertices[index++].set(p, ss, fillColor, m_gradient_is_vertical);
if (penWidth) {
- vertices[index++].set(rx, y, borderColor);
- vertices[index++].set(lx, y, borderColor);
- vertices[index++].set(rX, Y, borderColor);
- vertices[index++].set(lX, Y, borderColor);
+ vertices[index++].set(p, se, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(p, ss, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(outerEdge, outerSecondaryStart, borderColor, m_gradient_is_vertical);
}
}
- py = y;
- plx = lx;
- prx = rx;
+ pp = p;
+ pss = ss;
+ pse = se;
// Rotate
qreal tmp = c;
@@ -543,19 +573,24 @@ void QSGBasicInternalRectangleNode::updateGeometry()
quint16 *indices = g->indexDataAsUShort();
quint16 index = 0;
- float lx = innerRect.left();
- float rx = innerRect.right();
- float lX = outerRect.left();
- float rX = outerRect.right();
+ float innerStart = (m_gradient_is_vertical ? innerRect.top() : innerRect.left());
+ float innerEnd = (m_gradient_is_vertical ? innerRect.bottom() : innerRect.right());
+ float outerStart = (m_gradient_is_vertical ? outerRect.top() : outerRect.left());
+ float outerEnd = (m_gradient_is_vertical ? outerRect.bottom() : outerRect.right());
+
+ float innerSecondaryStart = (m_gradient_is_vertical ? innerRect.left() : innerRect.top());
+ float innerSecondaryEnd = (m_gradient_is_vertical ? innerRect.right() : innerRect.bottom());
+ float outerSecondaryStart = (m_gradient_is_vertical ? outerRect.left() : outerRect.top());
+ float outerSecondaryEnd = (m_gradient_is_vertical ? outerRect.right() : outerRect.bottom());
for (int part = -1; part <= 1; part += 2) {
- float y = (part == 1 ? innerRect.bottom() : innerRect.top());
- float Y = (part == 1 ? outerRect.bottom() : outerRect.top());
- gradientPos = (y - innerRect.top() + penWidth) / height;
+ float innerEdge = (part == 1 ? innerEnd : innerStart);
+ float outerEdge = (part == 1 ? outerEnd : outerStart);
+ gradientPos = (innerEdge - innerStart + penWidth) / length;
while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
// Insert vertices at gradient stops.
- float gy = (innerRect.top() - penWidth) + stops.at(nextGradientStop).first * height;
+ float gp = (innerStart - penWidth) + stops.at(nextGradientStop).first * length;
fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
@@ -580,22 +615,22 @@ void QSGBasicInternalRectangleNode::updateGeometry()
indices[innerAATail++] = index + 3;
bool lower = stops.at(nextGradientStop).first > 0.5f;
- float dy = lower ? qMin(0.0f, height - gy - delta) : qMax(0.0f, delta - gy);
- smoothVertices[index++].set(rx, gy, fillColor, width - rx - delta, dy);
- smoothVertices[index++].set(lx, gy, fillColor, delta - lx, dy);
+ float dp = lower ? qMin(0.0f, length - gp - delta) : qMax(0.0f, delta - gp);
+ smoothVertices[index++].set(gp, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(gp, innerSecondaryStart, fillColor, dp, delta - innerSecondaryStart, m_gradient_is_vertical);
if (penWidth) {
- smoothVertices[index++].set(rx, gy, borderColor, 0.49f * penWidth, (lower ? 0.49f : -0.49f) * penWidth);
- smoothVertices[index++].set(lx, gy, borderColor, -0.49f * penWidth, (lower ? 0.49f : -0.49f) * penWidth);
+ smoothVertices[index++].set(gp, innerSecondaryEnd, borderColor, (lower ? 0.49f : -0.49f) * penWidth, 0.49f * penWidth, m_gradient_is_vertical);
+ smoothVertices[index++].set(gp, innerSecondaryStart, borderColor, (lower ? 0.49f : -0.49f) * penWidth, -0.49f * penWidth, m_gradient_is_vertical);
} else {
- smoothVertices[index++].set(rx, gy, transparent, delta, lower ? delta : -delta);
- smoothVertices[index++].set(lx, gy, transparent, -delta, lower ? delta : -delta);
+ smoothVertices[index++].set(gp, innerSecondaryEnd, transparent, lower ? delta : -delta, delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(gp, innerSecondaryStart, transparent, lower ? delta : -delta, -delta, m_gradient_is_vertical);
}
} else {
- vertices[index++].set(rx, gy, fillColor);
- vertices[index++].set(lx, gy, fillColor);
+ vertices[index++].set(gp, innerSecondaryEnd, fillColor, m_gradient_is_vertical);
+ vertices[index++].set(gp, innerSecondaryStart, fillColor, m_gradient_is_vertical);
if (penWidth) {
- vertices[index++].set(rx, gy, borderColor);
- vertices[index++].set(lx, gy, borderColor);
+ vertices[index++].set(gp, innerSecondaryEnd, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(gp, innerSecondaryStart, borderColor, m_gradient_is_vertical);
}
}
++nextGradientStop;
@@ -632,34 +667,34 @@ void QSGBasicInternalRectangleNode::updateGeometry()
indices[innerAATail++] = index + 1;
indices[innerAATail++] = index + 3;
- float dy = part == 1 ? qMin(0.0f, height - y - delta) : qMax(0.0f, delta - y);
- smoothVertices[index++].set(rx, y, fillColor, width - rx - delta, dy);
- smoothVertices[index++].set(lx, y, fillColor, delta - lx, dy);
+ float dp = part == 1 ? qMin(0.0f, length - innerEdge - delta) : qMax(0.0f, delta - innerEdge);
+ smoothVertices[index++].set(innerEdge, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(innerEdge, innerSecondaryStart, fillColor, dp, delta - innerSecondaryStart, m_gradient_is_vertical);
if (penWidth) {
- smoothVertices[index++].set(rx, y, borderColor, 0.49f * penWidth, 0.49f * penWidth * part);
- smoothVertices[index++].set(lx, y, borderColor, -0.49f * penWidth, 0.49f * penWidth * part);
- smoothVertices[index++].set(rX, Y, borderColor, -0.49f * penWidth, -0.49f * penWidth * part);
- smoothVertices[index++].set(lX, Y, borderColor, 0.49f * penWidth, -0.49f * penWidth * part);
- smoothVertices[index++].set(rX, Y, transparent, delta, delta * part);
- smoothVertices[index++].set(lX, Y, transparent, -delta, delta * part);
+ smoothVertices[index++].set(innerEdge, innerSecondaryEnd, borderColor, 0.49f * penWidth * part, 0.49f * penWidth, m_gradient_is_vertical);
+ smoothVertices[index++].set(innerEdge, innerSecondaryStart, borderColor, 0.49f * penWidth * part, -0.49f * penWidth, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, -0.49f * penWidth * part, -0.49f * penWidth, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryStart, borderColor, -0.49f * penWidth * part, 0.49f * penWidth, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryEnd, transparent, delta * part, delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(outerEdge, outerSecondaryStart, transparent, delta * part, -delta, m_gradient_is_vertical);
indices[--outerAAHead] = index - 2;
indices[--outerAAHead] = index - 4;
indices[outerAATail++] = index - 3;
indices[outerAATail++] = index - 1;
} else {
- smoothVertices[index++].set(rx, y, transparent, delta, delta * part);
- smoothVertices[index++].set(lx, y, transparent, -delta, delta * part);
+ smoothVertices[index++].set(innerEdge, innerSecondaryEnd, transparent, delta * part, delta, m_gradient_is_vertical);
+ smoothVertices[index++].set(innerEdge, innerSecondaryStart, transparent, delta * part, -delta, m_gradient_is_vertical);
}
} else {
- vertices[index++].set(rx, y, fillColor);
- vertices[index++].set(lx, y, fillColor);
+ vertices[index++].set(innerEdge, innerSecondaryEnd, fillColor, m_gradient_is_vertical);
+ vertices[index++].set(innerEdge, innerSecondaryStart, fillColor, m_gradient_is_vertical);
if (penWidth) {
- vertices[index++].set(rx, y, borderColor);
- vertices[index++].set(lx, y, borderColor);
- vertices[index++].set(rX, Y, borderColor);
- vertices[index++].set(lX, Y, borderColor);
+ vertices[index++].set(innerEdge, innerSecondaryEnd, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(innerEdge, innerSecondaryStart, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, m_gradient_is_vertical);
+ vertices[index++].set(outerEdge, outerSecondaryStart, borderColor, m_gradient_is_vertical);
}
}
}
diff --git a/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h b/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h
index 98e53669ce..99f26b9aed 100644
--- a/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h
+++ b/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h
@@ -66,6 +66,7 @@ public:
void setPenColor(const QColor &color) override;
void setPenWidth(qreal width) override;
void setGradientStops(const QGradientStops &stops) override;
+ void setGradientVertical(bool vertical) override;
void setRadius(qreal radius) override;
void setAntialiasing(bool antialiasing) override;
void setAligned(bool aligned) override;
@@ -90,6 +91,7 @@ protected:
uint m_antialiasing : 1;
uint m_gradient_is_opaque : 1;
uint m_dirty_geometry : 1;
+ uint m_gradient_is_vertical : 1;
QSGGeometry m_geometry;
};
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 9ee1a323e5..02be9daac0 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -234,6 +234,27 @@ QQmlProperty QQuickAbstractAnimationPrivate::createProperty(QObject *obj, const
The corresponding handler is \c onStopped.
*/
+/*!
+ \qmlsignal QtQuick::Animation::finished()
+ \since 5.12
+
+ This signal is emitted when the animation has finished naturally.
+
+ It is not emitted when \l running is set to \c false, nor for animations whose
+ \l loops property is set to \c Animation.Infinite.
+
+ In addition, it is only emitted for top-level, standalone animations. It
+ will not be emitted for animations in a Behavior or Transition, or
+ animations that are part of an animation group.
+
+ If \l alwaysRunToEnd is true, this signal will not be emitted until the
+ animation has completed its current iteration.
+
+ The corresponding handler is \c onFinished.
+
+ \sa stopped(), started(), running
+*/
+
void QQuickAbstractAnimation::setRunning(bool r)
{
Q_D(QQuickAbstractAnimation);
@@ -656,6 +677,7 @@ void QQuickAbstractAnimationPrivate::animationFinished(QAbstractAnimationJob*)
if (loopCount != 1)
animationInstance->setLoopCount(loopCount);
}
+ emit q->finished();
}
QQuickAbstractAnimation::ThreadingModel QQuickAbstractAnimation::threadingModel() const
diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h
index 2293f2597f..746cb938bd 100644
--- a/src/quick/util/qquickanimation_p.h
+++ b/src/quick/util/qquickanimation_p.h
@@ -126,6 +126,7 @@ Q_SIGNALS:
void pausedChanged(bool);
void alwaysRunToEndChanged(bool);
void loopCountChanged(int);
+ Q_REVISION(12) void finished();
public Q_SLOTS:
void restart();
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 7fa20636ec..5337bfd640 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -388,7 +388,7 @@ public:
float matVals[16];
QV4::ScopedValue v(scope);
for (quint32 i = 0; i < 16; ++i) {
- v = array->getIndexed(i);
+ v = array->get(i);
if (!v->isNumber())
return QMatrix4x4();
matVals[i] = v->asDouble();
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index f7c8724318..5d7664433b 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -39,8 +39,10 @@
#include "qquickimageprovider.h"
+#include "qquickimageprovider_p.h"
#include "qquickpixmapcache_p.h"
#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qqmlglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -160,7 +162,10 @@ QQuickTextureFactory *QQuickTextureFactory::textureFactoryForImage(const QImage
Constructs the image response
*/
QQuickImageResponse::QQuickImageResponse()
+ : QObject(*(new QQuickImageResponsePrivate))
{
+ qmlobject_connect(this, QQuickImageResponse, SIGNAL(finished()),
+ this, QQuickImageResponse, SLOT(_q_finished()));
}
/*!
diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h
index 4f8193789a..82d0501697 100644
--- a/src/quick/util/qquickimageprovider.h
+++ b/src/quick/util/qquickimageprovider.h
@@ -69,6 +69,8 @@ public:
static QQuickTextureFactory *textureFactoryForImage(const QImage &image);
};
+class QQuickImageResponsePrivate;
+
class Q_QUICK_EXPORT QQuickImageResponse : public QObject
{
Q_OBJECT
@@ -84,6 +86,10 @@ public Q_SLOTS:
Q_SIGNALS:
void finished();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickImageResponse)
+ Q_PRIVATE_SLOT(d_func(), void _q_finished())
};
class Q_QUICK_EXPORT QQuickImageProvider : public QQmlImageProviderBase
diff --git a/src/quick/util/qquickimageprovider_p.h b/src/quick/util/qquickimageprovider_p.h
new file mode 100644
index 0000000000..b5baf79319
--- /dev/null
+++ b/src/quick/util/qquickimageprovider_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKQQUICKIMAGEPROVIDER_P_H
+#define QQUICKQQUICKIMAGEPROVIDER_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 <private/qobject_p.h>
+#include <qquickimageprovider.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickImageResponsePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickImageResponse)
+public:
+ bool finished = false;
+
+ void _q_finished() { finished = true; }
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QQUICKQQUICKIMAGEPROVIDER_P_H
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 4237ec3edf..0dd2a88ca1 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -39,6 +39,7 @@
#include "qquickpixmapcache_p.h"
#include <qquickimageprovider.h>
+#include "qquickimageprovider_p.h"
#include <qqmlengine.h>
#include <private/qqmlglobal_p.h>
@@ -179,6 +180,8 @@ public:
QQuickPixmapReaderThreadObject(QQuickPixmapReader *);
void processJobs();
bool event(QEvent *e) override;
+public slots:
+ void asyncResponseFinished(QQuickImageResponse *response);
private slots:
void networkRequestDone();
void asyncResponseFinished();
@@ -613,10 +616,15 @@ void QQuickPixmapReaderThreadObject::networkRequestDone()
#endif
}
+void QQuickPixmapReaderThreadObject::asyncResponseFinished(QQuickImageResponse *response)
+{
+ reader->asyncResponseFinished(response);
+}
+
void QQuickPixmapReaderThreadObject::asyncResponseFinished()
{
QQuickImageResponse *response = static_cast<QQuickImageResponse *>(sender());
- reader->asyncResponseFinished(response);
+ asyncResponseFinished(response);
}
void QQuickPixmapReader::processJobs()
@@ -800,7 +808,14 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize);
}
- QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished()));
+ // Might be that the async provider was so quick it emitted the signal before we
+ // could connect to it.
+ if (static_cast<QQuickImageResponsePrivate*>(QObjectPrivate::get(response))->finished) {
+ QMetaObject::invokeMethod(threadObject, "asyncResponseFinished",
+ Qt::QueuedConnection, Q_ARG(QQuickImageResponse*, response));
+ } else {
+ QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished()));
+ }
asyncResponses.insert(response, runningJob);
break;
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index bd9f04e562..decc6eac31 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -116,9 +116,8 @@ void QQuickProfiler::stopProfilingImpl()
m_data.clear();
}
-void QQuickProfiler::reportDataImpl(bool trackLocations)
+void QQuickProfiler::reportDataImpl()
{
- Q_UNUSED(trackLocations);
QMutexLocker lock(&m_dataMutex);
emit dataReady(m_data);
m_data.clear();
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index d699ddf371..28b058c2e8 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -357,7 +357,7 @@ protected:
void startProfilingImpl(quint64 features);
void stopProfilingImpl();
- void reportDataImpl(bool trackLocations);
+ void reportDataImpl();
void setTimer(const QElapsedTimer &t);
};
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index a3a598621f..9c01a3f80e 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -298,7 +298,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
}
}
- if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->containsTranslations()) {
+ if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
QUrl url = QUrl();
int line = -1;
int column = -1;
@@ -313,7 +313,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
QString expression;
QQmlBinding::Identifier id = QQmlBinding::Invalid;
- if (!binding->containsTranslations()) {
+ if (!binding->isTranslationBinding()) {
expression = binding->valueAsString(qmlUnit);
id = binding->value.compiledScriptIndex;
}
@@ -468,7 +468,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
QQmlContextData *context = QQmlContextData::get(qmlContext(this));
QQmlBinding *newBinding = nullptr;
- if (e.binding && e.binding->containsTranslations()) {
+ if (e.binding && e.binding->isTranslationBinding()) {
newBinding = QQmlBinding::createTranslationBinding(d->compilationUnit, e.binding, object(), context);
} else if (e.id != QQmlBinding::Invalid) {
QV4::Scope scope(qmlEngine(this)->handle());
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index b953ad1c7f..3ca6440784 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -222,7 +222,7 @@ bool QQuickState::isWhenKnown() const
QQmlBinding *QQuickState::when() const
{
Q_D(const QQuickState);
- return d->when;
+ return d->when.data();
}
void QQuickState::setWhen(QQmlBinding *when)
diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h
index f1bc24c558..61472b4d06 100644
--- a/src/quick/util/qquickstate_p_p.h
+++ b/src/quick/util/qquickstate_p_p.h
@@ -203,12 +203,12 @@ class QQuickStatePrivate : public QObjectPrivate
public:
QQuickStatePrivate()
- : when(nullptr), named(false), inState(false), group(nullptr) {}
+ : named(false), inState(false), group(nullptr) {}
typedef QList<QQuickSimpleAction> SimpleActionList;
QString name;
- QQmlBinding *when;
+ QQmlBinding::Ptr when;
bool named;
struct OperationGuard : public QQmlGuard<QQuickStateOperation>
diff --git a/src/quick/util/qquicksvgparser.cpp b/src/quick/util/qquicksvgparser.cpp
index 2bf9c121d3..0687913565 100644
--- a/src/quick/util/qquicksvgparser.cpp
+++ b/src/quick/util/qquicksvgparser.cpp
@@ -280,11 +280,8 @@ bool QQuickSvgParser::parsePathDataFast(const QString &dataStr, QPainterPath &pa
++str;
QChar pathElem = *str;
++str;
- QChar endc = *end;
- *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
QVarLengthArray<qreal, 8> arg;
parseNumbersArray(str, arg);
- *const_cast<QChar *>(end) = endc;
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
arg.append(0);//dummy
const qreal *num = arg.constData();
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index b2e5b84cf4..31d4d4c437 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -132,4 +132,7 @@ void QQuickUtilModule::defineModule()
qmlRegisterType<QQuickShortcut,9>("QtQuick", 2, 9, "Shortcut");
#endif
+
+ qmlRegisterUncreatableType<QQuickAbstractAnimation, 12>("QtQuick", 2, 12, "Animation",
+ QQuickAbstractAnimation::tr("Animation is an abstract class"));
}
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index edcb268cd9..c51f082d03 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -53,6 +53,7 @@ HEADERS += \
$$PWD/qquickfontloader_p.h \
$$PWD/qquickstyledtext_p.h \
$$PWD/qquickimageprovider.h \
+ $$PWD/qquickimageprovider_p.h \
$$PWD/qquicksvgparser_p.h \
$$PWD/qquickvaluetypes_p.h \
$$PWD/qquickanimator_p.h \
diff --git a/src/imports/shapes/qquicknvprfunctions.cpp b/src/quickshapes/qquicknvprfunctions.cpp
index 409a59be7f..409a59be7f 100644
--- a/src/imports/shapes/qquicknvprfunctions.cpp
+++ b/src/quickshapes/qquicknvprfunctions.cpp
diff --git a/src/imports/shapes/qquicknvprfunctions_p.h b/src/quickshapes/qquicknvprfunctions_p.h
index 342e92cbc3..92246cf4c8 100644
--- a/src/imports/shapes/qquicknvprfunctions_p.h
+++ b/src/quickshapes/qquicknvprfunctions_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
#include <qopengl.h>
#include <QtGui/qsurfaceformat.h>
diff --git a/src/imports/shapes/qquicknvprfunctions_p_p.h b/src/quickshapes/qquicknvprfunctions_p_p.h
index 6df20566af..3d9ca0de9f 100644
--- a/src/imports/shapes/qquicknvprfunctions_p_p.h
+++ b/src/quickshapes/qquicknvprfunctions_p_p.h
@@ -51,7 +51,8 @@
// We mean it.
//
-#include "qquicknvprfunctions_p.h"
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
+#include <QtQuickShapes/private/qquicknvprfunctions_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/imports/shapes/qquickshape.cpp b/src/quickshapes/qquickshape.cpp
index 067a54736f..edfa308c4d 100644
--- a/src/imports/shapes/qquickshape.cpp
+++ b/src/quickshapes/qquickshape.cpp
@@ -658,9 +658,22 @@ void QQuickShapePrivate::setStatus(QQuickShape::Status newStatus)
}
}
+struct QQuickShapeResourceInitializer
+{
+ QQuickShapeResourceInitializer()
+ {
+#if defined(QT_STATIC)
+ Q_INIT_RESOURCE(qtquickshapes);
+#endif
+ }
+};
+
+Q_GLOBAL_STATIC(QQuickShapeResourceInitializer, initQQuickShapeResources)
+
QQuickShape::QQuickShape(QQuickItem *parent)
: QQuickItem(*(new QQuickShapePrivate), parent)
{
+ initQQuickShapeResources();
setFlag(ItemHasContents);
}
diff --git a/src/imports/shapes/qquickshape_p.h b/src/quickshapes/qquickshape_p.h
index 1dfeaf9228..cd242cafc3 100644
--- a/src/imports/shapes/qquickshape_p.h
+++ b/src/quickshapes/qquickshape_p.h
@@ -51,7 +51,8 @@
// We mean it.
//
-#include "qquickitem.h"
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
+#include <QtQuick/qquickitem.h>
#include <private/qtquickglobal_p.h>
#include <private/qquickpath_p_p.h>
@@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QQuickShapePathPrivate;
class QQuickShapePrivate;
-class QQuickShapeGradient : public QQuickGradient
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeGradient : public QQuickGradient
{
Q_OBJECT
Q_PROPERTY(SpreadMode spread READ spread WRITE setSpread NOTIFY spreadChanged)
@@ -88,7 +89,7 @@ private:
SpreadMode m_spread;
};
-class QQuickShapeLinearGradient : public QQuickShapeGradient
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeLinearGradient : public QQuickShapeGradient
{
Q_OBJECT
Q_PROPERTY(qreal x1 READ x1 WRITE setX1 NOTIFY x1Changed)
@@ -120,7 +121,7 @@ private:
QPointF m_end;
};
-class QQuickShapeRadialGradient : public QQuickShapeGradient
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeRadialGradient : public QQuickShapeGradient
{
Q_OBJECT
Q_PROPERTY(qreal centerX READ centerX WRITE setCenterX NOTIFY centerXChanged)
@@ -167,7 +168,7 @@ private:
qreal m_focalRadius = 0;
};
-class QQuickShapeConicalGradient : public QQuickShapeGradient
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeConicalGradient : public QQuickShapeGradient
{
Q_OBJECT
Q_PROPERTY(qreal centerX READ centerX WRITE setCenterX NOTIFY centerXChanged)
@@ -197,7 +198,7 @@ private:
qreal m_angle = 0;
};
-class QQuickShapePath : public QQuickPath
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapePath : public QQuickPath
{
Q_OBJECT
@@ -296,7 +297,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_fillGradientChanged())
};
-class QQuickShape : public QQuickItem
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShape : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(RendererType rendererType READ rendererType NOTIFY rendererChanged)
diff --git a/src/imports/shapes/qquickshape_p_p.h b/src/quickshapes/qquickshape_p_p.h
index ef2775885e..bf4a47f62c 100644
--- a/src/imports/shapes/qquickshape_p_p.h
+++ b/src/quickshapes/qquickshape_p_p.h
@@ -51,7 +51,8 @@
// We mean it.
//
-#include "qquickshape_p.h"
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
+#include <QtQuickShapes/private/qquickshape_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QPainterPath>
#include <QColor>
@@ -122,7 +123,7 @@ struct QQuickShapeStrokeFillParams
QQuickShapeGradient *fillGradient;
};
-class QQuickShapePathPrivate : public QQuickPathPrivate
+class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapePathPrivate : public QQuickPathPrivate
{
Q_DECLARE_PUBLIC(QQuickShapePath)
diff --git a/src/imports/shapes/qquickshapegenericrenderer.cpp b/src/quickshapes/qquickshapegenericrenderer.cpp
index 8a4785a83a..8a4785a83a 100644
--- a/src/imports/shapes/qquickshapegenericrenderer.cpp
+++ b/src/quickshapes/qquickshapegenericrenderer.cpp
diff --git a/src/imports/shapes/qquickshapegenericrenderer_p.h b/src/quickshapes/qquickshapegenericrenderer_p.h
index 11070ae7dc..9928d7ab72 100644
--- a/src/imports/shapes/qquickshapegenericrenderer_p.h
+++ b/src/quickshapes/qquickshapegenericrenderer_p.h
@@ -51,7 +51,8 @@
// We mean it.
//
-#include "qquickshape_p_p.h"
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
+#include <QtQuickShapes/private/qquickshape_p_p.h>
#include <qsgnode.h>
#include <qsggeometry.h>
#include <qsgmaterial.h>
diff --git a/src/imports/shapes/qquickshapenvprrenderer.cpp b/src/quickshapes/qquickshapenvprrenderer.cpp
index 51af0d8961..51af0d8961 100644
--- a/src/imports/shapes/qquickshapenvprrenderer.cpp
+++ b/src/quickshapes/qquickshapenvprrenderer.cpp
diff --git a/src/imports/shapes/qquickshapenvprrenderer_p.h b/src/quickshapes/qquickshapenvprrenderer_p.h
index f6c9fc169e..d40eb1bce9 100644
--- a/src/imports/shapes/qquickshapenvprrenderer_p.h
+++ b/src/quickshapes/qquickshapenvprrenderer_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
-#include "qquickshape_p_p.h"
-#include "qquicknvprfunctions_p.h"
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
+#include <QtQuickShapes/private/qquickshape_p_p.h>
+#include <QtQuickShapes/private/qquicknvprfunctions_p.h>
#include <qsgrendernode.h>
#include <QColor>
#include <QVector4D>
diff --git a/src/quickshapes/qquickshapesglobal.h b/src/quickshapes/qquickshapesglobal.h
new file mode 100644
index 0000000000..eb279c5d14
--- /dev/null
+++ b/src/quickshapes/qquickshapesglobal.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QQUICKSHAPESGLOBAL_H
+#define QQUICKSHAPESGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_STATIC
+# if defined(QT_BUILD_QUICKSHAPES_LIB)
+# define Q_QUICKSHAPES_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QUICKSHAPES_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define Q_QUICKSHAPES_EXPORT
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSHAPESGLOBAL_H
+
diff --git a/src/quickshapes/qquickshapesglobal_p.h b/src/quickshapes/qquickshapesglobal_p.h
new file mode 100644
index 0000000000..2f559b45a0
--- /dev/null
+++ b/src/quickshapes/qquickshapesglobal_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSHAPESGLOBAL_P_H
+#define QQUICKSHAPESGLOBAL_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 "qquickshapesglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+#define Q_QUICKSHAPES_PRIVATE_EXPORT Q_QUICKSHAPES_EXPORT
+
+QT_END_NAMESPACE
+
+
+#endif // QQUICKSHAPESGLOBAL_P_H
diff --git a/src/imports/shapes/qquickshapesoftwarerenderer.cpp b/src/quickshapes/qquickshapesoftwarerenderer.cpp
index 0f5c3604b5..0f5c3604b5 100644
--- a/src/imports/shapes/qquickshapesoftwarerenderer.cpp
+++ b/src/quickshapes/qquickshapesoftwarerenderer.cpp
diff --git a/src/imports/shapes/qquickshapesoftwarerenderer_p.h b/src/quickshapes/qquickshapesoftwarerenderer_p.h
index 0abc2e37b0..11e658b4b7 100644
--- a/src/imports/shapes/qquickshapesoftwarerenderer_p.h
+++ b/src/quickshapes/qquickshapesoftwarerenderer_p.h
@@ -51,7 +51,8 @@
// We mean it.
//
-#include "qquickshape_p_p.h"
+#include <QtQuickShapes/private/qquickshapesglobal_p.h>
+#include <QtQuickShapes/private/qquickshape_p_p.h>
#include <qsgrendernode.h>
#include <QPen>
#include <QBrush>
diff --git a/src/imports/shapes/qtquickshapesplugin.qrc b/src/quickshapes/qtquickshapes.qrc
index f139861693..f139861693 100644
--- a/src/imports/shapes/qtquickshapesplugin.qrc
+++ b/src/quickshapes/qtquickshapes.qrc
diff --git a/src/quickshapes/quickshapes.pro b/src/quickshapes/quickshapes.pro
new file mode 100644
index 0000000000..5a59dec18e
--- /dev/null
+++ b/src/quickshapes/quickshapes.pro
@@ -0,0 +1,33 @@
+TARGET = QtQuickShapes
+
+QT = core gui-private qml quick-private
+
+CONFIG += simd optimize_full internal_module
+
+HEADERS += \
+ qquickshapesglobal.h \
+ qquickshapesglobal_p.h \
+ qquickshape_p.h \
+ qquickshape_p_p.h \
+ qquickshapegenericrenderer_p.h \
+ qquickshapesoftwarerenderer_p.h
+
+SOURCES += \
+ qquickshape.cpp \
+ qquickshapegenericrenderer.cpp \
+ qquickshapesoftwarerenderer.cpp
+
+qtConfig(opengl) {
+ HEADERS += \
+ qquicknvprfunctions_p.h \
+ qquicknvprfunctions_p_p.h \
+ qquickshapenvprrenderer_p.h
+
+ SOURCES += \
+ qquicknvprfunctions.cpp \
+ qquickshapenvprrenderer.cpp
+}
+
+RESOURCES += qtquickshapes.qrc
+
+load(qt_module)
diff --git a/src/imports/shapes/shaders/blit.frag b/src/quickshapes/shaders/blit.frag
index 505f0db179..505f0db179 100644
--- a/src/imports/shapes/shaders/blit.frag
+++ b/src/quickshapes/shaders/blit.frag
diff --git a/src/imports/shapes/shaders/blit.vert b/src/quickshapes/shaders/blit.vert
index f8306bd945..f8306bd945 100644
--- a/src/imports/shapes/shaders/blit.vert
+++ b/src/quickshapes/shaders/blit.vert
diff --git a/src/imports/shapes/shaders/blit_core.frag b/src/quickshapes/shaders/blit_core.frag
index 7073808fba..7073808fba 100644
--- a/src/imports/shapes/shaders/blit_core.frag
+++ b/src/quickshapes/shaders/blit_core.frag
diff --git a/src/imports/shapes/shaders/blit_core.vert b/src/quickshapes/shaders/blit_core.vert
index 5246441da3..5246441da3 100644
--- a/src/imports/shapes/shaders/blit_core.vert
+++ b/src/quickshapes/shaders/blit_core.vert
diff --git a/src/imports/shapes/shaders/conicalgradient.frag b/src/quickshapes/shaders/conicalgradient.frag
index af5fdd5ee0..af5fdd5ee0 100644
--- a/src/imports/shapes/shaders/conicalgradient.frag
+++ b/src/quickshapes/shaders/conicalgradient.frag
diff --git a/src/imports/shapes/shaders/conicalgradient.vert b/src/quickshapes/shaders/conicalgradient.vert
index 3350b0675a..3350b0675a 100644
--- a/src/imports/shapes/shaders/conicalgradient.vert
+++ b/src/quickshapes/shaders/conicalgradient.vert
diff --git a/src/imports/shapes/shaders/conicalgradient_core.frag b/src/quickshapes/shaders/conicalgradient_core.frag
index e18b80159a..e18b80159a 100644
--- a/src/imports/shapes/shaders/conicalgradient_core.frag
+++ b/src/quickshapes/shaders/conicalgradient_core.frag
diff --git a/src/imports/shapes/shaders/conicalgradient_core.vert b/src/quickshapes/shaders/conicalgradient_core.vert
index f94a56401b..f94a56401b 100644
--- a/src/imports/shapes/shaders/conicalgradient_core.vert
+++ b/src/quickshapes/shaders/conicalgradient_core.vert
diff --git a/src/imports/shapes/shaders/lineargradient.frag b/src/quickshapes/shaders/lineargradient.frag
index 7f4a739109..7f4a739109 100644
--- a/src/imports/shapes/shaders/lineargradient.frag
+++ b/src/quickshapes/shaders/lineargradient.frag
diff --git a/src/imports/shapes/shaders/lineargradient.vert b/src/quickshapes/shaders/lineargradient.vert
index eb21b8886b..eb21b8886b 100644
--- a/src/imports/shapes/shaders/lineargradient.vert
+++ b/src/quickshapes/shaders/lineargradient.vert
diff --git a/src/imports/shapes/shaders/lineargradient_core.frag b/src/quickshapes/shaders/lineargradient_core.frag
index 5908acfa67..5908acfa67 100644
--- a/src/imports/shapes/shaders/lineargradient_core.frag
+++ b/src/quickshapes/shaders/lineargradient_core.frag
diff --git a/src/imports/shapes/shaders/lineargradient_core.vert b/src/quickshapes/shaders/lineargradient_core.vert
index 60b56f38e3..60b56f38e3 100644
--- a/src/imports/shapes/shaders/lineargradient_core.vert
+++ b/src/quickshapes/shaders/lineargradient_core.vert
diff --git a/src/imports/shapes/shaders/radialgradient.frag b/src/quickshapes/shaders/radialgradient.frag
index 0f503bc0f7..0f503bc0f7 100644
--- a/src/imports/shapes/shaders/radialgradient.frag
+++ b/src/quickshapes/shaders/radialgradient.frag
diff --git a/src/imports/shapes/shaders/radialgradient.vert b/src/quickshapes/shaders/radialgradient.vert
index 3350b0675a..3350b0675a 100644
--- a/src/imports/shapes/shaders/radialgradient.vert
+++ b/src/quickshapes/shaders/radialgradient.vert
diff --git a/src/imports/shapes/shaders/radialgradient_core.frag b/src/quickshapes/shaders/radialgradient_core.frag
index 706ce53e4d..706ce53e4d 100644
--- a/src/imports/shapes/shaders/radialgradient_core.frag
+++ b/src/quickshapes/shaders/radialgradient_core.frag
diff --git a/src/imports/shapes/shaders/radialgradient_core.vert b/src/quickshapes/shaders/radialgradient_core.vert
index f94a56401b..f94a56401b 100644
--- a/src/imports/shapes/shaders/radialgradient_core.vert
+++ b/src/quickshapes/shaders/radialgradient_core.vert
diff --git a/src/src.pro b/src/src.pro
index 5177dfc743..92d79a9825 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -2,15 +2,18 @@ TEMPLATE = subdirs
CONFIG += ordered
include($$OUT_PWD/qml/qtqml-config.pri)
include($$OUT_PWD/quick/qtquick-config.pri)
-QT_FOR_CONFIG += qml quick-private
+QT_FOR_CONFIG += qml qml-private quick-private
SUBDIRS += \
qml
-qtHaveModule(gui):qtConfig(animation) {
+qtConfig(qml-animation) {
SUBDIRS += \
- quick
+ quick \
+ quickshapes
+
+ qtConfig(testlib): \
+ SUBDIRS += qmltest
- qtConfig(testlib): SUBDIRS += qmltest
qtConfig(quick-particles): \
SUBDIRS += particles
qtHaveModule(widgets): SUBDIRS += quickwidgets
@@ -18,8 +21,9 @@ qtHaveModule(gui):qtConfig(animation) {
SUBDIRS += \
plugins \
- imports \
- qmldevtools
+ imports
+
+qtConfig(qml-devtools): SUBDIRS += qmldevtools
qmldevtools.depends = qml
@@ -27,3 +31,5 @@ qtConfig(qml-network) {
QT_FOR_CONFIG += network
qtConfig(localserver):qtConfig(qml-debug): SUBDIRS += qmldebug
}
+
+DISTFILES += sync.profile configure.json
diff --git a/sync.profile b/sync.profile
index 64abbd2eb9..642942d152 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,9 +1,13 @@
%modules = ( # path to module name map
"QtQml" => "$basedir/src/qml",
"QtQuick" => "$basedir/src/quick",
+ "QtQuickShapes" => "$basedir/src/quickshapes",
"QtQuickWidgets" => "$basedir/src/quickwidgets",
"QtQuickParticles" => "$basedir/src/particles",
"QtQuickTest" => "$basedir/src/qmltest",
"QtPacketProtocol" => "$basedir/src/plugins/qmltooling/packetprotocol",
"QtQmlDebug" => "$basedir/src/qmldebug",
);
+%inject_headers = (
+ "$basedir/src/qml" => [ "^qqmljsgrammar_p.h", "^qqmljsparser_p.h" ],
+);
diff --git a/tests/auto/guiapplauncher/demos.txt b/tests/auto/guiapplauncher/demos.txt
deleted file mode 100644
index 1c48b6923d..0000000000
--- a/tests/auto/guiapplauncher/demos.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-"quick/demos/clocks Example", "examples/quick/demos/clocks", "clocks", 0, -1
-"quick/demos/maroon Example", "examples/quick/demos/maroon", "maroon", 0, -1
-"quick/demos/calqlatr Example", "examples/quick/demos/calqlatr", "calqlatr", 0, -1
-"quick/demos/stocqt Example", "examples/quick/demos/stocqt", "stocqt", 0, -1
-"quick/demos/tweetsearch Example", "examples/quick/demos/tweetsearch", "tweetsearch", 0, -1
-"quick/demos/samegame Example", "examples/quick/demos/samegame", "samegame", 0, -1
-"quick/demos/phoyosurface Example", "examples/quick/demos/photosurface", "photosurface", 10, -1
-"quick/demos/rssnews Example", "examples/quick/demos/rssnews", "rssnews", 0, -1
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro
index 63721cc575..5c328fbfcc 100644
--- a/tests/auto/qml/debugger/debugger.pro
+++ b/tests/auto/qml/debugger/debugger.pro
@@ -1,5 +1,7 @@
TEMPLATE = subdirs
+SUBDIRS += qqmldebugjsserver
+
PUBLICTESTS += \
qdebugmessageservice \
qqmlenginedebugservice \
@@ -11,7 +13,8 @@ PUBLICTESTS += \
qqmlenginecontrol \
qqmldebuggingenabler \
qqmlnativeconnector \
- qqmldebugprocess
+ qqmldebugprocess \
+ qqmlpreview
PRIVATETESTS += \
qqmldebugclient \
@@ -21,6 +24,9 @@ PRIVATETESTS += \
SUBDIRS += $$PUBLICTESTS
+qqmldebugjs.depends = qqmldebugjsserver
+qqmlprofilerservice.depends = qqmldebugjsserver
+
qtConfig(private_tests): \
SUBDIRS += $$PRIVATETESTS
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
index f851688b5e..d2cfd3897a 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
+++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
@@ -89,21 +89,12 @@ public:
protected:
//inherited from QQmlDebugClient
- void stateChanged(State state);
void messageReceived(const QByteArray &data);
signals:
- void enabled();
void debugOutput();
};
-void QQmlDebugMsgClient::stateChanged(State state)
-{
- if (state == Enabled) {
- emit enabled();
- }
-}
-
void QQmlDebugMsgClient::messageReceived(const QByteArray &data)
{
QPacket ds(connection()->currentDataStreamVersion(), data);
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 452520cf11..ffdbf72ded 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -66,8 +66,6 @@ void tst_QQmlDebugClient::initTestCase()
QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
QQmlDebugConnector::setServices(QStringList()
<< QStringLiteral("tst_QQmlDebugClient::handshake()"));
- QTest::ignoreMessage(QtWarningMsg,
- "QML debugger: Cannot set plugin key after loading the plugin.");
m_service = new QQmlDebugTestService("tst_QQmlDebugClient::handshake()");
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
index 52e7f85e52..37118f4bd0 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
@@ -125,7 +125,7 @@ void tst_QQmlDebuggingEnabler::qmlscene()
QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable);
}
- QCOMPARE(m_process->state(), QLatin1String("running"));
+ QCOMPARE(m_process->state(), QProcess::Running);
if (!blockMode) {
QTRY_VERIFY_WITH_TIMEOUT(m_process->output().contains(
QLatin1String("Component.onCompleted")), 15000);
@@ -172,7 +172,7 @@ void tst_QQmlDebuggingEnabler::custom()
QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable);
}
- QCOMPARE(m_process->state(), QLatin1String("running"));
+ QCOMPARE(m_process->state(), QProcess::Running);
if (!blockMode) {
QTRY_VERIFY_WITH_TIMEOUT(m_process->output().contains(QLatin1String("QQmlEngine created")),
15000);
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/breakpointRelocation.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
index 06aabc94f9..06aabc94f9 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/breakpointRelocation.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/changeBreakpoint.qml b/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
index 00a85e56ac..00a85e56ac 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/changeBreakpoint.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/condition.qml b/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
index 3a50ba2eb7..3a50ba2eb7 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/condition.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/createComponent.qml b/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
index 089cc03733..089cc03733 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/createComponent.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml b/tests/auto/qml/debugger/qqmldebugjs/data/encodeQmlScope.qml
index 7ea048044f..7ea048044f 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/encodeQmlScope.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/exception.qml b/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
index 06f11fa016..06f11fa016 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/exception.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/loadjsfile.qml b/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
index 088c1b19fd..088c1b19fd 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/loadjsfile.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/oncompleted.qml b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
index deba24cf91..deba24cf91 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/oncompleted.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/quit.qml b/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
index bc8c2b90ae..bc8c2b90ae 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/quit.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/stepAction.qml b/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
index fb0b6c401c..fb0b6c401c 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/stepAction.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/test.js b/tests/auto/qml/debugger/qqmldebugjs/data/test.js
index 92e61d103c..92e61d103c 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/test.js
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/test.js
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/test.qml b/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
index a36d0cae91..a36d0cae91 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/timer.qml b/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
index 66e6b96e18..66e6b96e18 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/timer.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
index bd6debcea1..b9d5f116dc 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
@@ -1,4 +1,24 @@
-TEMPLATE = subdirs
-SUBDIRS = qqmldebugjs qqmldebugjsserver
+CONFIG += testcase
+TARGET = tst_qqmldebugjs
+QT += qml testlib gui-private core-private
+macos:CONFIG -= app_bundle
-qqmldebugjs.depends = qqmldebugjsserver
+SOURCES += tst_qqmldebugjs.cpp
+
+INCLUDEPATH += ../shared
+include(../shared/debugutil.pri)
+include(../shared/qqmlenginedebugclient.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/test.qml data/test.js \
+ data/timer.qml \
+ data/exception.qml \
+ data/oncompleted.qml \
+ data/loadjsfile.qml \
+ data/condition.qml \
+ data/changeBreakpoint.qml \
+ data/stepAction.qml \
+ data/breakpointRelocation.qml \
+ data/createComponent.qml \
+ data/encodeQmlScope.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro
deleted file mode 100644
index 52d70bd1b1..0000000000
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro
+++ /dev/null
@@ -1,24 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qqmldebugjs
-QT += qml testlib gui-private core-private
-CONFIG -= debug_and_release_target
-osx:CONFIG -= app_bundle
-
-SOURCES += tst_qqmldebugjs.cpp
-
-include(../../shared/debugutil.pri)
-include(../../shared/qqmlenginedebugclient.pri)
-
-TESTDATA = data/*
-
-OTHER_FILES += data/test.qml data/test.js \
- data/timer.qml \
- data/exception.qml \
- data/oncompleted.qml \
- data/loadjsfile.qml \
- data/condition.qml \
- data/changeBreakpoint.qml \
- data/stepAction.qml \
- data/breakpointRelocation.qml \
- data/createComponent.qml \
- data/encodeQmlScope.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.pro
deleted file mode 100644
index 837eaed9f1..0000000000
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-QT += qml testlib
-osx:CONFIG -= app_bundle
-CONFIG -= debug_and_release_target
-INCLUDEPATH += ../../shared
-SOURCES += qqmldebugjsserver.cpp
-DEFINES += QT_QML_DEBUG_NO_WARNING
-
-DESTDIR = ../qqmldebugjs
-
-target.path = $$[QT_INSTALL_TESTS]/tst_qqmldebugjs
-INSTALLS += target
-
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index a28dbcd9de..e3996e0c18 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -28,8 +28,8 @@
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
-#include "../../shared/qqmlenginedebugclient.h"
-#include "../../../../shared/util.h"
+#include "../shared/qqmlenginedebugclient.h"
+#include "../../../shared/util.h"
#include <private/qqmldebugclient_p.h>
#include <private/qqmldebugconnection_p.h>
@@ -256,6 +256,8 @@ public:
{
parser = jsEngine.evaluate(QLatin1String("JSON.parse"));
stringify = jsEngine.evaluate(QLatin1String("JSON.stringify"));
+ QObject::connect(this, &QQmlDebugClient::stateChanged,
+ this, &QJSDebugClient::onStateChanged);
}
void connect(bool redundantRefs = false, bool namesAsObjects = false);
@@ -277,7 +279,7 @@ public:
protected:
//inherited from QQmlDebugClient
- void stateChanged(State state);
+ void onStateChanged(State state);
void messageReceived(const QByteArray &data);
signals:
@@ -665,7 +667,7 @@ void QJSDebugClient::disconnect()
sendMessage(packMessage(DISCONNECT, json.toString().toUtf8()));
}
-void QJSDebugClient::stateChanged(State state)
+void QJSDebugClient::onStateChanged(State state)
{
if (state == Enabled)
flushSendBuffer();
@@ -770,7 +772,7 @@ QQmlDebugTest::ConnectResult tst_QQmlDebugJS::init(bool qmlscene, const QString
{
const QString executable = qmlscene
? QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene"
- : QCoreApplication::applicationDirPath() + QLatin1String("/qqmldebugjsserver");
+ : debugJsServerPath("qqmldebugjs");
return QQmlDebugTest::connect(
executable, restrictServices ? QStringLiteral("V8Debugger") : QString(),
testFile(qmlFile), blockMode);
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.cpp b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
index 6a4ec5cc75..6a4ec5cc75 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjsserver/qqmldebugjsserver.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
diff --git a/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.pro b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.pro
new file mode 100644
index 0000000000..a31da57054
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.pro
@@ -0,0 +1,9 @@
+QT += qml testlib
+macos:CONFIG -= app_bundle
+INCLUDEPATH += ../shared
+SOURCES += qqmldebugjsserver.cpp
+DEFINES += QT_QML_DEBUG_NO_WARNING
+
+target.path = $$[QT_INSTALL_TESTS]/qqmldebugjsserver
+INSTALLS += target
+
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
index 5b3c0c5240..4e47c92c2a 100644
--- a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
+++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
@@ -65,8 +65,6 @@ void tst_QQmlDebugLocal::initTestCase()
{
fileName = QString::fromLatin1("tst_QQmlDebugLocal%1").arg(std::time(nullptr));
QQmlDebugConnector::setPluginKey("QQmlDebugServer");
- QTest::ignoreMessage(QtWarningMsg,
- "QML debugger: Cannot set plugin key after loading the plugin.");
m_service = new QQmlDebugTestService("tst_QQmlDebugLocal::handshake()");
const QString waitingMsg = QString("QML Debugger: Connecting to socket %1...").arg(fileName);
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
index 993a1d5f63..35bd912d9b 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
@@ -118,7 +118,7 @@ void tst_QQmlDebugProcess::sessionStart()
QTimer::singleShot(delay, process.data(), wait);
QTRY_VERIFY(done);
- QVERIFY(process->state().startsWith("not running"));
+ QCOMPARE(process->state(), QProcess::NotRunning);
}
QTEST_MAIN(tst_QQmlDebugProcess)
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index 1daf6b581e..3557940386 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -75,8 +75,6 @@ void tst_QQmlDebugService::initTestCase()
QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
QQmlDebugConnector::setServices(QStringList()
<< QStringLiteral("tst_QQmlDebugService"));
- QTest::ignoreMessage(QtWarningMsg,
- "QML debugger: Cannot set plugin key after loading the plugin.");
m_service = new QQmlDebugTestService("tst_QQmlDebugService", 2);
foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices())
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/broken.qml b/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
new file mode 100644
index 0000000000..4ebbf7576a
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml b/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
new file mode 100644
index 0000000000..b525ab4fa0
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 100
+ height: 100
+ color: "blue"
+
+ RotationAnimation on rotation {
+ duration: 3600
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ }
+
+ Timer {
+ interval: 300
+ repeat: true
+ running: true
+ property int prevHit: -1
+ property int prevRotation: -1
+ onTriggered: {
+ var date = new Date;
+ var millis = date.getMilliseconds()
+
+ if (prevHit < 0) {
+ prevHit = millis;
+ prevRotation = parent.rotation
+ return;
+ }
+
+ var milliDelta = millis - prevHit;
+ if (milliDelta <= 0)
+ milliDelta += 1000;
+ prevHit = millis;
+
+ var delta = parent.rotation - prevRotation;
+ if (delta < 0)
+ delta += 360
+ prevRotation = parent.rotation
+ console.log(milliDelta, delta, "ms/degrees ");
+ }
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window.qml b/tests/auto/qml/debugger/qqmlpreview/data/window.qml
new file mode 100644
index 0000000000..f9f8d5aeb1
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.0
+
+Window {
+ visible: true
+
+ height: 100
+ width: 100
+
+ Timer {
+ repeat: false
+ interval: 1000
+ running: true
+ onTriggered: console.log("window.qml");
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window1.qml b/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
new file mode 100644
index 0000000000..e8e9ad706d
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.3
+
+Window {
+ visible: true
+
+ height: 200
+ width: 100
+
+ Timer {
+ interval: 1000
+ running: true
+ onTriggered: console.log("window1.qml");
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window2.qml b/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
new file mode 100644
index 0000000000..9ad42d2ee2
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.3
+
+Window {
+ visible: true
+
+ height: 100
+ width: 200
+
+ Timer {
+ interval: 1000
+ running: true
+ onTriggered: console.log("window2.qml");
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml b/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
new file mode 100644
index 0000000000..0aca235de1
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.2
+
+Window {
+ id: w
+ height: 100
+ width: 100
+ visible: true
+
+ Rectangle {
+ width: 50
+ height: 50
+ color: "blue"
+ anchors.centerIn: parent
+ }
+
+ Timer {
+ interval: 100
+ running: true
+ repeat: true
+ onTriggered: console.log("zoom", w.screen.devicePixelRatio)
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmlpreview/qqmlpreview.pro b/tests/auto/qml/debugger/qqmlpreview/qqmlpreview.pro
new file mode 100644
index 0000000000..4a0d385e1a
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/qqmlpreview.pro
@@ -0,0 +1,24 @@
+CONFIG += testcase
+TARGET = tst_qqmlpreview
+
+QT += qml testlib core qmldebug-private
+macos:CONFIG -= app_bundle
+
+INCLUDEPATH += ../../../../../src/plugins/qmltooling/qmldbg_preview/
+
+SOURCES += \
+ tst_qqmlpreview.cpp \
+ ../../../../../src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.cpp
+
+HEADERS += \
+ ../../../../../src/plugins/qmltooling/qmldbg_preview/qqmlpreviewblacklist.h
+
+include(../shared/debugutil.pri)
+
+TESTDATA = \
+ data/window.qml \
+ data/qtquick2.qml \
+ data/window2.qml \
+ data/window1.qml \
+ data/broken.qml \
+ data/zoom.qml
diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
new file mode 100644
index 0000000000..fa416900d0
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugprocess_p.h"
+#include "debugutil_p.h"
+#include "qqmlpreviewblacklist.h"
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtNetwork/qhostaddress.h>
+
+#include <private/qqmldebugconnection_p.h>
+#include <private/qqmlpreviewclient_p.h>
+
+class tst_QQmlPreview : public QQmlDebugTest
+{
+ Q_OBJECT
+
+private:
+ ConnectResult startQmlProcess(const QString &qmlFile);
+ void serveRequest(const QString &path);
+ QList<QQmlDebugClient *> createClients() override;
+
+ QPointer<QQmlPreviewClient> m_client;
+
+ QStringList m_files;
+ QStringList m_filesNotFound;
+ QStringList m_directories;
+ QStringList m_serviceErrors;
+
+private slots:
+ void cleanup() final;
+
+ void connect();
+ void load();
+ void rerun();
+ void blacklist();
+ void error();
+ void zoom();
+};
+
+QQmlDebugTest::ConnectResult tst_QQmlPreview::startQmlProcess(const QString &qmlFile)
+{
+ return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml",
+ QStringLiteral("QmlPreview"), testFile(qmlFile), true);
+}
+
+void tst_QQmlPreview::serveRequest(const QString &path)
+{
+ QFileInfo info(path);
+
+ if (info.isDir()) {
+ m_directories.append(path);
+ m_client->sendDirectory(path, QDir(path).entryList());
+ } else {
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly)) {
+ m_files.append(path);
+ m_client->sendFile(path, file.readAll());
+ } else {
+ m_filesNotFound.append(path);
+ m_client->sendError(path);
+ }
+ }
+}
+
+QList<QQmlDebugClient *> tst_QQmlPreview::createClients()
+{
+ m_client = new QQmlPreviewClient(m_connection);
+
+ QObject::connect(m_client, &QQmlPreviewClient::request, this, &tst_QQmlPreview::serveRequest);
+ QObject::connect(m_client, &QQmlPreviewClient::error, this, [this](const QString &error) {
+ m_serviceErrors.append(error);
+ });
+
+ return QList<QQmlDebugClient *>({m_client});
+}
+
+void checkFiles(const QStringList &files)
+{
+ QVERIFY(!files.contains("/etc/localtime"));
+ QVERIFY(!files.contains("/etc/timezome"));
+ QVERIFY(!files.contains(":/qgradient/webgradients.binaryjson"));
+}
+
+void tst_QQmlPreview::cleanup()
+{
+ // Use a separate function so that we don't return early from cleanup() on failure.
+ checkFiles(m_files);
+
+ QQmlDebugTest::cleanup();
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Files loaded:" << m_files;
+ qDebug() << "Files not loaded:" << m_filesNotFound;
+ qDebug() << "Directories loaded:" << m_directories;
+ qDebug() << "Errors reported:" << m_serviceErrors;
+ }
+
+ m_directories.clear();
+ m_files.clear();
+ m_filesNotFound.clear();
+ m_serviceErrors.clear();
+}
+
+void tst_QQmlPreview::connect()
+{
+ const QString file("window.qml");
+ QCOMPARE(startQmlProcess(file), ConnectSuccess);
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ m_client->triggerLoad(testFileUrl(file));
+ QTRY_VERIFY(m_files.contains(testFile(file)));
+ QTRY_VERIFY_WITH_TIMEOUT(m_process->output().contains("qml: window.qml"), 10000);
+ m_process->stop();
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::NotConnected);
+ QVERIFY(m_serviceErrors.isEmpty());
+}
+
+void tst_QQmlPreview::load()
+{
+ const QString file("qtquick2.qml");
+ QCOMPARE(startQmlProcess(file), ConnectSuccess);
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+ m_client->triggerLoad(testFileUrl(file));
+ QTRY_VERIFY(m_files.contains(testFile(file)));
+ QTRY_VERIFY(m_process->output().contains("ms/degrees"));
+
+ const QStringList files({"window2.qml", "window1.qml", "window.qml"});
+ for (const QString &newFile : files) {
+ m_client->triggerLoad(testFileUrl(newFile));
+ QTRY_VERIFY(m_files.contains(testFile(newFile)));
+ QTRY_VERIFY(m_process->output().contains(QString::fromLatin1("qml: %1").arg(newFile)));
+ }
+
+ m_process->stop();
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::NotConnected);
+ QVERIFY(m_serviceErrors.isEmpty());
+}
+
+void tst_QQmlPreview::rerun()
+{
+ const QString file("window.qml");
+ QCOMPARE(startQmlProcess(file), ConnectSuccess);
+ QVERIFY(m_client);
+ m_client->triggerLoad(testFileUrl(file));
+ const QLatin1String message("qml: window.qml");
+ QTRY_VERIFY(m_process->output().contains(message));
+ const int pos = m_process->output().lastIndexOf(message) + message.size();
+ QVERIFY(pos >= 0);
+
+ m_client->triggerRerun();
+ QTRY_VERIFY(m_process->output().indexOf(message, pos) >= pos);
+
+ m_process->stop();
+ QVERIFY(m_serviceErrors.isEmpty());
+}
+
+void tst_QQmlPreview::blacklist()
+{
+ QQmlPreviewBlacklist blacklist;
+
+ QStringList strings({
+ "lalala", "lulul", "trakdkd", "suppe", "zack"
+ });
+
+ for (const QString &string : strings)
+ QVERIFY(!blacklist.isBlacklisted(string));
+
+ for (const QString &string : strings)
+ blacklist.blacklist(string);
+
+ for (const QString &string : strings) {
+ QVERIFY(blacklist.isBlacklisted(string));
+ QVERIFY(!blacklist.isBlacklisted(string.left(string.size() / 2)));
+ QVERIFY(!blacklist.isBlacklisted(string + "45"));
+ QVERIFY(!blacklist.isBlacklisted(" " + string));
+ QVERIFY(blacklist.isBlacklisted(string + "/45"));
+ }
+
+ for (auto begin = strings.begin(), it = begin, end = strings.end(); it != end; ++it) {
+ std::rotate(begin, it, end);
+ QString path = "/" + strings.join('/');
+ blacklist.blacklist(path);
+ QVERIFY(blacklist.isBlacklisted(path));
+ QVERIFY(blacklist.isBlacklisted(path + "/file"));
+ QVERIFY(!blacklist.isBlacklisted(path + "more"));
+ path.chop(1);
+ QVERIFY(!blacklist.isBlacklisted(path));
+ std::reverse(begin, end);
+ }
+
+ blacklist.clear();
+ for (const QString &string : strings)
+ QVERIFY(!blacklist.isBlacklisted(string));
+
+ blacklist.blacklist(":/qt-project.org");
+ QVERIFY(blacklist.isBlacklisted(":/qt-project.org/QmlRuntime/conf/configuration.qml"));
+ QVERIFY(!blacklist.isBlacklisted(":/qt-project.orgQmlRuntime/conf/configuration.qml"));
+
+ QQmlPreviewBlacklist blacklist2;
+
+ blacklist2.blacklist(":/qt-project.org");
+ blacklist2.blacklist(":/QtQuick/Controls/Styles");
+ blacklist2.blacklist(":/ExtrasImports/QtQuick/Controls/Styles");
+ blacklist2.blacklist(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath));
+ blacklist2.blacklist("/home/ulf/.local/share/QtProject/Qml Runtime/configuration.qml");
+ blacklist2.blacklist("/usr/share");
+ blacklist2.blacklist("/usr/share/QtProject/Qml Runtime/configuration.qml");
+ QVERIFY(blacklist2.isBlacklisted(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)));
+ blacklist2.blacklist("/usr/local/share/QtProject/Qml Runtime/configuration.qml");
+ blacklist2.blacklist("qml");
+ blacklist2.blacklist(""); // This should not remove all other paths.
+
+ QVERIFY(blacklist2.isBlacklisted(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath) +
+ "/QtQuick/Window.2.0"));
+ QVERIFY(blacklist2.isBlacklisted(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)));
+ QVERIFY(blacklist2.isBlacklisted("/usr/share/QtProject/Qml Runtime/configuration.qml"));
+ QVERIFY(blacklist2.isBlacklisted("/usr/share/stuff"));
+ QVERIFY(blacklist2.isBlacklisted(""));
+
+ QQmlPreviewBlacklist blacklist3;
+ blacklist3.blacklist("/usr/share");
+ blacklist3.blacklist("/usr");
+ blacklist3.blacklist("/usrdings");
+ QVERIFY(blacklist3.isBlacklisted("/usrdings"));
+ QVERIFY(blacklist3.isBlacklisted("/usr/src"));
+ QVERIFY(!blacklist3.isBlacklisted("/opt/share"));
+ QVERIFY(!blacklist3.isBlacklisted("/opt"));
+
+ blacklist3.whitelist("/usr/share");
+ QVERIFY(blacklist3.isBlacklisted("/usrdings"));
+ QVERIFY(!blacklist3.isBlacklisted("/usr"));
+ QVERIFY(!blacklist3.isBlacklisted("/usr/share"));
+ QVERIFY(!blacklist3.isBlacklisted("/usr/src"));
+ QVERIFY(!blacklist3.isBlacklisted("/opt/share"));
+ QVERIFY(!blacklist3.isBlacklisted("/opt"));
+}
+
+void tst_QQmlPreview::error()
+{
+ QCOMPARE(startQmlProcess("window.qml"), ConnectSuccess);
+ QVERIFY(m_client);
+ m_client->triggerLoad(testFileUrl("broken.qml"));
+ QTRY_COMPARE_WITH_TIMEOUT(m_serviceErrors.count(), 1, 10000);
+ QVERIFY(m_serviceErrors.first().contains("broken.qml:32 Expected token `}'"));
+}
+
+static float parseZoomFactor(const QString &output)
+{
+ const QString prefix("zoom ");
+ const int start = output.lastIndexOf(prefix) + prefix.length();
+ if (start < 0)
+ return -1;
+ const int end = output.indexOf('\n', start);
+ if (end < 0)
+ return -1;
+ bool ok = false;
+ const float zoomFactor = output.mid(start, end - start).toFloat(&ok);
+ if (!ok)
+ return -1;
+ return zoomFactor;
+}
+
+void tst_QQmlPreview::zoom()
+{
+ const QString file("zoom.qml");
+ QCOMPARE(startQmlProcess(file), ConnectSuccess);
+ QVERIFY(m_client);
+ m_client->triggerLoad(testFileUrl(file));
+ QTRY_VERIFY(m_files.contains(testFile(file)));
+ float baseZoomFactor = -1;
+ QTRY_VERIFY((baseZoomFactor = parseZoomFactor(m_process->output())) > 0);
+ m_client->triggerZoom(2.0f);
+ QTRY_VERIFY(qFuzzyCompare(parseZoomFactor(m_process->output()), baseZoomFactor * 2.0f));
+ m_client->triggerZoom(1.5f);
+ QTRY_VERIFY(qFuzzyCompare(parseZoomFactor(m_process->output()), baseZoomFactor * 1.5f));
+ m_client->triggerZoom(0.5f);
+ QTRY_VERIFY(qFuzzyCompare(parseZoomFactor(m_process->output()), baseZoomFactor * 0.5f));
+ m_client->triggerZoom(-1.0f);
+ QTRY_VERIFY(qFuzzyCompare(parseZoomFactor(m_process->output()), baseZoomFactor));
+ m_process->stop();
+ QVERIFY(m_serviceErrors.isEmpty());
+}
+
+QTEST_MAIN(tst_QQmlPreview)
+
+#include "tst_qqmlpreview.moc"
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
new file mode 100644
index 0000000000..bc8c2b90ae
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+//DO NOT CHANGE
+
+Item {
+ Timer {
+ running: true
+ triggeredOnStart: true
+ onTriggered: Qt.quit();
+ }
+}
+
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 3cb315b355..eb0b0c2fe2 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -34,6 +34,7 @@
#include <private/qqmldebugconnection_p.h>
#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
#include <QtCore/qlibraryinfo.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -195,7 +196,9 @@ private:
};
ConnectResult connect(bool block, const QString &testFile, bool recordFromStart = true,
- uint flushInterval = 0, bool restrictServices = true);
+ uint flushInterval = 0, bool restrictServices = true,
+ const QString &executable
+ = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene");
void checkProcessTerminated();
void checkTraceReceived();
void checkJsHeap();
@@ -221,6 +224,7 @@ private slots:
void translationBinding();
void memory();
void compile();
+ void multiEngine();
private:
bool m_recordFromStart = true;
@@ -237,7 +241,7 @@ private:
QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect(
bool block, const QString &file, bool recordFromStart, uint flushInterval,
- bool restrictServices)
+ bool restrictServices, const QString &executable)
{
m_recordFromStart = recordFromStart;
m_flushInterval = flushInterval;
@@ -245,7 +249,7 @@ QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect(
// ### Still using qmlscene due to QTBUG-33377
return QQmlDebugTest::connect(
- QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene",
+ executable,
restrictServices ? "CanvasFrameRate,EngineControl,DebugMessages" : QString(),
testFile(file), block);
}
@@ -261,11 +265,13 @@ void tst_QQmlProfilerService::checkProcessTerminated()
QVERIFY(m_client->client);
QTRY_COMPARE(m_client->client->state(), QQmlDebugClient::NotConnected);
QVERIFY(m_process);
+ QVERIFY(m_process->exitStatus() != QProcess::CrashExit);
QTRY_COMPARE(m_process->exitStatus(), QProcess::NormalExit);
}
void tst_QQmlProfilerService::checkTraceReceived()
{
+ QVERIFY(m_process->exitStatus() != QProcess::CrashExit);
QTRY_VERIFY2(m_isComplete, "No trace received in time.");
QVector<qint64> numbers;
@@ -282,6 +288,7 @@ void tst_QQmlProfilerService::checkTraceReceived()
void tst_QQmlProfilerService::checkJsHeap()
{
+ QVERIFY(m_client);
QVERIFY2(m_client->jsHeapMessages.count() > 0, "no JavaScript heap messages received");
bool seen_alloc = false;
@@ -340,6 +347,11 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
int expectedPosition, const QQmlProfilerEventType &expected,
quint32 checks, const QVector<qint64> &expectedNumbers)
{
+ if (!m_client) {
+ qWarning() << "No debug client available";
+ return false;
+ }
+
const QVector<QQmlProfilerEvent> *target = nullptr;
switch (type) {
case MessageListQML: target = &(m_client->qmlMessages); break;
@@ -349,6 +361,11 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
case MessageListPixmap: target = &(m_client->pixmapMessages); break;
}
+ if (!target) {
+ qWarning() << "Invalid MessageListType" << type;
+ return false;
+ }
+
if (target->length() <= expectedPosition) {
qWarning() << "Not enough events. expected position:" << expectedPosition
<< "length:" << target->length();
@@ -629,7 +646,7 @@ void tst_QQmlProfilerService::scenegraphData()
void tst_QQmlProfilerService::profileOnExit()
{
- connect(true, "exit.qml");
+ QCOMPARE(connect(true, "exit.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
@@ -711,7 +728,7 @@ void tst_QQmlProfilerService::flushInterval()
void tst_QQmlProfilerService::translationBinding()
{
- connect(true, "qstr.qml");
+ QCOMPARE(connect(true, "qstr.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
@@ -727,12 +744,13 @@ void tst_QQmlProfilerService::translationBinding()
void tst_QQmlProfilerService::memory()
{
- connect(true, "memory.qml");
+ QCOMPARE(connect(true, "memory.qml"), ConnectSuccess);
checkProcessTerminated();
checkTraceReceived();
checkJsHeap();
+ QVERIFY(m_client);
int smallItems = 0;
for (auto message : m_client->jsHeapMessages) {
const QQmlProfilerEventType &type = m_client->types[message.typeIndex()];
@@ -757,6 +775,8 @@ void tst_QQmlProfilerService::compile()
// Flush interval so that we actually get the events before we stop recording.
connect(true, "test.qml", true, 100);
+ QVERIFY(m_client);
+
// We need to check specifically for compile events as we can otherwise stop recording after the
// StartTrace has arrived, but before it compiles anything.
QTRY_VERIFY(hasCompileEvents(m_client->types));
@@ -790,6 +810,22 @@ void tst_QQmlProfilerService::compile()
QCOMPARE(rangeStage, RangeEnd);
}
+void tst_QQmlProfilerService::multiEngine()
+{
+ QCOMPARE(connect(true, "quit.qml", true, 0, false, debugJsServerPath("qqmlprofilerservice")),
+ ConnectSuccess);
+
+ QSignalSpy spy(m_client->client, SIGNAL(complete(qint64)));
+
+ checkTraceReceived();
+ checkJsHeap();
+
+ QTRY_COMPARE(m_process->state(), QProcess::NotRunning);
+ QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
+
+ QCOMPARE(spy.count(), 1);
+}
+
QTEST_MAIN(tst_QQmlProfilerService)
#include "tst_qqmlprofilerservice.moc"
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index c65c592f10..a176f674e6 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -86,8 +86,7 @@ public:
QV4::Scope scope(v4);
QV4::ScopedString name(scope, v4->newString(functionName));
- QV4::ScopedContext ctx(scope, v4->rootContext());
- QV4::ScopedValue function(scope, FunctionObject::createBuiltinFunction(ctx, name, injectedFunction));
+ QV4::ScopedValue function(scope, FunctionObject::createBuiltinFunction(v4, name, injectedFunction, 0));
v4->globalObject->put(name, function);
}
@@ -220,7 +219,21 @@ public:
{
for (int i = 0, ei = m_stackTrace.size(); i != ei; ++i) {
m_capturedScope.append(NamedRefs());
- ScopeJob job(&collector, i, 0);
+ FrameJob frameJob(&collector, i);
+ debugger->runInEngine(&frameJob);
+ QJsonObject frameObj = frameJob.returnValue();
+ QJsonArray scopes = frameObj.value(QLatin1String("scopes")).toArray();
+ int nscopes = scopes.size();
+ int s = 0;
+ for (s = 0; s < nscopes; ++s) {
+ QJsonObject o = scopes.at(s).toObject();
+ if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext
+ break;
+ }
+ if (s == nscopes)
+ return;
+
+ ScopeJob job(&collector, i, s);
debugger->runInEngine(&job);
NamedRefs &refs = m_capturedScope.last();
QJsonObject object = job.returnValue();
@@ -482,7 +495,7 @@ void tst_qv4debugger::conditionalBreakPoint()
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 2);
+ QCOMPARE(frame0.size(), 3);
QVERIFY(frame0.contains("i"));
QCOMPARE(frame0.value("i").toInt(), 11);
}
@@ -541,7 +554,7 @@ void tst_qv4debugger::readArguments()
QVERIFY(m_debuggerAgent->m_wasPaused);
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 4);
+ QCOMPARE(frame0.size(), 5);
QVERIFY(frame0.contains(QStringLiteral("a")));
QCOMPARE(frame0.type(QStringLiteral("a")), QStringLiteral("number"));
QCOMPARE(frame0.value(QStringLiteral("a")).toDouble(), 1.0);
@@ -565,7 +578,7 @@ void tst_qv4debugger::readComplicatedArguments()
QVERIFY(m_debuggerAgent->m_wasPaused);
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 1);
+ QCOMPARE(frame0.size(), 2);
QVERIFY(frame0.contains(QStringLiteral("a")));
QCOMPARE(frame0.type(QStringLiteral("a")), QStringLiteral("number"));
QCOMPARE(frame0.value(QStringLiteral("a")).toInt(), 12);
@@ -589,7 +602,7 @@ void tst_qv4debugger::readLocals()
QVERIFY(m_debuggerAgent->m_wasPaused);
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 4); // locals and parameters
+ QCOMPARE(frame0.size(), 5); // locals and parameters
QVERIFY(frame0.contains("c"));
QCOMPARE(frame0.type("c"), QStringLiteral("number"));
QCOMPARE(frame0.value("c").toDouble(), 3.0);
@@ -614,7 +627,7 @@ void tst_qv4debugger::readObject()
QVERIFY(m_debuggerAgent->m_wasPaused);
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 2);
+ QCOMPARE(frame0.size(), 3);
QVERIFY(frame0.contains("b"));
QCOMPARE(frame0.type("b"), QStringLiteral("object"));
QJsonObject b = frame0.rawValue("b");
@@ -679,7 +692,7 @@ void tst_qv4debugger::readContextInAllFrames()
for (int i = 0; i < 12; ++i) {
const TestAgent::NamedRefs &scope = m_debuggerAgent->m_capturedScope.at(i);
- QCOMPARE(scope.size(), 2);
+ QCOMPARE(scope.size(), 3);
QVERIFY(scope.contains("n"));
QCOMPARE(scope.type("n"), QStringLiteral("number"));
QCOMPARE(scope.value("n").toDouble(), i + 1.0);
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index b118b22c64..68446b53a4 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -98,6 +98,9 @@ QString QQmlDebugTest::connectionStateString(const QQmlDebugConnection *connecti
QQmlDebugTestClient::QQmlDebugTestClient(const QString &s, QQmlDebugConnection *c)
: QQmlDebugClient(s, c)
{
+ connect(this, &QQmlDebugClient::stateChanged, this, [this](QQmlDebugClient::State newState) {
+ QCOMPARE(newState, state());
+ });
}
QByteArray QQmlDebugTestClient::waitForResponse()
@@ -111,31 +114,12 @@ QByteArray QQmlDebugTestClient::waitForResponse()
return lastMsg;
}
-void QQmlDebugTestClient::stateChanged(State stat)
-{
- QCOMPARE(stat, state());
- emit stateHasChanged();
-}
-
void QQmlDebugTestClient::messageReceived(const QByteArray &ba)
{
lastMsg = ba;
emit serverMessage(ba);
}
-template<typename F>
-struct Finalizer {
- F m_lambda;
- Finalizer(F &&lambda) : m_lambda(std::forward<F>(lambda)) {}
- ~Finalizer() { m_lambda(); }
-};
-
-template<typename F>
-static Finalizer<F> defer(F &&lambda)
-{
- return Finalizer<F>(std::forward<F>(lambda));
-}
-
QQmlDebugTest::ConnectResult QQmlDebugTest::connect(
const QString &executable, const QString &services, const QString &extraArgs,
bool block)
@@ -162,31 +146,27 @@ QQmlDebugTest::ConnectResult QQmlDebugTest::connect(
if (m_clients.contains(nullptr))
return ClientsFailed;
- auto allEnabled = [this]() {
- for (QQmlDebugClient *client : m_clients) {
- if (client->state() != QQmlDebugClient::Enabled)
- return false;
- }
- return true;
- };
+ ClientStateHandler stateHandler(m_clients, createOtherClients(m_connection), services.isEmpty()
+ ? QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable);
- QList<QQmlDebugClient *> others = createOtherClients(m_connection);
- auto deleter = defer([&others]() { qDeleteAll(others); });
- Q_UNUSED(deleter);
const int port = m_process->debugPort();
m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
- for (int tries = 0; tries < 100 && !allEnabled(); ++tries)
- QTest::qWait(50);
- if (!allEnabled())
+
+ QEventLoop loop;
+ QTimer timer;
+ QObject::connect(&stateHandler, &ClientStateHandler::allOk, &loop, &QEventLoop::quit);
+ QObject::connect(m_connection, &QQmlDebugConnection::disconnected, &loop, &QEventLoop::quit);
+ QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
+
+ timer.start(5000);
+ loop.exec();
+
+ if (!stateHandler.allEnabled())
return EnableFailed;
- const QQmlDebugClient::State expectedState = services.isEmpty() ? QQmlDebugClient::Enabled
- : QQmlDebugClient::Unavailable;
- for (QQmlDebugClient *other : others) {
- if (other->state() != expectedState)
- return RestrictFailed;
- }
+ if (!stateHandler.othersAsExpected())
+ return RestrictFailed;
return ConnectSuccess;
}
@@ -211,7 +191,7 @@ void QQmlDebugTest::cleanup()
if (QTest::currentTestFailed()) {
const QString null = QStringLiteral("null");
- qDebug() << "Process State:" << (m_process ? m_process->state() : null);
+ qDebug() << "Process State:" << (m_process ? m_process->stateString() : null);
qDebug() << "Application Output:" << (m_process ? m_process->output() : null);
qDebug() << "Connection State:" << QQmlDebugTest::connectionStateString(m_connection);
for (QQmlDebugClient *client : m_clients) {
@@ -234,3 +214,50 @@ void QQmlDebugTest::cleanup()
m_process = nullptr;
}
}
+
+ClientStateHandler::ClientStateHandler(const QList<QQmlDebugClient *> &clients,
+ const QList<QQmlDebugClient *> &others,
+ QQmlDebugClient::State expectedOthers) :
+ m_clients(clients), m_others(others), m_expectedOthers(expectedOthers)
+{
+ for (QQmlDebugClient *client : m_clients) {
+ QObject::connect(client, &QQmlDebugClient::stateChanged,
+ this, &ClientStateHandler::checkStates);
+ }
+ for (QQmlDebugClient *client : m_others) {
+ QObject::connect(client, &QQmlDebugClient::stateChanged,
+ this, &ClientStateHandler::checkStates);
+ }
+}
+
+ClientStateHandler::~ClientStateHandler()
+{
+ qDeleteAll(m_others);
+}
+
+void ClientStateHandler::checkStates()
+{
+ for (QQmlDebugClient *client : m_clients) {
+ if (client->state() != QQmlDebugClient::Enabled)
+ return;
+ }
+
+ m_allEnabled = true;
+
+ for (QQmlDebugClient *other : m_others) {
+ if (other->state() != m_expectedOthers)
+ return;
+ }
+
+ m_othersAsExpected = true;
+ emit allOk();
+}
+
+QString debugJsServerPath(const QString &selfPath)
+{
+ static const char *debugserver = "qqmldebugjsserver";
+ QString appPath = QCoreApplication::applicationDirPath();
+ const int position = appPath.lastIndexOf(selfPath);
+ return (position == -1 ? appPath : appPath.replace(position, selfPath.length(), debugserver))
+ + "/" + debugserver;
+}
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 94ad83bfce..1c32590305 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -88,11 +88,9 @@ public:
QByteArray waitForResponse();
signals:
- void stateHasChanged();
void serverMessage(const QByteArray &);
protected:
- virtual void stateChanged(State state);
virtual void messageReceived(const QByteArray &ba);
private:
@@ -116,4 +114,33 @@ public:
}
};
+class ClientStateHandler : public QObject
+{
+ Q_OBJECT
+public:
+ ClientStateHandler(const QList<QQmlDebugClient *> &clients,
+ const QList<QQmlDebugClient *> &others,
+ QQmlDebugClient::State expectedOthers);
+
+ ~ClientStateHandler();
+
+ bool allEnabled() const { return m_allEnabled; }
+ bool othersAsExpected() const { return m_othersAsExpected; }
+
+signals:
+ void allOk();
+
+private:
+ void checkStates();
+
+ const QList<QQmlDebugClient *> m_clients;
+ const QList<QQmlDebugClient *> m_others;
+ const QQmlDebugClient::State m_expectedOthers;
+
+ bool m_allEnabled = false;
+ bool m_othersAsExpected = false;
+};
+
+QString debugJsServerPath(const QString &selfPath);
+
#endif // DEBUGUTIL_P_H
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
index f2b85833c9..6f74edf863 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
@@ -50,6 +50,7 @@ QQmlDebugProcess::QQmlDebugProcess(const QString &executable, QObject *parent)
this, [this]() {
m_timer.stop();
m_eventLoop.quit();
+ emit finished();
});
connect(&m_timer, &QTimer::timeout,
this, &QQmlDebugProcess::timeout);
@@ -60,7 +61,7 @@ QQmlDebugProcess::~QQmlDebugProcess()
stop();
}
-QString QQmlDebugProcess::state()
+QString QQmlDebugProcess::stateString() const
{
QString stateStr;
switch (m_process.state()) {
@@ -155,6 +156,11 @@ bool QQmlDebugProcess::waitForFinished()
return m_process.waitForFinished();
}
+QProcess::ProcessState QQmlDebugProcess::state() const
+{
+ return m_process.state();
+}
+
QProcess::ExitStatus QQmlDebugProcess::exitStatus() const
{
return m_process.exitStatus();
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h b/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
index fd2c89bb41..945cc58c85 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
@@ -52,7 +52,7 @@ public:
QQmlDebugProcess(const QString &executable, QObject *parent = 0);
~QQmlDebugProcess();
- QString state();
+ QString stateString() const;
void addEnvironment(const QString &environment);
@@ -61,6 +61,7 @@ public:
int debugPort() const;
bool waitForFinished();
+ QProcess::ProcessState state() const;
QProcess::ExitStatus exitStatus() const;
QString output() const;
@@ -69,6 +70,7 @@ public:
signals:
void readyReadStandardOutput();
+ void finished();
private slots:
void timeout();
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
index 4dce07d824..896ed608fd 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
@@ -48,5 +48,4 @@ void QQmlDebugTestService::stateAboutToBeChanged(QQmlDebugService::State)
void QQmlDebugTestService::stateChanged(State)
{
Q_ASSERT(QThread::currentThread() != thread());
- emit stateHasChanged();
}
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
index 37b4a9f98c..9c39c0893d 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
@@ -38,9 +38,6 @@ class QQmlDebugTestService : public QQmlDebugService
public:
QQmlDebugTestService(const QString &s, float version = 1, QObject *parent = 0);
-signals:
- void stateHasChanged();
-
protected:
virtual void messageReceived(const QByteArray &ba);
virtual void stateAboutToBeChanged(State state);
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 589f25d174..dbf2e22c63 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -1,177 +1,2684 @@
-# wrong tests
-# uses octal number
-15.2.3.6-2-17-1 failing
+# ----- These are tests we will not fix
-# 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
+# The tests below rely on the ES6 spec quirk that allows 'let' as an identifier. We've
+# always treated 'let' as a reserved keyword (without ever getting a bug report about it),
+# so we'll keep it that way. It also removes a huge headache in the parser.
+language/statements/for-in/let-block-with-newline.js sloppyFails
+language/statements/for-of/let-block-with-newline.js sloppyFails
+language/statements/for/let-block-with-newline.js sloppyFails
+language/statements/if/let-block-with-newline.js sloppyFails
+language/statements/labeled/let-block-with-newline.js sloppyFails
+language/statements/while/let-block-with-newline.js sloppyFails
+language/statements/with/let-block-with-newline.js sloppyFails
+language/statements/for-in/let-identifier-with-newline.js sloppyFails
+language/statements/for-of/let-identifier-with-newline.js sloppyFails
+language/statements/for/let-identifier-with-newline.js sloppyFails
+language/statements/if/let-identifier-with-newline.js sloppyFails
+language/statements/labeled/let-identifier-with-newline.js sloppyFails
+language/statements/while/let-identifier-with-newline.js sloppyFails
+language/statements/with/let-identifier-with-newline.js sloppyFails
-11.2.3-3_3 failing
-S13_A15_T4 failing
-S15.4.4.3_A1_T1 failing
-S15.4.4.3_A3_T1 failing
-S15.5.4.11_A5_T1 failing
-S15.2.4.4_A14 failing
-# Function declarations in conditionals. We allow them, because the real
-# world requires them.
-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
-
-# es6: function length attributes are configurable, wasn't in es5
-S15.1.2.2_A9.2 failing
-S15.1.3.1_A5.2 failing
-S15.1.3.2_A5.2 failing
-S15.1.3.3_A5.2 failing
-S15.1.2.3_A7.2 failing
-S15.1.2.4_A2.2 failing
-S15.1.2.5_A2.2 failing
-S15.1.3.4_A5.2 failing
-15.2.3.3-4-186 failing
-S15.2.4.2_A9 failing
-S15.2.4.3_A9 failing
-S15.2.4.4_A9 failing
-S15.2.4.5_A9 failing
-S15.2.4.6_A9 failing
-S15.2.4.7_A9 failing
-15.3.3.2-1 failing
-15.4.4.2_A4.2
-S15.3.4.2_A9 failing
-S15.3.4.3_A9 failing
-S15.3.4.4_A9 failing
-15.3.4.5-15-2 failing
-S15.4.4.2_A4.2 failing
-S15.4.4.3_A4.2 failing
-S15.4.4.4_A4.2 failing
-S15.4.4.5_A6.2 failing
-S15.4.4.6_A5.2 failing
-S15.4.4.7_A6.2 failing
-S15.4.4.8_A5.2 failing
-S15.4.4.9_A5.2 failing
-S15.4.4.10_A5.2 failing
-S15.4.4.11_A7.2 failing
-S15.4.4.12_A5.2 failing
-S15.4.4.13_A5.2 failing
-S15.5.4.10_A9 failing
-S15.5.4.11_A9 failing
-S15.5.4.12_A9 failing
-S15.5.4.13_A9 failing
-S15.5.4.14_A9 failing
-S15.5.4.15_A9 failing
-S15.5.4.16_A9 failing
-S15.5.4.17_A9 failing
-S15.5.4.18_A9 failing
-S15.5.4.19_A9 failing
-S15.5.4.4_A9 failing
-S15.5.4.5_A9 failing
-S15.5.4.6_A9 failing
-S15.5.4.7_A9 failing
-S15.5.4.8_A9 failing
-S15.5.4.9_A9 failing
-S15.9.4.2_A3_T2 failing
-S15.9.4.3_A3_T2 failing
-S15.9.5.2_A3_T2 failing
-S15.9.5.3_A3_T2 failing
-S15.9.5.4_A3_T2 failing
-S15.9.5.5_A3_T2 failing
-S15.9.5.1_A3_T2 failing
-S15.9.5.10_A3_T2 failing
-S15.9.5.11_A3_T2 failing
-S15.9.5.12_A3_T2 failing
-S15.9.5.13_A3_T2 failing
-S15.9.5.14_A3_T2 failing
-S15.9.5.15_A3_T2 failing
-S15.9.5.16_A3_T2 failing
-S15.9.5.17_A3_T2 failing
-S15.9.5.18_A3_T2 failing
-S15.9.5.19_A3_T2 failing
-S15.9.5.20_A3_T2 failing
-S15.9.5.21_A3_T2 failing
-S15.9.5.22_A3_T2 failing
-S15.9.5.23_A3_T2 failing
-S15.9.5.24_A3_T2 failing
-S15.9.5.25_A3_T2 failing
-S15.9.5.26_A3_T2 failing
-S15.9.5.27_A3_T2 failing
-S15.9.5.28_A3_T2 failing
-S15.9.5.29_A3_T2 failing
-S15.9.5.30_A3_T2 failing
-S15.9.5.31_A3_T2 failing
-S15.9.5.32_A3_T2 failing
-S15.9.5.33_A3_T2 failing
-S15.9.5.34_A3_T2 failing
-S15.9.5.35_A3_T2 failing
-S15.9.5.36_A3_T2 failing
-S15.9.5.37_A3_T2 failing
-S15.9.5.38_A3_T2 failing
-S15.9.5.39_A3_T2 failing
-S15.9.5.40_A3_T2 failing
-S15.9.5.41_A3_T2 failing
-S15.9.5.42_A3_T2 failing
-S15.9.5.6_A3_T2 failing
-S15.9.5.7_A3_T2 failing
-S15.9.5.8_A3_T2 failing
-S15.9.5.9_A3_T2 failing
-S15.10.6.2_A9 failing
-S15.10.6.3_A9 failing
-S15.10.6.4_A9 failing
-
-# es6: Object.freeze(v) on a non-object returns v, no longer TypeError
-15.2.3.9-1 failing
-15.2.3.9-1-1 failing
-15.2.3.9-1-2 failing
-15.2.3.9-1-3 failing
-15.2.3.9-1-4 failing
-# es6: Object.preventExtensions(O) on a non-object, no longer TypeError
-15.2.3.10-1 failing
-15.2.3.10-1-3 failing
-15.2.3.10-1-4 failing
-# es6: Object.isSealed(O) on a non-object, no longer TypeError
-15.2.3.11-1
-# es6: Object.isFrozen(O) on a non-object, no longer TypeError
-15.2.3.12-1
-15.2.3.12-1-3
-15.2.3.12-1-4
-# es6: Object.isExtensible(O) on a non-object, no longer TypeError
-15.2.3.13-1
-15.2.3.13-1-3
-15.2.3.13-1-4
-# es6: Object.keys(O) on a non-object, no longer TypeError
-15.2.3.14-1-1
-15.2.3.14-1-2
-15.2.3.14-1-3
-15.2.3.14-1
-15.2.3.14-2
-15.2.3.14-3
-# es6: Object.getOwnPropertyDescriptor(O) on a non-object, no longer TypeError
-15.2.3.3-1
-15.2.3.3-1-3
-15.2.3.3-1-4
-# es6: Object.getPrototypeOf(O) on a non-object, no longer TypeError
-15.2.3.2-1
-15.2.3.2-1-3
-15.2.3.2-1-4
-# es6: Object.getOwnPropertyNames(O) on a non-object, no longer TypeError
-15.2.3.4-1
-15.2.3.4-1-4
-15.2.3.4-1-5
-# es6: Object.seal(O) on a non-object, no longer TypeError
-15.2.3.8-1
-15.2.3.8-1-1
-15.2.3.8-1-2
-15.2.3.8-1-3
-15.2.3.8-1-4
-
-# es6: Date.prototype is no longer a DateObject
-15.9.5.40_1 failing
+# ----- test failures that should be fixed
+built-ins/Array/from/iter-cstm-ctor-err.js fails
+built-ins/Array/from/proto-from-ctor-realm.js fails
+built-ins/Array/isArray/proxy-revoked.js fails
+built-ins/Array/isArray/proxy.js fails
+built-ins/Array/length/define-own-prop-length-overflow-realm.js fails
+built-ins/Array/of/proto-from-ctor-realm.js fails
+built-ins/Array/proto-from-ctor-realm.js fails
+built-ins/Array/prototype/Symbol.unscopables/prop-desc.js fails
+built-ins/Array/prototype/Symbol.unscopables/value.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-to-string-throws.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-value-of-throws.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like-negative-length.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like-primitive-non-number-length.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like-string-length.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like-to-length-throws.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_array-like.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_holey-sloppy-arguments.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_length-throws.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-throws.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-with-dupes.js sloppyFails
+built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-boolean-wrapper.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-function.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-getter-throws.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-number-wrapper.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-reg-exp.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-sparse-object.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js fails
+built-ins/Array/prototype/concat/Array.prototype.concat_strict-arguments.js fails
+built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js fails
+built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js fails
+built-ins/Array/prototype/concat/create-ctor-non-object.js fails
+built-ins/Array/prototype/concat/create-proto-from-ctor-realm-array.js fails
+built-ins/Array/prototype/concat/create-proto-from-ctor-realm-non-array.js fails
+built-ins/Array/prototype/concat/create-proxy.js fails
+built-ins/Array/prototype/concat/create-revoked-proxy.js fails
+built-ins/Array/prototype/concat/create-species-non-ctor.js fails
+built-ins/Array/prototype/concat/create-species.js fails
+built-ins/Array/prototype/concat/is-concat-spreadable-is-array-proxy-revoked.js fails
+built-ins/Array/prototype/concat/is-concat-spreadable-proxy-revoked.js fails
+built-ins/Array/prototype/concat/is-concat-spreadable-proxy.js fails
+built-ins/Array/prototype/concat/is-concat-spreadable-val-falsey.js fails
+built-ins/Array/prototype/concat/is-concat-spreadable-val-truthy.js fails
+built-ins/Array/prototype/every/15.4.4.16-3-29.js fails
+built-ins/Array/prototype/filter/create-ctor-non-object.js fails
+built-ins/Array/prototype/filter/create-proto-from-ctor-realm-array.js fails
+built-ins/Array/prototype/filter/create-proto-from-ctor-realm-non-array.js fails
+built-ins/Array/prototype/filter/create-proxy.js fails
+built-ins/Array/prototype/filter/create-species-non-ctor.js fails
+built-ins/Array/prototype/filter/create-species.js fails
+built-ins/Array/prototype/includes/length-boundaries.js fails
+built-ins/Array/prototype/indexOf/15.4.4.14-3-28.js fails
+built-ins/Array/prototype/indexOf/15.4.4.14-3-29.js fails
+built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js fails
+built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-28.js fails
+built-ins/Array/prototype/map/create-ctor-non-object.js fails
+built-ins/Array/prototype/map/create-proto-from-ctor-realm-array.js fails
+built-ins/Array/prototype/map/create-proto-from-ctor-realm-non-array.js fails
+built-ins/Array/prototype/map/create-proxy.js fails
+built-ins/Array/prototype/map/create-species-non-ctor.js fails
+built-ins/Array/prototype/map/create-species.js fails
+built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js fails
+built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js fails
+built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js fails
+built-ins/Array/prototype/pop/clamps-to-integer-limit.js fails
+built-ins/Array/prototype/pop/length-near-integer-limit.js fails
+built-ins/Array/prototype/push/S15.4.4.7_A2_T2.js fails
+built-ins/Array/prototype/push/S15.4.4.7_A3.js fails
+built-ins/Array/prototype/push/throws-if-integer-limit-exceeded.js fails
+built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-object.js fails
+built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy.js fails
+built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js fails
+built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js fails
+built-ins/Array/prototype/slice/create-ctor-non-object.js fails
+built-ins/Array/prototype/slice/create-non-array-invalid-len.js fails
+built-ins/Array/prototype/slice/create-proto-from-ctor-realm-array.js fails
+built-ins/Array/prototype/slice/create-proto-from-ctor-realm-non-array.js fails
+built-ins/Array/prototype/slice/create-proxied-array-invalid-len.js fails
+built-ins/Array/prototype/slice/create-proxy.js fails
+built-ins/Array/prototype/slice/create-species-neg-zero.js fails
+built-ins/Array/prototype/slice/create-species-non-ctor.js fails
+built-ins/Array/prototype/slice/create-species.js fails
+built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js fails
+built-ins/Array/prototype/slice/length-exceeding-integer-limit.js fails
+built-ins/Array/prototype/some/15.4.4.17-3-28.js fails
+built-ins/Array/prototype/some/15.4.4.17-3-29.js fails
+built-ins/Array/prototype/sort/comparefn-nonfunction-call-throws.js fails
+built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js fails
+built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js fails
+built-ins/Array/prototype/splice/create-ctor-non-object.js fails
+built-ins/Array/prototype/splice/create-proto-from-ctor-realm-array.js fails
+built-ins/Array/prototype/splice/create-proto-from-ctor-realm-non-array.js fails
+built-ins/Array/prototype/splice/create-proxy.js fails
+built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js fails
+built-ins/Array/prototype/splice/create-species-neg-zero.js fails
+built-ins/Array/prototype/splice/create-species-non-ctor.js fails
+built-ins/Array/prototype/splice/create-species.js fails
+built-ins/Array/prototype/splice/length-and-deleteCount-exceeding-integer-limit.js fails
+built-ins/Array/prototype/splice/length-exceeding-integer-limit-shrink-array.js fails
+built-ins/Array/prototype/splice/length-near-integer-limit-grow-array.js fails
+built-ins/Array/prototype/toLocaleString/S15.4.4.3_A1_T1.js fails
+built-ins/Array/prototype/toLocaleString/S15.4.4.3_A3_T1.js fails
+built-ins/Array/prototype/toLocaleString/primitive_this_value.js strictFails
+built-ins/Array/prototype/toLocaleString/primitive_this_value_getter.js strictFails
+built-ins/Array/prototype/unshift/clamps-to-integer-limit.js fails
+built-ins/Array/prototype/unshift/length-near-integer-limit.js fails
+built-ins/Array/prototype/unshift/throws-if-integer-limit-exceeded.js fails
+built-ins/ArrayBuffer/data-allocation-after-object-creation.js fails
+built-ins/ArrayBuffer/proto-from-ctor-realm.js fails
+built-ins/ArrayBuffer/prototype-from-newtarget.js fails
+built-ins/ArrayBuffer/prototype/byteLength/detached-buffer.js fails
+built-ins/ArrayBuffer/prototype/slice/end-default-if-absent.js fails
+built-ins/ArrayBuffer/prototype/slice/end-default-if-undefined.js fails
+built-ins/ArrayBuffer/prototype/slice/end-exceeds-length.js fails
+built-ins/ArrayBuffer/prototype/slice/negative-end.js fails
+built-ins/ArrayBuffer/prototype/slice/negative-start.js fails
+built-ins/ArrayBuffer/prototype/slice/nonconstructor.js fails
+built-ins/ArrayBuffer/prototype/slice/species-constructor-is-undefined.js fails
+built-ins/ArrayBuffer/prototype/slice/species-is-null.js fails
+built-ins/ArrayBuffer/prototype/slice/species-is-undefined.js fails
+built-ins/ArrayBuffer/prototype/slice/species-returns-larger-arraybuffer.js fails
+built-ins/ArrayBuffer/prototype/slice/species.js fails
+built-ins/ArrayBuffer/prototype/slice/start-default-if-absent.js fails
+built-ins/ArrayBuffer/prototype/slice/start-default-if-undefined.js fails
+built-ins/ArrayBuffer/prototype/slice/start-exceeds-end.js fails
+built-ins/ArrayBuffer/prototype/slice/start-exceeds-length.js fails
+built-ins/ArrayBuffer/prototype/slice/tointeger-conversion-end.js fails
+built-ins/ArrayBuffer/prototype/slice/tointeger-conversion-start.js fails
+built-ins/ArrayBuffer/undefined-newtarget-throws.js fails
+built-ins/ArrayIteratorPrototype/next/detach-typedarray-in-progress.js fails
+built-ins/AsyncFunction/AsyncFunction-construct.js fails
+built-ins/AsyncFunction/AsyncFunction-is-extensible.js fails
+built-ins/AsyncFunction/AsyncFunction-is-subclass.js fails
+built-ins/AsyncFunction/AsyncFunction-length.js fails
+built-ins/AsyncFunction/AsyncFunction-name.js fails
+built-ins/AsyncFunction/AsyncFunction-prototype.js fails
+built-ins/AsyncFunction/AsyncFunction.js fails
+built-ins/AsyncFunction/AsyncFunctionPrototype-is-extensible.js fails
+built-ins/AsyncFunction/AsyncFunctionPrototype-prototype.js fails
+built-ins/AsyncFunction/AsyncFunctionPrototype-to-string.js fails
+built-ins/AsyncFunction/instance-construct-throws.js fails
+built-ins/AsyncFunction/instance-has-name.js fails
+built-ins/AsyncFunction/instance-length.js fails
+built-ins/AsyncFunction/instance-prototype-property.js fails
+built-ins/AsyncGeneratorPrototype/next/name.js fails
+built-ins/AsyncGeneratorPrototype/return/name.js fails
+built-ins/AsyncGeneratorPrototype/throw/name.js fails
+built-ins/Atomics/Symbol.toStringTag.js fails
+built-ins/Atomics/add/descriptor.js fails
+built-ins/Atomics/add/length.js fails
+built-ins/Atomics/add/name.js fails
+built-ins/Atomics/add/nonshared-int-views.js fails
+built-ins/Atomics/add/shared-nonint-views.js fails
+built-ins/Atomics/and/descriptor.js fails
+built-ins/Atomics/and/length.js fails
+built-ins/Atomics/and/name.js fails
+built-ins/Atomics/and/nonshared-int-views.js fails
+built-ins/Atomics/and/shared-nonint-views.js fails
+built-ins/Atomics/compareExchange/descriptor.js fails
+built-ins/Atomics/compareExchange/length.js fails
+built-ins/Atomics/compareExchange/name.js fails
+built-ins/Atomics/compareExchange/nonshared-int-views.js fails
+built-ins/Atomics/compareExchange/shared-nonint-views.js fails
+built-ins/Atomics/exchange/descriptor.js fails
+built-ins/Atomics/exchange/length.js fails
+built-ins/Atomics/exchange/name.js fails
+built-ins/Atomics/exchange/nonshared-int-views.js fails
+built-ins/Atomics/exchange/shared-nonint-views.js fails
+built-ins/Atomics/isLockFree/corner-cases.js fails
+built-ins/Atomics/isLockFree/descriptor.js fails
+built-ins/Atomics/isLockFree/length.js fails
+built-ins/Atomics/isLockFree/name.js fails
+built-ins/Atomics/isLockFree/value.js fails
+built-ins/Atomics/load/descriptor.js fails
+built-ins/Atomics/load/length.js fails
+built-ins/Atomics/load/name.js fails
+built-ins/Atomics/load/nonshared-int-views.js fails
+built-ins/Atomics/load/shared-nonint-views.js fails
+built-ins/Atomics/or/descriptor.js fails
+built-ins/Atomics/or/length.js fails
+built-ins/Atomics/or/name.js fails
+built-ins/Atomics/or/nonshared-int-views.js fails
+built-ins/Atomics/or/shared-nonint-views.js fails
+built-ins/Atomics/prop-desc.js fails
+built-ins/Atomics/proto.js fails
+built-ins/Atomics/store/descriptor.js fails
+built-ins/Atomics/store/length.js fails
+built-ins/Atomics/store/name.js fails
+built-ins/Atomics/store/nonshared-int-views.js fails
+built-ins/Atomics/store/shared-nonint-views.js fails
+built-ins/Atomics/sub/descriptor.js fails
+built-ins/Atomics/sub/length.js fails
+built-ins/Atomics/sub/name.js fails
+built-ins/Atomics/sub/nonshared-int-views.js fails
+built-ins/Atomics/sub/shared-nonint-views.js fails
+built-ins/Atomics/wait/descriptor.js fails
+built-ins/Atomics/wait/did-timeout.js fails
+built-ins/Atomics/wait/good-views.js fails
+built-ins/Atomics/wait/length.js fails
+built-ins/Atomics/wait/name.js fails
+built-ins/Atomics/wait/nan-timeout.js fails
+built-ins/Atomics/wait/negative-timeout.js fails
+built-ins/Atomics/wait/no-spurious-wakeup.js fails
+built-ins/Atomics/wait/nonshared-int-views.js fails
+built-ins/Atomics/wait/shared-nonint-views.js fails
+built-ins/Atomics/wait/was-woken.js fails
+built-ins/Atomics/wake/counts.js fails
+built-ins/Atomics/wake/descriptor.js fails
+built-ins/Atomics/wake/length.js fails
+built-ins/Atomics/wake/name.js fails
+built-ins/Atomics/wake/nonshared-int-views.js fails
+built-ins/Atomics/wake/shared-nonint-views.js fails
+built-ins/Atomics/wake/wake-all-on-loc.js fails
+built-ins/Atomics/wake/wake-all.js fails
+built-ins/Atomics/wake/wake-in-order.js fails
+built-ins/Atomics/wake/wake-nan.js fails
+built-ins/Atomics/wake/wake-negative.js fails
+built-ins/Atomics/wake/wake-one.js fails
+built-ins/Atomics/wake/wake-two.js fails
+built-ins/Atomics/wake/wake-zero.js fails
+built-ins/Atomics/xor/descriptor.js fails
+built-ins/Atomics/xor/length.js fails
+built-ins/Atomics/xor/name.js fails
+built-ins/Atomics/xor/nonshared-int-views.js fails
+built-ins/Atomics/xor/shared-nonint-views.js fails
+built-ins/Boolean/proto-from-ctor-realm.js fails
+built-ins/DataView/custom-proto-access-throws.js fails
+built-ins/DataView/custom-proto-if-object-is-used.js fails
+built-ins/DataView/detached-buffer.js fails
+built-ins/DataView/length.js fails
+built-ins/DataView/newtarget-undefined-throws.js fails
+built-ins/DataView/proto-from-ctor-realm.js fails
+built-ins/DataView/prototype/buffer/detached-buffer.js fails
+built-ins/DataView/prototype/byteLength/detached-buffer.js fails
+built-ins/DataView/prototype/byteOffset/detached-buffer.js fails
+built-ins/DataView/prototype/getFloat32/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getFloat32/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getFloat32/detached-buffer.js fails
+built-ins/DataView/prototype/getFloat32/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getFloat32/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getFloat32/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getFloat64/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getFloat64/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getFloat64/detached-buffer.js fails
+built-ins/DataView/prototype/getFloat64/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getFloat64/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getFloat64/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getInt16/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getInt16/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getInt16/detached-buffer.js fails
+built-ins/DataView/prototype/getInt16/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getInt16/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getInt16/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getInt32/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getInt32/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getInt32/detached-buffer.js fails
+built-ins/DataView/prototype/getInt32/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getInt32/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getInt32/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getInt8/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getInt8/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getInt8/detached-buffer.js fails
+built-ins/DataView/prototype/getInt8/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getInt8/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getInt8/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getUint16/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getUint16/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getUint16/detached-buffer.js fails
+built-ins/DataView/prototype/getUint16/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getUint16/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getUint16/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getUint32/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getUint32/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getUint32/detached-buffer.js fails
+built-ins/DataView/prototype/getUint32/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getUint32/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getUint32/toindex-byteoffset.js fails
+built-ins/DataView/prototype/getUint8/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/getUint8/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/getUint8/detached-buffer.js fails
+built-ins/DataView/prototype/getUint8/index-is-out-of-range.js fails
+built-ins/DataView/prototype/getUint8/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/getUint8/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setFloat32/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setFloat32/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setFloat32/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setFloat32/detached-buffer.js fails
+built-ins/DataView/prototype/setFloat32/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setFloat32/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setFloat32/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setFloat32/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setFloat32/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setFloat64/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setFloat64/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setFloat64/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setFloat64/detached-buffer.js fails
+built-ins/DataView/prototype/setFloat64/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setFloat64/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setFloat64/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setFloat64/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setFloat64/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setInt16/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setInt16/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setInt16/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setInt16/detached-buffer.js fails
+built-ins/DataView/prototype/setInt16/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setInt16/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setInt16/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setInt16/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setInt16/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setInt32/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setInt32/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setInt32/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setInt32/detached-buffer.js fails
+built-ins/DataView/prototype/setInt32/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setInt32/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setInt32/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setInt32/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setInt32/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setInt8/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setInt8/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setInt8/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setInt8/detached-buffer.js fails
+built-ins/DataView/prototype/setInt8/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setInt8/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setInt8/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setInt8/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setInt8/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setUint16/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setUint16/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setUint16/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setUint16/detached-buffer.js fails
+built-ins/DataView/prototype/setUint16/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setUint16/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setUint16/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setUint16/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setUint16/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setUint32/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setUint32/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setUint32/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setUint32/detached-buffer.js fails
+built-ins/DataView/prototype/setUint32/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setUint32/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setUint32/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setUint32/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setUint32/toindex-byteoffset.js fails
+built-ins/DataView/prototype/setUint8/detached-buffer-after-number-value.js fails
+built-ins/DataView/prototype/setUint8/detached-buffer-after-toindex-byteoffset.js fails
+built-ins/DataView/prototype/setUint8/detached-buffer-before-outofrange-byteoffset.js fails
+built-ins/DataView/prototype/setUint8/detached-buffer.js fails
+built-ins/DataView/prototype/setUint8/index-check-before-value-conversion.js fails
+built-ins/DataView/prototype/setUint8/index-is-out-of-range.js fails
+built-ins/DataView/prototype/setUint8/negative-byteoffset-throws.js fails
+built-ins/DataView/prototype/setUint8/range-check-after-value-conversion.js fails
+built-ins/DataView/prototype/setUint8/toindex-byteoffset.js fails
+built-ins/DataView/toindex-bytelength.js fails
+built-ins/DataView/toindex-byteoffset.js fails
+built-ins/Date/UTC/infinity-make-day.js fails
+built-ins/Date/UTC/nans.js fails
+built-ins/Date/UTC/no-arg.js fails
+built-ins/Date/UTC/non-integer-values.js fails
+built-ins/Date/UTC/return-value.js fails
+built-ins/Date/UTC/year-offset.js fails
+built-ins/Date/proto-from-ctor-realm-one.js fails
+built-ins/Date/proto-from-ctor-realm-two.js fails
+built-ins/Date/proto-from-ctor-realm-zero.js fails
+built-ins/Date/prototype/toDateString/format.js fails
+built-ins/Date/prototype/toDateString/invalid-date.js fails
+built-ins/Date/prototype/toString/format.js fails
+built-ins/Date/prototype/toTimeString/format.js fails
+built-ins/Date/prototype/toTimeString/invalid-date.js fails
+built-ins/Date/prototype/toUTCString/day-names.js fails
+built-ins/Date/prototype/toUTCString/format.js fails
+built-ins/Date/prototype/toUTCString/month-names.js fails
+built-ins/Date/subclassing.js fails
+built-ins/Error/proto-from-ctor-realm.js fails
+built-ins/Error/prototype/S15.11.4_A2.js fails
+built-ins/Function/call-bind-this-realm-undef.js fails
+built-ins/Function/call-bind-this-realm-value.js fails
+built-ins/Function/internals/Call/class-ctor-realm.js fails
+built-ins/Function/internals/Construct/base-ctor-revoked-proxy-realm.js fails
+built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js fails
+built-ins/Function/internals/Construct/derived-return-val-realm.js fails
+built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js fails
+built-ins/Function/internals/Construct/derived-this-uninitialized.js fails
+built-ins/Function/proto-from-ctor-realm.js fails
+built-ins/Function/prototype/Symbol.hasInstance/this-val-not-callable.js fails
+built-ins/Function/prototype/Symbol.hasInstance/this-val-poisoned-prototype.js fails
+built-ins/Function/prototype/Symbol.hasInstance/value-non-obj.js fails
+built-ins/Function/prototype/bind/BoundFunction_restricted-properties.js fails
+built-ins/Function/prototype/bind/get-fn-realm.js fails
+built-ins/Function/prototype/bind/instance-name-chained.js fails
+built-ins/Function/prototype/bind/instance-name-non-string.js fails
+built-ins/Function/prototype/bind/instance-name.js fails
+built-ins/Function/prototype/bind/proto-from-ctor-realm.js fails
+built-ins/Function/prototype/toString/AsyncFunction.js fails
+built-ins/Function/prototype/toString/Function.js fails
+built-ins/Function/prototype/toString/GeneratorFunction.js fails
+built-ins/Function/prototype/toString/anonymous-intrinsics.js fails
+built-ins/Function/prototype/toString/arrow-function.js fails
+built-ins/Function/prototype/toString/async-arrow-function.js fails
+built-ins/Function/prototype/toString/async-function-declaration.js fails
+built-ins/Function/prototype/toString/async-function-expression.js fails
+built-ins/Function/prototype/toString/async-method-class-expression-static.js fails
+built-ins/Function/prototype/toString/async-method-class-expression.js fails
+built-ins/Function/prototype/toString/async-method-class-statement-static.js fails
+built-ins/Function/prototype/toString/async-method-class-statement.js fails
+built-ins/Function/prototype/toString/async-method-object.js fails
+built-ins/Function/prototype/toString/bound-function.js fails
+built-ins/Function/prototype/toString/class-declaration-complex-heritage.js fails
+built-ins/Function/prototype/toString/class-declaration-explicit-ctor.js fails
+built-ins/Function/prototype/toString/class-declaration-implicit-ctor.js fails
+built-ins/Function/prototype/toString/class-expression-explicit-ctor.js fails
+built-ins/Function/prototype/toString/class-expression-implicit-ctor.js fails
+built-ins/Function/prototype/toString/function-declaration-non-simple-parameter-list.js fails
+built-ins/Function/prototype/toString/function-declaration.js fails
+built-ins/Function/prototype/toString/function-expression.js fails
+built-ins/Function/prototype/toString/generator-function-declaration.js fails
+built-ins/Function/prototype/toString/generator-function-expression.js fails
+built-ins/Function/prototype/toString/generator-method.js fails
+built-ins/Function/prototype/toString/getter-class-expression-static.js fails
+built-ins/Function/prototype/toString/getter-class-expression.js fails
+built-ins/Function/prototype/toString/getter-class-statement-static.js fails
+built-ins/Function/prototype/toString/getter-class-statement.js fails
+built-ins/Function/prototype/toString/getter-object.js fails
+built-ins/Function/prototype/toString/intrinsics.js fails
+built-ins/Function/prototype/toString/line-terminator-normalisation-CR-LF.js fails
+built-ins/Function/prototype/toString/line-terminator-normalisation-CR.js fails
+built-ins/Function/prototype/toString/line-terminator-normalisation-LF.js fails
+built-ins/Function/prototype/toString/method-class-expression-static.js fails
+built-ins/Function/prototype/toString/method-class-expression.js fails
+built-ins/Function/prototype/toString/method-class-statement-static.js fails
+built-ins/Function/prototype/toString/method-class-statement.js fails
+built-ins/Function/prototype/toString/method-computed-property-name.js fails
+built-ins/Function/prototype/toString/method-object.js fails
+built-ins/Function/prototype/toString/proxy.js fails
+built-ins/Function/prototype/toString/setter-class-expression-static.js fails
+built-ins/Function/prototype/toString/setter-class-expression.js fails
+built-ins/Function/prototype/toString/setter-class-statement-static.js fails
+built-ins/Function/prototype/toString/setter-class-statement.js fails
+built-ins/Function/prototype/toString/setter-object.js fails
+built-ins/Function/prototype/toString/symbol-named-builtins.js fails
+built-ins/Function/prototype/toString/unicode.js fails
+built-ins/GeneratorFunction/proto-from-ctor-realm.js fails
+built-ins/JSON/parse/revived-proxy-revoked.js fails
+built-ins/JSON/parse/revived-proxy.js fails
+built-ins/JSON/stringify/replacer-proxy-revoked.js fails
+built-ins/JSON/stringify/replacer-proxy.js fails
+built-ins/JSON/stringify/value-proxy.js fails
+built-ins/Map/iterable-calls-set.js fails
+built-ins/Map/iterator-close-after-set-failure.js fails
+built-ins/Map/iterator-is-undefined-throws.js fails
+built-ins/Map/iterator-item-first-entry-returns-abrupt.js fails
+built-ins/Map/iterator-item-second-entry-returns-abrupt.js fails
+built-ins/Map/iterator-items-are-not-object-close-iterator.js fails
+built-ins/Map/iterator-items-are-not-object.js fails
+built-ins/Map/map-iterable-throws-when-set-is-not-callable.js fails
+built-ins/Map/map-iterable.js fails
+built-ins/Map/proto-from-ctor-realm.js fails
+built-ins/Map/prototype/clear/context-is-weakmap-object-throws.js fails
+built-ins/Map/prototype/delete/context-is-weakmap-object-throws.js fails
+built-ins/Map/prototype/delete/does-not-break-iterators.js fails
+built-ins/Map/prototype/delete/returns-true-for-deleted-entry.js fails
+built-ins/Map/prototype/entries/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/forEach/callback-parameters.js fails
+built-ins/Map/prototype/forEach/deleted-values-during-foreach.js fails
+built-ins/Map/prototype/forEach/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/forEach/iterates-in-key-insertion-order.js fails
+built-ins/Map/prototype/forEach/iterates-values-added-after-foreach-begins.js fails
+built-ins/Map/prototype/forEach/iterates-values-deleted-then-readded.js fails
+built-ins/Map/prototype/get/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/has/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/keys/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/set/append-new-values.js fails
+built-ins/Map/prototype/set/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/set/length.js fails
+built-ins/Map/prototype/size/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Map/prototype/size/returns-count-of-present-values-by-iterable.js fails
+built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js fails
+built-ins/Math/max/zeros.js fails
+built-ins/Math/round/S15.8.2.15_A7.js fails
+built-ins/NativeErrors/EvalError/proto.js fails
+built-ins/NativeErrors/EvalError/prototype/not-error-object.js fails
+built-ins/NativeErrors/RangeError/proto.js fails
+built-ins/NativeErrors/RangeError/prototype/not-error-object.js fails
+built-ins/NativeErrors/ReferenceError/proto.js fails
+built-ins/NativeErrors/ReferenceError/prototype/not-error-object.js fails
+built-ins/NativeErrors/SyntaxError/proto.js fails
+built-ins/NativeErrors/SyntaxError/prototype/not-error-object.js fails
+built-ins/NativeErrors/TypeError/proto.js fails
+built-ins/NativeErrors/TypeError/prototype/not-error-object.js fails
+built-ins/NativeErrors/URIError/proto.js fails
+built-ins/NativeErrors/URIError/prototype/not-error-object.js fails
+built-ins/Number/isFinite/arg-is-not-number.js fails
+built-ins/Number/isNaN/arg-is-not-number.js fails
+built-ins/Number/proto-from-ctor-realm.js fails
+built-ins/Number/prototype/toExponential/infinity.js fails
+built-ins/Number/prototype/toExponential/nan.js fails
+built-ins/Number/prototype/toExponential/range.js fails
+built-ins/Number/prototype/toFixed/range.js fails
+built-ins/Number/prototype/toPrecision/infinity.js fails
+built-ins/Number/prototype/toPrecision/nan.js fails
+built-ins/Number/prototype/toPrecision/range.js fails
+built-ins/Number/prototype/toPrecision/return-values.js fails
+built-ins/Number/string-binary-literal.js fails
+built-ins/Number/string-hex-literal-invalid.js fails
+built-ins/Number/string-octal-literal.js fails
+built-ins/Object/assign/Target-Symbol.js fails
+built-ins/Object/assign/source-own-prop-desc-missing.js fails
+built-ins/Object/create/15.2.3.5-4-14.js strictFails
+built-ins/Object/create/15.2.3.5-4-37.js strictFails
+built-ins/Object/entries/exception-during-enumeration.js fails
+built-ins/Object/entries/function-length.js fails
+built-ins/Object/entries/function-name.js fails
+built-ins/Object/entries/function-property-descriptor.js fails
+built-ins/Object/entries/getter-adding-key.js fails
+built-ins/Object/entries/getter-making-future-key-nonenumerable.js fails
+built-ins/Object/entries/getter-removing-future-key.js fails
+built-ins/Object/entries/inherited-properties-omitted.js fails
+built-ins/Object/entries/observable-operations.js fails
+built-ins/Object/entries/primitive-booleans.js fails
+built-ins/Object/entries/primitive-numbers.js fails
+built-ins/Object/entries/primitive-strings.js fails
+built-ins/Object/entries/primitive-symbols.js fails
+built-ins/Object/entries/symbols-omitted.js fails
+built-ins/Object/entries/tamper-with-global-object.js fails
+built-ins/Object/entries/tamper-with-object-keys.js fails
+built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-212.js fails
+built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-213.js fails
+built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-214.js fails
+built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-215.js fails
+built-ins/Object/getOwnPropertyDescriptors/function-length.js fails
+built-ins/Object/getOwnPropertyDescriptors/function-name.js fails
+built-ins/Object/getOwnPropertyDescriptors/function-property-descriptor.js fails
+built-ins/Object/getOwnPropertyDescriptors/inherited-properties-omitted.js fails
+built-ins/Object/getOwnPropertyDescriptors/normal-object.js fails
+built-ins/Object/getOwnPropertyDescriptors/observable-operations.js fails
+built-ins/Object/getOwnPropertyDescriptors/primitive-booleans.js fails
+built-ins/Object/getOwnPropertyDescriptors/primitive-numbers.js fails
+built-ins/Object/getOwnPropertyDescriptors/primitive-strings.js fails
+built-ins/Object/getOwnPropertyDescriptors/primitive-symbols.js fails
+built-ins/Object/getOwnPropertyDescriptors/proxy-undefined-descriptor.js fails
+built-ins/Object/getOwnPropertyDescriptors/symbols-included.js fails
+built-ins/Object/getOwnPropertyDescriptors/tamper-with-global-object.js fails
+built-ins/Object/getOwnPropertyDescriptors/tamper-with-object-keys.js fails
+built-ins/Object/getPrototypeOf/15.2.3.2-2-12.js fails
+built-ins/Object/getPrototypeOf/15.2.3.2-2-13.js fails
+built-ins/Object/getPrototypeOf/15.2.3.2-2-14.js fails
+built-ins/Object/getPrototypeOf/15.2.3.2-2-15.js fails
+built-ins/Object/getPrototypeOf/15.2.3.2-2-16.js fails
+built-ins/Object/getPrototypeOf/15.2.3.2-2-17.js fails
+built-ins/Object/isExtensible/15.2.3.13-1-1.js fails
+built-ins/Object/isExtensible/15.2.3.13-1-2.js fails
+built-ins/Object/isFrozen/15.2.3.12-1-1.js fails
+built-ins/Object/isFrozen/15.2.3.12-1-2.js fails
+built-ins/Object/keys/proxy-keys.js fails
+built-ins/Object/preventExtensions/15.2.3.10-1-1.js fails
+built-ins/Object/preventExtensions/15.2.3.10-1-2.js fails
+built-ins/Object/proto-from-ctor.js fails
+built-ins/Object/prototype/toLocaleString/primitive_this_value_getter.js strictFails
+built-ins/Object/prototype/toString/no-prototype-property.js fails
+built-ins/Object/prototype/toString/proxy-array.js fails
+built-ins/Object/prototype/toString/proxy-function.js fails
+built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js fails
+built-ins/Object/values/exception-during-enumeration.js fails
+built-ins/Object/values/function-length.js fails
+built-ins/Object/values/function-name.js fails
+built-ins/Object/values/function-property-descriptor.js fails
+built-ins/Object/values/getter-adding-key.js fails
+built-ins/Object/values/getter-making-future-key-nonenumerable.js fails
+built-ins/Object/values/getter-removing-future-key.js fails
+built-ins/Object/values/inherited-properties-omitted.js fails
+built-ins/Object/values/observable-operations.js fails
+built-ins/Object/values/primitive-booleans.js fails
+built-ins/Object/values/primitive-numbers.js fails
+built-ins/Object/values/primitive-strings.js fails
+built-ins/Object/values/primitive-symbols.js fails
+built-ins/Object/values/symbols-omitted.js fails
+built-ins/Object/values/tamper-with-global-object.js fails
+built-ins/Object/values/tamper-with-object-keys.js fails
+built-ins/Promise/S25.4.3.1_A1.1_T1.js fails
+built-ins/Promise/S25.4.3.1_A2.1_T1.js fails
+built-ins/Promise/S25.4.3.1_A2.2_T1.js fails
+built-ins/Promise/S25.4.3.1_A3.1_T1.js fails
+built-ins/Promise/Symbol.species/length.js fails
+built-ins/Promise/Symbol.species/prop-desc.js fails
+built-ins/Promise/Symbol.species/return-value.js fails
+built-ins/Promise/Symbol.species/symbol-species-name.js fails
+built-ins/Promise/Symbol.species/symbol-species.js fails
+built-ins/Promise/all/S25.4.4.1_A1.1_T1.js fails
+built-ins/Promise/all/S25.4.4.1_A2.1_T1.js fails
+built-ins/Promise/all/S25.4.4.1_A4.1_T1.js fails
+built-ins/Promise/all/S25.4.4.1_A6.1_T1.js fails
+built-ins/Promise/all/call-resolve-element-after-return.js fails
+built-ins/Promise/all/call-resolve-element-items.js fails
+built-ins/Promise/all/call-resolve-element.js fails
+built-ins/Promise/all/capability-executor-called-twice.js fails
+built-ins/Promise/all/capability-executor-not-callable.js fails
+built-ins/Promise/all/capability-resolve-throws-no-close.js fails
+built-ins/Promise/all/ctx-ctor-throws.js fails
+built-ins/Promise/all/ctx-ctor.js fails
+built-ins/Promise/all/ctx-non-ctor.js fails
+built-ins/Promise/all/ctx-non-object.js fails
+built-ins/Promise/all/invoke-resolve-error-close.js fails
+built-ins/Promise/all/invoke-resolve-get-error-close.js fails
+built-ins/Promise/all/invoke-resolve-return.js fails
+built-ins/Promise/all/invoke-resolve.js fails
+built-ins/Promise/all/invoke-then-error-close.js fails
+built-ins/Promise/all/invoke-then-get-error-close.js fails
+built-ins/Promise/all/invoke-then.js fails
+built-ins/Promise/all/iter-next-val-err-no-close.js fails
+built-ins/Promise/all/iter-step-err-no-close.js fails
+built-ins/Promise/all/length.js fails
+built-ins/Promise/all/name.js fails
+built-ins/Promise/all/new-resolve-function.js fails
+built-ins/Promise/all/prop-desc.js fails
+built-ins/Promise/all/resolve-before-loop-exit-from-same.js fails
+built-ins/Promise/all/resolve-before-loop-exit.js fails
+built-ins/Promise/all/resolve-element-function-extensible.js fails
+built-ins/Promise/all/resolve-element-function-length.js fails
+built-ins/Promise/all/resolve-element-function-name.js fails
+built-ins/Promise/all/resolve-element-function-nonconstructor.js fails
+built-ins/Promise/all/resolve-element-function-prototype.js fails
+built-ins/Promise/all/resolve-from-same-thenable.js fails
+built-ins/Promise/all/same-reject-function.js fails
+built-ins/Promise/all/species-get-error.js fails
+built-ins/Promise/exec-args.js fails
+built-ins/Promise/executor-function-extensible.js fails
+built-ins/Promise/executor-function-length.js fails
+built-ins/Promise/executor-function-name.js fails
+built-ins/Promise/executor-function-nonconstructor.js fails
+built-ins/Promise/executor-function-prototype.js fails
+built-ins/Promise/length.js fails
+built-ins/Promise/name.js fails
+built-ins/Promise/proto-from-ctor-realm.js fails
+built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js fails
+built-ins/Promise/prototype/S25.4.5_A3.1_T1.js fails
+built-ins/Promise/prototype/Symbol.toStringTag.js fails
+built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js fails
+built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js fails
+built-ins/Promise/prototype/catch/invokes-then.js fails
+built-ins/Promise/prototype/catch/length.js fails
+built-ins/Promise/prototype/catch/name.js fails
+built-ins/Promise/prototype/catch/prop-desc.js fails
+built-ins/Promise/prototype/catch/this-value-non-object.js fails
+built-ins/Promise/prototype/catch/this-value-obj-coercible.js fails
+built-ins/Promise/prototype/catch/this-value-then-not-callable.js fails
+built-ins/Promise/prototype/catch/this-value-then-poisoned.js fails
+built-ins/Promise/prototype/catch/this-value-then-throws.js fails
+built-ins/Promise/prototype/no-promise-state.js fails
+built-ins/Promise/prototype/prop-desc.js fails
+built-ins/Promise/prototype/proto.js fails
+built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js fails
+built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js fails
+built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js fails
+built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js fails
+built-ins/Promise/prototype/then/capability-executor-called-twice.js fails
+built-ins/Promise/prototype/then/capability-executor-not-callable.js fails
+built-ins/Promise/prototype/then/context-check-on-entry.js fails
+built-ins/Promise/prototype/then/ctor-custom.js fails
+built-ins/Promise/prototype/then/ctor-null.js fails
+built-ins/Promise/prototype/then/ctor-poisoned.js fails
+built-ins/Promise/prototype/then/ctor-throws.js fails
+built-ins/Promise/prototype/then/ctor-undef.js fails
+built-ins/Promise/prototype/then/length.js fails
+built-ins/Promise/prototype/then/name.js fails
+built-ins/Promise/prototype/then/prop-desc.js fails
+built-ins/Promise/race/S25.4.4.3_A1.1_T1.js fails
+built-ins/Promise/race/S25.4.4.3_A2.1_T1.js fails
+built-ins/Promise/race/S25.4.4.3_A3.1_T1.js fails
+built-ins/Promise/race/S25.4.4.3_A3.1_T2.js fails
+built-ins/Promise/race/capability-executor-called-twice.js fails
+built-ins/Promise/race/capability-executor-not-callable.js fails
+built-ins/Promise/race/ctx-ctor-throws.js fails
+built-ins/Promise/race/ctx-ctor.js fails
+built-ins/Promise/race/ctx-non-ctor.js fails
+built-ins/Promise/race/ctx-non-object.js fails
+built-ins/Promise/race/invoke-resolve-error-close.js fails
+built-ins/Promise/race/invoke-resolve-get-error-close.js fails
+built-ins/Promise/race/invoke-resolve-return.js fails
+built-ins/Promise/race/invoke-resolve.js fails
+built-ins/Promise/race/invoke-then-error-close.js fails
+built-ins/Promise/race/invoke-then-get-error-close.js fails
+built-ins/Promise/race/invoke-then.js fails
+built-ins/Promise/race/iter-next-val-err-no-close.js fails
+built-ins/Promise/race/iter-step-err-no-close.js fails
+built-ins/Promise/race/length.js fails
+built-ins/Promise/race/name.js fails
+built-ins/Promise/race/prop-desc.js fails
+built-ins/Promise/race/same-reject-function.js fails
+built-ins/Promise/race/same-resolve-function.js fails
+built-ins/Promise/race/species-get-error.js fails
+built-ins/Promise/reject-function-extensible.js fails
+built-ins/Promise/reject-function-length.js fails
+built-ins/Promise/reject-function-name.js fails
+built-ins/Promise/reject-function-nonconstructor.js fails
+built-ins/Promise/reject-function-prototype.js fails
+built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js fails
+built-ins/Promise/reject/S25.4.4.4_A3.1_T1.js fails
+built-ins/Promise/reject/capability-executor-called-twice.js fails
+built-ins/Promise/reject/capability-executor-not-callable.js fails
+built-ins/Promise/reject/capability-invocation-error.js fails
+built-ins/Promise/reject/capability-invocation.js fails
+built-ins/Promise/reject/ctx-ctor-throws.js fails
+built-ins/Promise/reject/ctx-ctor.js fails
+built-ins/Promise/reject/ctx-non-ctor.js fails
+built-ins/Promise/reject/ctx-non-object.js fails
+built-ins/Promise/reject/length.js fails
+built-ins/Promise/reject/name.js fails
+built-ins/Promise/reject/prop-desc.js fails
+built-ins/Promise/resolve-function-extensible.js fails
+built-ins/Promise/resolve-function-length.js fails
+built-ins/Promise/resolve-function-name.js fails
+built-ins/Promise/resolve-function-nonconstructor.js fails
+built-ins/Promise/resolve-function-prototype.js fails
+built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js fails
+built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js fails
+built-ins/Promise/resolve/arg-uniq-ctor.js fails
+built-ins/Promise/resolve/capability-executor-called-twice.js fails
+built-ins/Promise/resolve/capability-executor-not-callable.js fails
+built-ins/Promise/resolve/capability-invocation-error.js fails
+built-ins/Promise/resolve/context-non-object-with-promise.js fails
+built-ins/Promise/resolve/ctx-ctor-throws.js fails
+built-ins/Promise/resolve/ctx-ctor.js fails
+built-ins/Promise/resolve/ctx-non-ctor.js fails
+built-ins/Promise/resolve/ctx-non-object.js fails
+built-ins/Promise/resolve/length.js fails
+built-ins/Promise/resolve/name.js fails
+built-ins/Promise/resolve/prop-desc.js fails
+built-ins/Promise/resolve/resolve-from-promise-capability.js fails
+built-ins/Promise/resolve/resolve-prms-cstm-then.js fails
+built-ins/Proxy/apply/arguments-realm.js fails
+built-ins/Proxy/apply/call-parameters.js fails
+built-ins/Proxy/apply/call-result.js fails
+built-ins/Proxy/apply/return-abrupt.js fails
+built-ins/Proxy/apply/trap-is-not-callable-realm.js fails
+built-ins/Proxy/apply/trap-is-null.js fails
+built-ins/Proxy/apply/trap-is-undefined-no-property.js fails
+built-ins/Proxy/apply/trap-is-undefined.js fails
+built-ins/Proxy/construct/arguments-realm.js fails
+built-ins/Proxy/construct/call-parameters-new-target.js fails
+built-ins/Proxy/construct/call-parameters.js fails
+built-ins/Proxy/construct/call-result.js fails
+built-ins/Proxy/construct/return-is-abrupt.js fails
+built-ins/Proxy/construct/trap-is-not-callable-realm.js fails
+built-ins/Proxy/construct/trap-is-null.js fails
+built-ins/Proxy/construct/trap-is-undefined-no-property.js fails
+built-ins/Proxy/construct/trap-is-undefined-proto-from-ctor-realm.js fails
+built-ins/Proxy/construct/trap-is-undefined.js fails
+built-ins/Proxy/create-target-is-not-constructor.js fails
+built-ins/Proxy/defineProperty/desc-realm.js fails
+built-ins/Proxy/defineProperty/null-handler-realm.js fails
+built-ins/Proxy/defineProperty/targetdesc-configurable-desc-not-configurable-realm.js fails
+built-ins/Proxy/defineProperty/targetdesc-not-compatible-descriptor-not-configurable-target-realm.js fails
+built-ins/Proxy/defineProperty/targetdesc-not-compatible-descriptor-not-configurable-target.js fails
+built-ins/Proxy/defineProperty/targetdesc-not-compatible-descriptor-realm.js fails
+built-ins/Proxy/defineProperty/targetdesc-not-compatible-descriptor.js fails
+built-ins/Proxy/defineProperty/targetdesc-undefined-not-configurable-descriptor-realm.js fails
+built-ins/Proxy/defineProperty/targetdesc-undefined-target-is-not-extensible-realm.js fails
+built-ins/Proxy/defineProperty/trap-is-not-callable-realm.js fails
+built-ins/Proxy/deleteProperty/trap-is-not-callable-realm.js fails
+built-ins/Proxy/enumerate/removed-does-not-trigger.js fails
+built-ins/Proxy/get-fn-realm.js fails
+built-ins/Proxy/get/trap-is-not-callable-realm.js fails
+built-ins/Proxy/get/trap-is-undefined-receiver.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/result-type-is-not-object-nor-undefined-realm.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/result-type-is-not-object-nor-undefined.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/resultdesc-is-invalid-descriptor.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/resultdesc-is-not-configurable-targetdesc-is-configurable.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/resultdesc-return-not-configurable.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/trap-is-not-callable-realm.js fails
+built-ins/Proxy/getOwnPropertyDescriptor/trap-is-undefined.js fails
+built-ins/Proxy/getPrototypeOf/trap-is-not-callable-realm.js fails
+built-ins/Proxy/has/call-object-create.js fails
+built-ins/Proxy/has/call-with.js sloppyFails
+built-ins/Proxy/has/return-false-target-not-extensible-using-with.js sloppyFails
+built-ins/Proxy/has/return-false-target-prop-exists-using-with.js sloppyFails
+built-ins/Proxy/has/return-false-targetdesc-not-configurable-using-with.js sloppyFails
+built-ins/Proxy/has/return-is-abrupt-with.js sloppyFails
+built-ins/Proxy/has/trap-is-not-callable-realm.js fails
+built-ins/Proxy/has/trap-is-not-callable-using-with.js sloppyFails
+built-ins/Proxy/isExtensible/trap-is-not-callable-realm.js fails
+built-ins/Proxy/ownKeys/call-parameters-object-getownpropertynames.js fails
+built-ins/Proxy/ownKeys/call-parameters-object-getownpropertysymbols.js fails
+built-ins/Proxy/ownKeys/call-parameters-object-keys.js fails
+built-ins/Proxy/ownKeys/extensible-return-trap-result-absent-not-configurable-keys.js fails
+built-ins/Proxy/ownKeys/extensible-return-trap-result.js fails
+built-ins/Proxy/ownKeys/not-extensible-missing-keys-throws.js fails
+built-ins/Proxy/ownKeys/not-extensible-new-keys-throws.js fails
+built-ins/Proxy/ownKeys/not-extensible-return-keys.js fails
+built-ins/Proxy/ownKeys/null-handler.js fails
+built-ins/Proxy/ownKeys/return-all-non-configurable-keys.js fails
+built-ins/Proxy/ownKeys/return-duplicate-entries-throws.js fails
+built-ins/Proxy/ownKeys/return-duplicate-symbol-entries-throws.js fails
+built-ins/Proxy/ownKeys/return-not-list-object-throws-realm.js fails
+built-ins/Proxy/ownKeys/return-not-list-object-throws.js fails
+built-ins/Proxy/ownKeys/return-type-throws-array.js fails
+built-ins/Proxy/ownKeys/return-type-throws-boolean.js fails
+built-ins/Proxy/ownKeys/return-type-throws-null.js fails
+built-ins/Proxy/ownKeys/return-type-throws-number.js fails
+built-ins/Proxy/ownKeys/return-type-throws-object.js fails
+built-ins/Proxy/ownKeys/return-type-throws-undefined.js fails
+built-ins/Proxy/ownKeys/trap-is-not-callable-realm.js fails
+built-ins/Proxy/ownKeys/trap-is-not-callable.js fails
+built-ins/Proxy/ownKeys/trap-is-undefined.js fails
+built-ins/Proxy/preventExtensions/trap-is-not-callable-realm.js fails
+built-ins/Proxy/proxy-no-prototype.js fails
+built-ins/Proxy/revocable/revocation-function-name.js fails
+built-ins/Proxy/revocable/revocation-function-nonconstructor.js fails
+built-ins/Proxy/set/trap-is-not-callable-realm.js fails
+built-ins/Proxy/set/trap-is-undefined-receiver.js fails
+built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js fails
+built-ins/Reflect/construct/newtarget-is-not-constructor-throws.js fails
+built-ins/Reflect/construct/return-with-newtarget-argument.js fails
+built-ins/Reflect/ownKeys/return-on-corresponding-order.js fails
+built-ins/Reflect/set/creates-a-data-descriptor.js fails
+built-ins/Reflect/set/different-property-descriptors.js fails
+built-ins/Reflect/set/receiver-is-not-object.js fails
+built-ins/Reflect/set/return-false-if-target-is-not-writable.js fails
+built-ins/Reflect/set/set-value-on-data-descriptor.js fails
+built-ins/Reflect/set/symbol-property.js fails
+built-ins/RegExp/15.10.4.1-1.js fails
+built-ins/RegExp/S15.10.2.12_A2_T1.js fails
+built-ins/RegExp/S15.10.3.1_A2_T1.js fails
+built-ins/RegExp/S15.10.3.1_A2_T2.js fails
+built-ins/RegExp/S15.10.4.1_A2_T1.js fails
+built-ins/RegExp/S15.10.4.1_A2_T2.js fails
+built-ins/RegExp/call_with_non_regexp_same_constructor.js fails
+built-ins/RegExp/call_with_regexp_match_falsy.js fails
+built-ins/RegExp/call_with_regexp_not_same_constructor.js fails
+built-ins/RegExp/dotall/without-dotall-unicode.js fails
+built-ins/RegExp/from-regexp-like-flag-override.js fails
+built-ins/RegExp/from-regexp-like-get-source-err.js fails
+built-ins/RegExp/from-regexp-like-short-circuit.js fails
+built-ins/RegExp/from-regexp-like.js fails
+built-ins/RegExp/proto-from-ctor-realm.js fails
+built-ins/RegExp/prototype/15.10.6.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-coerce-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-failure-g-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-failure-return-val.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-failure-y-return-val.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-failure-y-set-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-failure-y-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-infer-unicode.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-success-g-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-success-return-val-groups.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-success-return-val.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-success-u-return-val-groups.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-success-y-set-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-success-y-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/builtin-y-coerce-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.match/coerce-arg-err.js fails
+built-ins/RegExp/prototype/Symbol.match/coerce-arg.js fails
+built-ins/RegExp/prototype/Symbol.match/coerce-global.js fails
+built-ins/RegExp/prototype/Symbol.match/exec-err.js fails
+built-ins/RegExp/prototype/Symbol.match/exec-invocation.js fails
+built-ins/RegExp/prototype/Symbol.match/exec-return-type-invalid.js fails
+built-ins/RegExp/prototype/Symbol.match/exec-return-type-valid.js fails
+built-ins/RegExp/prototype/Symbol.match/g-coerce-result-err.js fails
+built-ins/RegExp/prototype/Symbol.match/g-get-exec-err.js fails
+built-ins/RegExp/prototype/Symbol.match/g-get-result-err.js fails
+built-ins/RegExp/prototype/Symbol.match/g-init-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/g-match-empty-advance-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/g-match-empty-coerce-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.match/g-match-no-coerce-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/g-match-no-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/g-success-return-val.js fails
+built-ins/RegExp/prototype/Symbol.match/g-zero-matches.js fails
+built-ins/RegExp/prototype/Symbol.match/get-exec-err.js fails
+built-ins/RegExp/prototype/Symbol.match/get-global-err.js fails
+built-ins/RegExp/prototype/Symbol.match/get-unicode-error.js fails
+built-ins/RegExp/prototype/Symbol.match/length.js fails
+built-ins/RegExp/prototype/Symbol.match/name.js fails
+built-ins/RegExp/prototype/Symbol.match/prop-desc.js fails
+built-ins/RegExp/prototype/Symbol.match/this-val-non-regexp.js fails
+built-ins/RegExp/prototype/Symbol.match/u-advance-after-empty.js fails
+built-ins/RegExp/prototype/Symbol.match/y-fail-global-return.js fails
+built-ins/RegExp/prototype/Symbol.match/y-fail-lastindex-no-write.js fails
+built-ins/RegExp/prototype/Symbol.match/y-fail-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/y-fail-return.js fails
+built-ins/RegExp/prototype/Symbol.match/y-init-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.match/y-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.replace/arg-1-coerce-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/arg-1-coerce.js fails
+built-ins/RegExp/prototype/Symbol.replace/arg-2-coerce-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/arg-2-coerce.js fails
+built-ins/RegExp/prototype/Symbol.replace/coerce-global.js fails
+built-ins/RegExp/prototype/Symbol.replace/coerce-unicode.js fails
+built-ins/RegExp/prototype/Symbol.replace/exec-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/exec-invocation.js fails
+built-ins/RegExp/prototype/Symbol.replace/fn-coerce-replacement-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/fn-coerce-replacement.js fails
+built-ins/RegExp/prototype/Symbol.replace/fn-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/fn-invoke-args.js fails
+built-ins/RegExp/prototype/Symbol.replace/fn-invoke-this-no-strict.js sloppyFails
+built-ins/RegExp/prototype/Symbol.replace/fn-invoke-this-strict.js strictFails
+built-ins/RegExp/prototype/Symbol.replace/g-init-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/g-init-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.replace/g-pos-decrement.js fails
+built-ins/RegExp/prototype/Symbol.replace/g-pos-increment.js fails
+built-ins/RegExp/prototype/Symbol.replace/get-exec-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/get-global-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/get-unicode-error.js fails
+built-ins/RegExp/prototype/Symbol.replace/length.js fails
+built-ins/RegExp/prototype/Symbol.replace/match-failure.js fails
+built-ins/RegExp/prototype/Symbol.replace/name.js fails
+built-ins/RegExp/prototype/Symbol.replace/prop-desc.js fails
+built-ins/RegExp/prototype/Symbol.replace/replace-with-trailing.js fails
+built-ins/RegExp/prototype/Symbol.replace/replace-without-trailing.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-capture-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-capture.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-index-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-index.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-length-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-length.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-matched-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-coerce-matched.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-get-capture-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-get-index-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-get-length-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/result-get-matched-err.js fails
+built-ins/RegExp/prototype/Symbol.replace/subst-after.js fails
+built-ins/RegExp/prototype/Symbol.replace/subst-before.js fails
+built-ins/RegExp/prototype/Symbol.replace/subst-capture-idx-1.js fails
+built-ins/RegExp/prototype/Symbol.replace/subst-capture-idx-2.js fails
+built-ins/RegExp/prototype/Symbol.replace/subst-dollar.js fails
+built-ins/RegExp/prototype/Symbol.replace/subst-matched.js fails
+built-ins/RegExp/prototype/Symbol.replace/u-advance-after-empty.js fails
+built-ins/RegExp/prototype/Symbol.replace/y-fail-global-return.js fails
+built-ins/RegExp/prototype/Symbol.replace/y-fail-lastindex-no-write.js fails
+built-ins/RegExp/prototype/Symbol.replace/y-fail-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.replace/y-fail-return.js fails
+built-ins/RegExp/prototype/Symbol.replace/y-init-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.replace/y-set-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.search/coerce-string-err.js fails
+built-ins/RegExp/prototype/Symbol.search/coerce-string.js fails
+built-ins/RegExp/prototype/Symbol.search/cstm-exec-return-index.js fails
+built-ins/RegExp/prototype/Symbol.search/failure-return-val.js fails
+built-ins/RegExp/prototype/Symbol.search/get-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.search/lastindex-no-restore.js fails
+built-ins/RegExp/prototype/Symbol.search/length.js fails
+built-ins/RegExp/prototype/Symbol.search/match-err.js fails
+built-ins/RegExp/prototype/Symbol.search/name.js fails
+built-ins/RegExp/prototype/Symbol.search/prop-desc.js fails
+built-ins/RegExp/prototype/Symbol.search/set-lastindex-init-err.js fails
+built-ins/RegExp/prototype/Symbol.search/set-lastindex-init.js fails
+built-ins/RegExp/prototype/Symbol.search/set-lastindex-restore-err.js fails
+built-ins/RegExp/prototype/Symbol.search/set-lastindex-restore.js fails
+built-ins/RegExp/prototype/Symbol.search/success-get-index-err.js fails
+built-ins/RegExp/prototype/Symbol.search/success-return-val.js fails
+built-ins/RegExp/prototype/Symbol.search/u-lastindex-advance.js fails
+built-ins/RegExp/prototype/Symbol.search/y-fail-return.js fails
+built-ins/RegExp/prototype/Symbol.split/coerce-flags-err.js fails
+built-ins/RegExp/prototype/Symbol.split/coerce-flags.js fails
+built-ins/RegExp/prototype/Symbol.split/coerce-limit-err.js fails
+built-ins/RegExp/prototype/Symbol.split/coerce-limit.js fails
+built-ins/RegExp/prototype/Symbol.split/coerce-string-err.js fails
+built-ins/RegExp/prototype/Symbol.split/coerce-string.js fails
+built-ins/RegExp/prototype/Symbol.split/get-flags-err.js fails
+built-ins/RegExp/prototype/Symbol.split/last-index-exceeds-str-size.js fails
+built-ins/RegExp/prototype/Symbol.split/length.js fails
+built-ins/RegExp/prototype/Symbol.split/limit-0-bail.js fails
+built-ins/RegExp/prototype/Symbol.split/name.js fails
+built-ins/RegExp/prototype/Symbol.split/prop-desc.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-ctor-get-err.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-ctor-non-obj.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-ctor-undef.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-err.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-species-get-err.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-species-non-ctor.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-species-undef.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor-y.js fails
+built-ins/RegExp/prototype/Symbol.split/species-ctor.js fails
+built-ins/RegExp/prototype/Symbol.split/splitter-proto-from-ctor-realm.js fails
+built-ins/RegExp/prototype/Symbol.split/str-adv-thru-empty-match.js fails
+built-ins/RegExp/prototype/Symbol.split/str-coerce-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-coerce-lastindex.js fails
+built-ins/RegExp/prototype/Symbol.split/str-empty-match-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-empty-match.js fails
+built-ins/RegExp/prototype/Symbol.split/str-empty-no-match.js fails
+built-ins/RegExp/prototype/Symbol.split/str-get-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-limit-capturing.js fails
+built-ins/RegExp/prototype/Symbol.split/str-limit.js fails
+built-ins/RegExp/prototype/Symbol.split/str-match-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-result-coerce-length-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-result-coerce-length.js fails
+built-ins/RegExp/prototype/Symbol.split/str-result-get-capture-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-result-get-length-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-set-lastindex-err.js fails
+built-ins/RegExp/prototype/Symbol.split/str-set-lastindex-match.js fails
+built-ins/RegExp/prototype/Symbol.split/str-set-lastindex-no-match.js fails
+built-ins/RegExp/prototype/Symbol.split/str-trailing-chars.js fails
+built-ins/RegExp/prototype/Symbol.split/u-lastindex-adv-thru-failure.js fails
+built-ins/RegExp/prototype/Symbol.split/u-lastindex-adv-thru-match.js fails
+built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js fails
+built-ins/RegExp/prototype/exec/failure-lastindex-access.js fails
+built-ins/RegExp/prototype/exec/success-lastindex-access.js fails
+built-ins/RegExp/prototype/exec/u-captured-value.js fails
+built-ins/RegExp/prototype/exec/u-lastindex-adv.js fails
+built-ins/RegExp/prototype/exec/u-lastindex-value.js fails
+built-ins/RegExp/prototype/exec/y-fail-lastindex-no-write.js fails
+built-ins/RegExp/prototype/exec/y-fail-lastindex.js fails
+built-ins/RegExp/prototype/exec/y-fail-return.js fails
+built-ins/RegExp/prototype/exec/y-init-lastindex.js fails
+built-ins/RegExp/prototype/exec/y-set-lastindex.js fails
+built-ins/RegExp/prototype/flags/coercion-global.js fails
+built-ins/RegExp/prototype/flags/coercion-ignoreCase.js fails
+built-ins/RegExp/prototype/flags/coercion-multiline.js fails
+built-ins/RegExp/prototype/flags/coercion-sticky.js fails
+built-ins/RegExp/prototype/flags/coercion-unicode.js fails
+built-ins/RegExp/prototype/flags/length.js fails
+built-ins/RegExp/prototype/flags/name.js fails
+built-ins/RegExp/prototype/flags/prop-desc.js fails
+built-ins/RegExp/prototype/flags/this-val-non-obj.js fails
+built-ins/RegExp/prototype/flags/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/global/15.10.7.2-2.js fails
+built-ins/RegExp/prototype/global/S15.10.7.2_A9.js fails
+built-ins/RegExp/prototype/global/length.js fails
+built-ins/RegExp/prototype/global/name.js fails
+built-ins/RegExp/prototype/global/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/ignoreCase/15.10.7.3-2.js fails
+built-ins/RegExp/prototype/ignoreCase/S15.10.7.3_A9.js fails
+built-ins/RegExp/prototype/ignoreCase/length.js fails
+built-ins/RegExp/prototype/ignoreCase/name.js fails
+built-ins/RegExp/prototype/ignoreCase/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/multiline/15.10.7.4-2.js fails
+built-ins/RegExp/prototype/multiline/S15.10.7.4_A9.js fails
+built-ins/RegExp/prototype/multiline/length.js fails
+built-ins/RegExp/prototype/multiline/name.js fails
+built-ins/RegExp/prototype/multiline/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/no-regexp-matcher.js fails
+built-ins/RegExp/prototype/source/length.js fails
+built-ins/RegExp/prototype/source/name.js fails
+built-ins/RegExp/prototype/source/prop-desc.js fails
+built-ins/RegExp/prototype/source/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/source/value-line-terminator.js fails
+built-ins/RegExp/prototype/source/value-u.js fails
+built-ins/RegExp/prototype/sticky/length.js fails
+built-ins/RegExp/prototype/sticky/name.js fails
+built-ins/RegExp/prototype/sticky/prop-desc.js fails
+built-ins/RegExp/prototype/sticky/this-val-invalid-obj.js fails
+built-ins/RegExp/prototype/sticky/this-val-non-obj.js fails
+built-ins/RegExp/prototype/sticky/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/sticky/this-val-regexp.js fails
+built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js fails
+built-ins/RegExp/prototype/test/y-fail-lastindex-no-write.js fails
+built-ins/RegExp/prototype/test/y-fail-lastindex.js fails
+built-ins/RegExp/prototype/test/y-fail-return.js fails
+built-ins/RegExp/prototype/test/y-init-lastindex.js fails
+built-ins/RegExp/prototype/test/y-set-lastindex.js fails
+built-ins/RegExp/prototype/unicode/length.js fails
+built-ins/RegExp/prototype/unicode/name.js fails
+built-ins/RegExp/prototype/unicode/prop-desc.js fails
+built-ins/RegExp/prototype/unicode/this-val-invalid-obj.js fails
+built-ins/RegExp/prototype/unicode/this-val-non-obj.js fails
+built-ins/RegExp/prototype/unicode/this-val-regexp-prototype.js fails
+built-ins/RegExp/prototype/unicode/this-val-regexp.js fails
+built-ins/RegExp/u180e.js fails
+built-ins/RegExp/unicode_identity_escape.js fails
+built-ins/RegExp/valid-flags-y.js fails
+built-ins/Set/proto-from-ctor-realm.js fails
+built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/Set/prototype/clear/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/Set/prototype/delete/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/Set/prototype/entries/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/Set/prototype/forEach/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js fails
+built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js fails
+built-ins/Set/prototype/has/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/Set/prototype/values/does-not-have-setdata-internal-slot-weakset.js fails
+built-ins/SharedArrayBuffer/allocation-limit.js fails
+built-ins/SharedArrayBuffer/data-allocation-after-object-creation.js fails
+built-ins/SharedArrayBuffer/init-zero.js fails
+built-ins/SharedArrayBuffer/length-is-absent.js fails
+built-ins/SharedArrayBuffer/length-is-too-large-throws.js fails
+built-ins/SharedArrayBuffer/negative-length-throws.js fails
+built-ins/SharedArrayBuffer/newtarget-prototype-is-not-object.js fails
+built-ins/SharedArrayBuffer/proto-from-ctor-realm.js fails
+built-ins/SharedArrayBuffer/prototype-from-newtarget.js fails
+built-ins/SharedArrayBuffer/prototype/Symbol.toStringTag.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/invoked-as-accessor.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/invoked-as-func.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/length.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/name.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/prop-desc.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/return-bytelength.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/this-has-no-typedarrayname-internal.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/this-is-arraybuffer.js fails
+built-ins/SharedArrayBuffer/prototype/byteLength/this-is-not-object.js fails
+built-ins/SharedArrayBuffer/prototype/constructor.js fails
+built-ins/SharedArrayBuffer/prototype/slice/context-is-not-arraybuffer-object.js fails
+built-ins/SharedArrayBuffer/prototype/slice/context-is-not-object.js fails
+built-ins/SharedArrayBuffer/prototype/slice/descriptor.js fails
+built-ins/SharedArrayBuffer/prototype/slice/end-default-if-absent.js fails
+built-ins/SharedArrayBuffer/prototype/slice/end-default-if-undefined.js fails
+built-ins/SharedArrayBuffer/prototype/slice/end-exceeds-length.js fails
+built-ins/SharedArrayBuffer/prototype/slice/extensible.js fails
+built-ins/SharedArrayBuffer/prototype/slice/length.js fails
+built-ins/SharedArrayBuffer/prototype/slice/name.js fails
+built-ins/SharedArrayBuffer/prototype/slice/negative-end.js fails
+built-ins/SharedArrayBuffer/prototype/slice/negative-start.js fails
+built-ins/SharedArrayBuffer/prototype/slice/nonconstructor.js fails
+built-ins/SharedArrayBuffer/prototype/slice/number-conversion.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-constructor-is-not-object.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-constructor-is-undefined.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-is-not-constructor.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-is-not-object.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-is-null.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-is-undefined.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-returns-larger-arraybuffer.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-returns-not-arraybuffer.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-returns-same-arraybuffer.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species-returns-smaller-arraybuffer.js fails
+built-ins/SharedArrayBuffer/prototype/slice/species.js fails
+built-ins/SharedArrayBuffer/prototype/slice/start-default-if-absent.js fails
+built-ins/SharedArrayBuffer/prototype/slice/start-default-if-undefined.js fails
+built-ins/SharedArrayBuffer/prototype/slice/start-exceeds-end.js fails
+built-ins/SharedArrayBuffer/prototype/slice/start-exceeds-length.js fails
+built-ins/SharedArrayBuffer/prototype/slice/this-is-arraybuffer.js fails
+built-ins/SharedArrayBuffer/prototype/slice/tointeger-conversion-end.js fails
+built-ins/SharedArrayBuffer/prototype/slice/tointeger-conversion-start.js fails
+built-ins/SharedArrayBuffer/return-abrupt-from-length-symbol.js fails
+built-ins/SharedArrayBuffer/return-abrupt-from-length.js fails
+built-ins/SharedArrayBuffer/toindex-length.js fails
+built-ins/SharedArrayBuffer/undefined-newtarget-throws.js fails
+built-ins/SharedArrayBuffer/zero-length.js fails
+built-ins/String/proto-from-ctor-realm.js fails
+built-ins/String/prototype/endsWith/return-abrupt-from-searchstring-regexp-test.js fails
+built-ins/String/prototype/includes/return-abrupt-from-searchstring-regexp-test.js fails
+built-ins/String/prototype/indexOf/position-tointeger-toprimitive.js fails
+built-ins/String/prototype/indexOf/position-tointeger.js fails
+built-ins/String/prototype/indexOf/searchstring-tostring-toprimitive.js fails
+built-ins/String/prototype/match/invoke-builtin-match.js fails
+built-ins/String/prototype/match/cstm-matcher-invocation.js fails
+built-ins/String/prototype/replace/cstm-replace-invocation.js fails
+built-ins/String/prototype/replace/this-value-not-obj-coercible.js fails
+built-ins/String/prototype/search/cstm-search-invocation.js fails
+built-ins/String/prototype/search/invoke-builtin-search-searcher-undef.js fails
+built-ins/String/prototype/search/invoke-builtin-search.js fails
+built-ins/String/prototype/slice/this-value-not-obj-coercible.js fails
+built-ins/String/prototype/split/cstm-split-invocation.js fails
+built-ins/String/prototype/startsWith/return-abrupt-from-searchstring-regexp-test.js fails
+built-ins/String/prototype/toLocaleLowerCase/Final_Sigma_U180E.js fails
+built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional.js fails
+built-ins/String/prototype/toLowerCase/Final_Sigma_U180E.js fails
+built-ins/String/prototype/toLowerCase/special_casing_conditional.js fails
+built-ins/String/raw/length.js fails
+built-ins/String/raw/name.js fails
+built-ins/String/raw/raw.js fails
+built-ins/String/raw/return-empty-string-from-empty-array-length.js fails
+built-ins/String/raw/return-empty-string-if-length-is-negative-infinity.js fails
+built-ins/String/raw/return-empty-string-if-length-is-not-defined.js fails
+built-ins/String/raw/return-empty-string-if-length-is-undefined.js fails
+built-ins/String/raw/return-empty-string-if-length-is-zero-NaN.js fails
+built-ins/String/raw/return-empty-string-if-length-is-zero-boolean.js fails
+built-ins/String/raw/return-empty-string-if-length-is-zero-null.js fails
+built-ins/String/raw/return-empty-string-if-length-is-zero-or-less-number.js fails
+built-ins/String/raw/return-empty-string-if-length-is-zero-or-less-string.js fails
+built-ins/String/raw/return-the-string-value-from-template.js fails
+built-ins/String/raw/return-the-string-value.js fails
+built-ins/String/raw/returns-abrupt-from-next-key-toString.js fails
+built-ins/String/raw/returns-abrupt-from-next-key.js fails
+built-ins/String/raw/returns-abrupt-from-substitution.js fails
+built-ins/String/raw/special-characters.js fails
+built-ins/String/raw/substitutions-are-appended-on-same-index.js fails
+built-ins/String/raw/substitutions-are-limited-to-template-raw-length.js fails
+built-ins/String/raw/template-length-throws.js fails
+built-ins/String/raw/template-raw-throws.js fails
+built-ins/String/raw/template-substitutions-are-appended-on-same-index.js fails
+built-ins/String/raw/zero-literal-segments.js fails
+built-ins/Symbol/for/cross-realm.js fails
+built-ins/Symbol/hasInstance/cross-realm.js fails
+built-ins/Symbol/isConcatSpreadable/cross-realm.js fails
+built-ins/Symbol/iterator/cross-realm.js fails
+built-ins/Symbol/keyFor/cross-realm.js fails
+built-ins/Symbol/match/cross-realm.js fails
+built-ins/Symbol/replace/cross-realm.js fails
+built-ins/Symbol/search/cross-realm.js fails
+built-ins/Symbol/species/builtin-getter-name.js fails
+built-ins/Symbol/species/cross-realm.js fails
+built-ins/Symbol/split/cross-realm.js fails
+built-ins/Symbol/toPrimitive/cross-realm.js fails
+built-ins/Symbol/toStringTag/cross-realm.js fails
+built-ins/Symbol/unscopables/cross-realm.js fails
+built-ins/ThrowTypeError/distinct-cross-realm.js fails
+built-ins/TypedArray/from/arylk-get-length-error.js fails
+built-ins/TypedArray/from/arylk-to-length-error.js fails
+built-ins/TypedArray/from/iter-access-error.js fails
+built-ins/TypedArray/from/iter-invoke-error.js fails
+built-ins/TypedArray/from/iter-next-error.js fails
+built-ins/TypedArray/from/iter-next-value-error.js fails
+built-ins/TypedArray/from/length.js fails
+built-ins/TypedArray/from/name.js fails
+built-ins/TypedArray/from/prop-desc.js fails
+built-ins/TypedArray/name.js fails
+built-ins/TypedArray/of/length.js fails
+built-ins/TypedArray/of/name.js fails
+built-ins/TypedArray/of/prop-desc.js fails
+built-ins/TypedArray/prototype/Symbol.toStringTag/detached-buffer.js fails
+built-ins/TypedArray/prototype/buffer/detached-buffer.js fails
+built-ins/TypedArray/prototype/byteLength/detached-buffer.js fails
+built-ins/TypedArray/prototype/byteOffset/detached-buffer.js fails
+built-ins/TypedArray/prototype/constructor.js fails
+built-ins/TypedArray/prototype/copyWithin/bit-precision.js fails
+built-ins/TypedArray/prototype/copyWithin/coerced-values-end.js fails
+built-ins/TypedArray/prototype/copyWithin/coerced-values-start.js fails
+built-ins/TypedArray/prototype/copyWithin/coerced-values-target.js fails
+built-ins/TypedArray/prototype/copyWithin/detached-buffer.js fails
+built-ins/TypedArray/prototype/copyWithin/get-length-ignores-length-prop.js fails
+built-ins/TypedArray/prototype/copyWithin/invoked-as-func.js fails
+built-ins/TypedArray/prototype/copyWithin/invoked-as-method.js fails
+built-ins/TypedArray/prototype/copyWithin/length.js fails
+built-ins/TypedArray/prototype/copyWithin/name.js fails
+built-ins/TypedArray/prototype/copyWithin/negative-end.js fails
+built-ins/TypedArray/prototype/copyWithin/negative-out-of-bounds-end.js fails
+built-ins/TypedArray/prototype/copyWithin/negative-out-of-bounds-start.js fails
+built-ins/TypedArray/prototype/copyWithin/negative-out-of-bounds-target.js fails
+built-ins/TypedArray/prototype/copyWithin/negative-start.js fails
+built-ins/TypedArray/prototype/copyWithin/negative-target.js fails
+built-ins/TypedArray/prototype/copyWithin/non-negative-out-of-bounds-end.js fails
+built-ins/TypedArray/prototype/copyWithin/non-negative-out-of-bounds-target-and-start.js fails
+built-ins/TypedArray/prototype/copyWithin/non-negative-target-and-start.js fails
+built-ins/TypedArray/prototype/copyWithin/non-negative-target-start-and-end.js fails
+built-ins/TypedArray/prototype/copyWithin/prop-desc.js fails
+built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-end.js fails
+built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-start.js fails
+built-ins/TypedArray/prototype/copyWithin/return-abrupt-from-target.js fails
+built-ins/TypedArray/prototype/copyWithin/return-this.js fails
+built-ins/TypedArray/prototype/copyWithin/undefined-end.js fails
+built-ins/TypedArray/prototype/entries/detached-buffer.js fails
+built-ins/TypedArray/prototype/every/callbackfn-arguments-with-thisarg.js fails
+built-ins/TypedArray/prototype/every/callbackfn-arguments-without-thisarg.js fails
+built-ins/TypedArray/prototype/every/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/every/callbackfn-no-interaction-over-non-integer.js fails
+built-ins/TypedArray/prototype/every/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/every/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/every/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/every/callbackfn-set-value-during-interaction.js fails
+built-ins/TypedArray/prototype/every/callbackfn-this.js fails
+built-ins/TypedArray/prototype/every/detached-buffer.js fails
+built-ins/TypedArray/prototype/every/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/every/invoked-as-func.js fails
+built-ins/TypedArray/prototype/every/invoked-as-method.js fails
+built-ins/TypedArray/prototype/every/length.js fails
+built-ins/TypedArray/prototype/every/name.js fails
+built-ins/TypedArray/prototype/every/prop-desc.js fails
+built-ins/TypedArray/prototype/every/returns-false-if-any-cb-returns-false.js fails
+built-ins/TypedArray/prototype/every/returns-true-if-every-cb-returns-true.js fails
+built-ins/TypedArray/prototype/every/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/fill/coerced-indexes.js fails
+built-ins/TypedArray/prototype/fill/detached-buffer.js fails
+built-ins/TypedArray/prototype/fill/fill-values-conversion-once.js fails
+built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan.js fails
+built-ins/TypedArray/prototype/fill/fill-values-conversion-operations.js fails
+built-ins/TypedArray/prototype/fill/fill-values-custom-start-and-end.js fails
+built-ins/TypedArray/prototype/fill/fill-values-non-numeric.js fails
+built-ins/TypedArray/prototype/fill/fill-values-relative-end.js fails
+built-ins/TypedArray/prototype/fill/fill-values-relative-start.js fails
+built-ins/TypedArray/prototype/fill/fill-values.js fails
+built-ins/TypedArray/prototype/fill/get-length-ignores-length-prop.js fails
+built-ins/TypedArray/prototype/fill/invoked-as-func.js fails
+built-ins/TypedArray/prototype/fill/invoked-as-method.js fails
+built-ins/TypedArray/prototype/fill/length.js fails
+built-ins/TypedArray/prototype/fill/name.js fails
+built-ins/TypedArray/prototype/fill/prop-desc.js fails
+built-ins/TypedArray/prototype/fill/return-abrupt-from-end.js fails
+built-ins/TypedArray/prototype/fill/return-abrupt-from-set-value.js fails
+built-ins/TypedArray/prototype/fill/return-abrupt-from-start.js fails
+built-ins/TypedArray/prototype/fill/return-this.js fails
+built-ins/TypedArray/prototype/filter/arraylength-internal.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-arguments-with-thisarg.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-arguments-without-thisarg.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-called-before-ctor.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-called-before-species.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-no-iteration-over-non-integer.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-set-value-during-iteration.js fails
+built-ins/TypedArray/prototype/filter/callbackfn-this.js fails
+built-ins/TypedArray/prototype/filter/detached-buffer.js fails
+built-ins/TypedArray/prototype/filter/invoked-as-func.js fails
+built-ins/TypedArray/prototype/filter/invoked-as-method.js fails
+built-ins/TypedArray/prototype/filter/length.js fails
+built-ins/TypedArray/prototype/filter/name.js fails
+built-ins/TypedArray/prototype/filter/prop-desc.js fails
+built-ins/TypedArray/prototype/filter/result-does-not-share-buffer.js fails
+built-ins/TypedArray/prototype/filter/result-empty-callbackfn-returns-false.js fails
+built-ins/TypedArray/prototype/filter/result-full-callbackfn-returns-true.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-ctor-abrupt.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-ctor-inherited.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-ctor.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species-abrupt.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species-custom-ctor-invocation.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species-custom-ctor-length.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species-custom-ctor-returns-another-instance.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species-custom-ctor.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species-use-default-ctor.js fails
+built-ins/TypedArray/prototype/filter/speciesctor-get-species.js fails
+built-ins/TypedArray/prototype/filter/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/filter/values-are-set.js fails
+built-ins/TypedArray/prototype/find/detached-buffer.js fails
+built-ins/TypedArray/prototype/find/get-length-ignores-length-prop.js fails
+built-ins/TypedArray/prototype/find/invoked-as-func.js fails
+built-ins/TypedArray/prototype/find/invoked-as-method.js fails
+built-ins/TypedArray/prototype/find/length.js fails
+built-ins/TypedArray/prototype/find/name.js fails
+built-ins/TypedArray/prototype/find/predicate-call-changes-value.js fails
+built-ins/TypedArray/prototype/find/predicate-call-parameters.js fails
+built-ins/TypedArray/prototype/find/predicate-call-this-non-strict.js sloppyFails
+built-ins/TypedArray/prototype/find/predicate-call-this-strict.js strictFails
+built-ins/TypedArray/prototype/find/predicate-may-detach-buffer.js fails
+built-ins/TypedArray/prototype/find/predicate-not-called-on-empty-array.js fails
+built-ins/TypedArray/prototype/find/prop-desc.js fails
+built-ins/TypedArray/prototype/find/return-abrupt-from-predicate-call.js fails
+built-ins/TypedArray/prototype/find/return-found-value-predicate-result-is-true.js fails
+built-ins/TypedArray/prototype/find/return-undefined-if-predicate-returns-false-value.js fails
+built-ins/TypedArray/prototype/findIndex/detached-buffer.js fails
+built-ins/TypedArray/prototype/findIndex/get-length-ignores-length-prop.js fails
+built-ins/TypedArray/prototype/findIndex/invoked-as-func.js fails
+built-ins/TypedArray/prototype/findIndex/invoked-as-method.js fails
+built-ins/TypedArray/prototype/findIndex/length.js fails
+built-ins/TypedArray/prototype/findIndex/name.js fails
+built-ins/TypedArray/prototype/findIndex/predicate-call-changes-value.js fails
+built-ins/TypedArray/prototype/findIndex/predicate-call-parameters.js fails
+built-ins/TypedArray/prototype/findIndex/predicate-call-this-non-strict.js sloppyFails
+built-ins/TypedArray/prototype/findIndex/predicate-call-this-strict.js strictFails
+built-ins/TypedArray/prototype/findIndex/predicate-may-detach-buffer.js fails
+built-ins/TypedArray/prototype/findIndex/predicate-not-called-on-empty-array.js fails
+built-ins/TypedArray/prototype/findIndex/prop-desc.js fails
+built-ins/TypedArray/prototype/findIndex/return-abrupt-from-predicate-call.js fails
+built-ins/TypedArray/prototype/findIndex/return-index-predicate-result-is-true.js fails
+built-ins/TypedArray/prototype/findIndex/return-negative-one-if-predicate-returns-false-value.js fails
+built-ins/TypedArray/prototype/forEach/arraylength-internal.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-arguments-with-thisarg.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-arguments-without-thisarg.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-no-interaction-over-non-integer.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-set-value-during-interaction.js fails
+built-ins/TypedArray/prototype/forEach/callbackfn-this.js fails
+built-ins/TypedArray/prototype/forEach/detached-buffer.js fails
+built-ins/TypedArray/prototype/forEach/invoked-as-func.js fails
+built-ins/TypedArray/prototype/forEach/invoked-as-method.js fails
+built-ins/TypedArray/prototype/forEach/length.js fails
+built-ins/TypedArray/prototype/forEach/name.js fails
+built-ins/TypedArray/prototype/forEach/prop-desc.js fails
+built-ins/TypedArray/prototype/forEach/returns-undefined.js fails
+built-ins/TypedArray/prototype/forEach/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/includes/detached-buffer.js fails
+built-ins/TypedArray/prototype/includes/fromIndex-equal-or-greater-length-returns-false.js fails
+built-ins/TypedArray/prototype/includes/fromIndex-infinity.js fails
+built-ins/TypedArray/prototype/includes/fromIndex-minus-zero.js fails
+built-ins/TypedArray/prototype/includes/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/includes/invoked-as-func.js fails
+built-ins/TypedArray/prototype/includes/invoked-as-method.js fails
+built-ins/TypedArray/prototype/includes/length-zero-returns-false.js fails
+built-ins/TypedArray/prototype/includes/length.js fails
+built-ins/TypedArray/prototype/includes/name.js fails
+built-ins/TypedArray/prototype/includes/prop-desc.js fails
+built-ins/TypedArray/prototype/includes/return-abrupt-tointeger-fromindex.js fails
+built-ins/TypedArray/prototype/includes/samevaluezero.js fails
+built-ins/TypedArray/prototype/includes/search-found-returns-true.js fails
+built-ins/TypedArray/prototype/includes/search-not-found-returns-false.js fails
+built-ins/TypedArray/prototype/includes/tointeger-fromindex.js fails
+built-ins/TypedArray/prototype/indexOf/detached-buffer.js fails
+built-ins/TypedArray/prototype/indexOf/fromIndex-equal-or-greater-length-returns-minus-one.js fails
+built-ins/TypedArray/prototype/indexOf/fromIndex-infinity.js fails
+built-ins/TypedArray/prototype/indexOf/fromIndex-minus-zero.js fails
+built-ins/TypedArray/prototype/indexOf/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/indexOf/invoked-as-func.js fails
+built-ins/TypedArray/prototype/indexOf/invoked-as-method.js fails
+built-ins/TypedArray/prototype/indexOf/length-zero-returns-minus-one.js fails
+built-ins/TypedArray/prototype/indexOf/length.js fails
+built-ins/TypedArray/prototype/indexOf/name.js fails
+built-ins/TypedArray/prototype/indexOf/prop-desc.js fails
+built-ins/TypedArray/prototype/indexOf/return-abrupt-tointeger-fromindex.js fails
+built-ins/TypedArray/prototype/indexOf/search-found-returns-index.js fails
+built-ins/TypedArray/prototype/indexOf/search-not-found-returns-minus-one.js fails
+built-ins/TypedArray/prototype/indexOf/strict-comparison.js fails
+built-ins/TypedArray/prototype/indexOf/tointeger-fromindex.js fails
+built-ins/TypedArray/prototype/join/custom-separator-result-from-tostring-on-each-simple-value.js fails
+built-ins/TypedArray/prototype/join/custom-separator-result-from-tostring-on-each-value.js fails
+built-ins/TypedArray/prototype/join/detached-buffer.js fails
+built-ins/TypedArray/prototype/join/empty-instance-empty-string.js fails
+built-ins/TypedArray/prototype/join/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/join/invoked-as-func.js fails
+built-ins/TypedArray/prototype/join/invoked-as-method.js fails
+built-ins/TypedArray/prototype/join/length.js fails
+built-ins/TypedArray/prototype/join/name.js fails
+built-ins/TypedArray/prototype/join/prop-desc.js fails
+built-ins/TypedArray/prototype/join/result-from-tostring-on-each-simple-value.js fails
+built-ins/TypedArray/prototype/join/result-from-tostring-on-each-value.js fails
+built-ins/TypedArray/prototype/join/return-abrupt-from-separator.js fails
+built-ins/TypedArray/prototype/keys/detached-buffer.js fails
+built-ins/TypedArray/prototype/lastIndexOf/detached-buffer.js fails
+built-ins/TypedArray/prototype/lastIndexOf/fromIndex-infinity.js fails
+built-ins/TypedArray/prototype/lastIndexOf/fromIndex-minus-zero.js fails
+built-ins/TypedArray/prototype/lastIndexOf/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/lastIndexOf/invoked-as-func.js fails
+built-ins/TypedArray/prototype/lastIndexOf/invoked-as-method.js fails
+built-ins/TypedArray/prototype/lastIndexOf/length-zero-returns-minus-one.js fails
+built-ins/TypedArray/prototype/lastIndexOf/length.js fails
+built-ins/TypedArray/prototype/lastIndexOf/name.js fails
+built-ins/TypedArray/prototype/lastIndexOf/prop-desc.js fails
+built-ins/TypedArray/prototype/lastIndexOf/return-abrupt-tointeger-fromindex.js fails
+built-ins/TypedArray/prototype/lastIndexOf/search-found-returns-index.js fails
+built-ins/TypedArray/prototype/lastIndexOf/search-not-found-returns-minus-one.js fails
+built-ins/TypedArray/prototype/lastIndexOf/strict-comparison.js fails
+built-ins/TypedArray/prototype/lastIndexOf/tointeger-fromindex.js fails
+built-ins/TypedArray/prototype/length/detached-buffer.js fails
+built-ins/TypedArray/prototype/map/arraylength-internal.js fails
+built-ins/TypedArray/prototype/map/callbackfn-arguments-with-thisarg.js fails
+built-ins/TypedArray/prototype/map/callbackfn-arguments-without-thisarg.js fails
+built-ins/TypedArray/prototype/map/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/map/callbackfn-no-interaction-over-non-integer-properties.js fails
+built-ins/TypedArray/prototype/map/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/map/callbackfn-return-affects-returned-object.js fails
+built-ins/TypedArray/prototype/map/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/map/callbackfn-return-does-not-copy-non-integer-properties.js fails
+built-ins/TypedArray/prototype/map/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/map/callbackfn-set-value-during-interaction.js fails
+built-ins/TypedArray/prototype/map/callbackfn-this.js fails
+built-ins/TypedArray/prototype/map/detached-buffer.js fails
+built-ins/TypedArray/prototype/map/invoked-as-func.js fails
+built-ins/TypedArray/prototype/map/invoked-as-method.js fails
+built-ins/TypedArray/prototype/map/length.js fails
+built-ins/TypedArray/prototype/map/name.js fails
+built-ins/TypedArray/prototype/map/prop-desc.js fails
+built-ins/TypedArray/prototype/map/return-new-typedarray-conversion-operation-consistent-nan.js fails
+built-ins/TypedArray/prototype/map/return-new-typedarray-conversion-operation.js fails
+built-ins/TypedArray/prototype/map/return-new-typedarray-from-empty-length.js fails
+built-ins/TypedArray/prototype/map/return-new-typedarray-from-positive-length.js fails
+built-ins/TypedArray/prototype/map/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-arguments-custom-accumulator.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-arguments-default-accumulator.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-no-iteration-over-non-integer-properties.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-set-value-during-iteration.js fails
+built-ins/TypedArray/prototype/reduce/callbackfn-this.js fails
+built-ins/TypedArray/prototype/reduce/detached-buffer.js fails
+built-ins/TypedArray/prototype/reduce/empty-instance-return-initialvalue.js fails
+built-ins/TypedArray/prototype/reduce/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/reduce/invoked-as-func.js fails
+built-ins/TypedArray/prototype/reduce/invoked-as-method.js fails
+built-ins/TypedArray/prototype/reduce/length.js fails
+built-ins/TypedArray/prototype/reduce/name.js fails
+built-ins/TypedArray/prototype/reduce/prop-desc.js fails
+built-ins/TypedArray/prototype/reduce/result-is-last-callbackfn-return.js fails
+built-ins/TypedArray/prototype/reduce/result-of-any-type.js fails
+built-ins/TypedArray/prototype/reduce/return-first-value-without-callbackfn.js fails
+built-ins/TypedArray/prototype/reduce/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-arguments-custom-accumulator.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-arguments-default-accumulator.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-no-iteration-over-non-integer-properties.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-set-value-during-iteration.js fails
+built-ins/TypedArray/prototype/reduceRight/callbackfn-this.js fails
+built-ins/TypedArray/prototype/reduceRight/detached-buffer.js fails
+built-ins/TypedArray/prototype/reduceRight/empty-instance-return-initialvalue.js fails
+built-ins/TypedArray/prototype/reduceRight/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/reduceRight/invoked-as-func.js fails
+built-ins/TypedArray/prototype/reduceRight/invoked-as-method.js fails
+built-ins/TypedArray/prototype/reduceRight/length.js fails
+built-ins/TypedArray/prototype/reduceRight/name.js fails
+built-ins/TypedArray/prototype/reduceRight/prop-desc.js fails
+built-ins/TypedArray/prototype/reduceRight/result-is-last-callbackfn-return.js fails
+built-ins/TypedArray/prototype/reduceRight/result-of-any-type.js fails
+built-ins/TypedArray/prototype/reduceRight/return-first-value-without-callbackfn.js fails
+built-ins/TypedArray/prototype/reduceRight/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/reverse/detached-buffer.js fails
+built-ins/TypedArray/prototype/reverse/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/reverse/invoked-as-func.js fails
+built-ins/TypedArray/prototype/reverse/invoked-as-method.js fails
+built-ins/TypedArray/prototype/reverse/length.js fails
+built-ins/TypedArray/prototype/reverse/name.js fails
+built-ins/TypedArray/prototype/reverse/preserves-non-numeric-properties.js fails
+built-ins/TypedArray/prototype/reverse/prop-desc.js fails
+built-ins/TypedArray/prototype/reverse/returns-original-object.js fails
+built-ins/TypedArray/prototype/reverse/reverts.js fails
+built-ins/TypedArray/prototype/set/array-arg-set-values-in-order.js fails
+built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js fails
+built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-tointeger-offset-throws.js fails
+built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-throws.js fails
+built-ins/TypedArray/prototype/set/typedarray-arg-srcbuffer-detached-during-tointeger-offset-throws.js fails
+built-ins/TypedArray/prototype/set/typedarray-arg-targetbuffer-detached-during-tointeger-offset-throws.js fails
+built-ins/TypedArray/prototype/slice/arraylength-internal.js fails
+built-ins/TypedArray/prototype/slice/bit-precision.js fails
+built-ins/TypedArray/prototype/slice/detached-buffer-zero-count-custom-ctor-other-targettype.js fails
+built-ins/TypedArray/prototype/slice/detached-buffer-zero-count-custom-ctor-same-targettype.js fails
+built-ins/TypedArray/prototype/slice/detached-buffer.js fails
+built-ins/TypedArray/prototype/slice/infinity.js fails
+built-ins/TypedArray/prototype/slice/invoked-as-func.js fails
+built-ins/TypedArray/prototype/slice/invoked-as-method.js fails
+built-ins/TypedArray/prototype/slice/length.js fails
+built-ins/TypedArray/prototype/slice/minus-zero.js fails
+built-ins/TypedArray/prototype/slice/name.js fails
+built-ins/TypedArray/prototype/slice/prop-desc.js fails
+built-ins/TypedArray/prototype/slice/result-does-not-copy-ordinary-properties.js fails
+built-ins/TypedArray/prototype/slice/results-with-different-length.js fails
+built-ins/TypedArray/prototype/slice/results-with-empty-length.js fails
+built-ins/TypedArray/prototype/slice/results-with-same-length.js fails
+built-ins/TypedArray/prototype/slice/return-abrupt-from-end.js fails
+built-ins/TypedArray/prototype/slice/return-abrupt-from-start.js fails
+built-ins/TypedArray/prototype/slice/set-values-from-different-ctor-type.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-ctor-abrupt.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-ctor-inherited.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-ctor.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species-abrupt.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species-custom-ctor-invocation.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species-custom-ctor-length.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species-custom-ctor-returns-another-instance.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species-custom-ctor.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species-use-default-ctor.js fails
+built-ins/TypedArray/prototype/slice/speciesctor-get-species.js fails
+built-ins/TypedArray/prototype/slice/tointeger-end.js fails
+built-ins/TypedArray/prototype/slice/tointeger-start.js fails
+built-ins/TypedArray/prototype/some/callbackfn-arguments-with-thisarg.js fails
+built-ins/TypedArray/prototype/some/callbackfn-arguments-without-thisarg.js fails
+built-ins/TypedArray/prototype/some/callbackfn-detachbuffer.js fails
+built-ins/TypedArray/prototype/some/callbackfn-no-interaction-over-non-integer.js fails
+built-ins/TypedArray/prototype/some/callbackfn-not-called-on-empty.js fails
+built-ins/TypedArray/prototype/some/callbackfn-return-does-not-change-instance.js fails
+built-ins/TypedArray/prototype/some/callbackfn-returns-abrupt.js fails
+built-ins/TypedArray/prototype/some/callbackfn-set-value-during-interaction.js fails
+built-ins/TypedArray/prototype/some/callbackfn-this.js fails
+built-ins/TypedArray/prototype/some/detached-buffer.js fails
+built-ins/TypedArray/prototype/some/get-length-uses-internal-arraylength.js fails
+built-ins/TypedArray/prototype/some/invoked-as-func.js fails
+built-ins/TypedArray/prototype/some/invoked-as-method.js fails
+built-ins/TypedArray/prototype/some/length.js fails
+built-ins/TypedArray/prototype/some/name.js fails
+built-ins/TypedArray/prototype/some/prop-desc.js fails
+built-ins/TypedArray/prototype/some/returns-false-if-every-cb-returns-false.js fails
+built-ins/TypedArray/prototype/some/returns-true-if-any-cb-returns-true.js fails
+built-ins/TypedArray/prototype/some/values-are-not-cached.js fails
+built-ins/TypedArray/prototype/sort/arraylength-internal.js fails
+built-ins/TypedArray/prototype/sort/comparefn-call-throws.js fails
+built-ins/TypedArray/prototype/sort/comparefn-calls.js fails
+built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js fails
+built-ins/TypedArray/prototype/sort/detached-buffer.js fails
+built-ins/TypedArray/prototype/sort/invoked-as-func.js fails
+built-ins/TypedArray/prototype/sort/invoked-as-method.js fails
+built-ins/TypedArray/prototype/sort/length.js fails
+built-ins/TypedArray/prototype/sort/name.js fails
+built-ins/TypedArray/prototype/sort/prop-desc.js fails
+built-ins/TypedArray/prototype/sort/return-same-instance.js fails
+built-ins/TypedArray/prototype/sort/sortcompare-with-no-tostring.js fails
+built-ins/TypedArray/prototype/sort/sorted-values-nan.js fails
+built-ins/TypedArray/prototype/sort/sorted-values.js fails
+built-ins/TypedArray/prototype/subarray/detached-buffer.js fails
+built-ins/TypedArray/prototype/subarray/length.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-inherited.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-species-abrupt.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-returns-another-instance.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-species-use-default-ctor.js fails
+built-ins/TypedArray/prototype/subarray/speciesctor-get-species.js fails
+built-ins/TypedArray/prototype/toLocaleString/calls-tolocalestring-from-each-value.js fails
+built-ins/TypedArray/prototype/toLocaleString/calls-tostring-from-each-value.js fails
+built-ins/TypedArray/prototype/toLocaleString/calls-valueof-from-each-value.js fails
+built-ins/TypedArray/prototype/toLocaleString/detached-buffer.js fails
+built-ins/TypedArray/prototype/toLocaleString/empty-instance-returns-empty-string.js fails
+built-ins/TypedArray/prototype/toLocaleString/invoked-as-method.js fails
+built-ins/TypedArray/prototype/toLocaleString/prop-desc.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-firstelement-tolocalestring.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-firstelement-tostring.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-firstelement-valueof.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-nextelement-tolocalestring.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-nextelement-tostring.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-nextelement-valueof.js fails
+built-ins/TypedArray/prototype/toLocaleString/return-result.js fails
+built-ins/TypedArray/prototype/toLocaleString/this-is-not-object.js fails
+built-ins/TypedArray/prototype/toLocaleString/this-is-not-typedarray-instance.js fails
+built-ins/TypedArray/prototype/toString.js fails
+built-ins/TypedArray/prototype/toString/detached-buffer.js fails
+built-ins/TypedArray/prototype/values/detached-buffer.js fails
+built-ins/TypedArrays/ctors/buffer-arg/byteoffset-to-number-detachbuffer.js fails
+built-ins/TypedArrays/ctors/buffer-arg/custom-proto-access-throws.js fails
+built-ins/TypedArrays/ctors/buffer-arg/defined-negative-length.js fails
+built-ins/TypedArrays/ctors/buffer-arg/detachedbuffer.js fails
+built-ins/TypedArrays/ctors/buffer-arg/length-to-number-detachbuffer.js fails
+built-ins/TypedArrays/ctors/buffer-arg/proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/buffer-arg/use-custom-proto-if-object.js fails
+built-ins/TypedArrays/ctors/length-arg/custom-proto-access-throws.js fails
+built-ins/TypedArrays/ctors/length-arg/proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/length-arg/use-custom-proto-if-object.js fails
+built-ins/TypedArrays/ctors/no-args/custom-proto-access-throws.js fails
+built-ins/TypedArrays/ctors/no-args/proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/no-args/use-custom-proto-if-object.js fails
+built-ins/TypedArrays/ctors/object-arg/as-generator-iterable-returns.js fails
+built-ins/TypedArrays/ctors/object-arg/custom-proto-access-throws.js fails
+built-ins/TypedArrays/ctors/object-arg/iterator-not-callable-throws.js fails
+built-ins/TypedArrays/ctors/object-arg/proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/object-arg/use-custom-proto-if-object.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/custom-proto-access-throws.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js fails
+built-ins/TypedArrays/ctors/typedarray-arg/use-custom-proto-if-object.js fails
+built-ins/TypedArrays/from/arylk-get-length-error.js fails
+built-ins/TypedArrays/from/arylk-to-length-error.js fails
+built-ins/TypedArrays/from/custom-ctor-returns-other-instance.js fails
+built-ins/TypedArrays/from/custom-ctor.js fails
+built-ins/TypedArrays/from/iter-access-error.js fails
+built-ins/TypedArrays/from/iter-invoke-error.js fails
+built-ins/TypedArrays/from/iter-next-error.js fails
+built-ins/TypedArrays/from/iter-next-value-error.js fails
+built-ins/TypedArrays/from/mapfn-abrupt-completion.js fails
+built-ins/TypedArrays/from/mapfn-arguments.js fails
+built-ins/TypedArrays/from/mapfn-this-with-thisarg.js fails
+built-ins/TypedArrays/from/mapfn-this-without-thisarg-non-strict.js sloppyFails
+built-ins/TypedArrays/from/mapfn-this-without-thisarg-strict.js strictFails
+built-ins/TypedArrays/from/nan-conversion.js fails
+built-ins/TypedArrays/from/new-instance-empty.js fails
+built-ins/TypedArrays/from/new-instance-from-ordinary-object.js fails
+built-ins/TypedArrays/from/new-instance-from-sparse-array.js fails
+built-ins/TypedArrays/from/new-instance-from-zero.js fails
+built-ins/TypedArrays/from/new-instance-using-custom-ctor.js fails
+built-ins/TypedArrays/from/new-instance-with-mapfn.js fails
+built-ins/TypedArrays/from/new-instance-without-mapfn.js fails
+built-ins/TypedArrays/from/property-abrupt-completion.js fails
+built-ins/TypedArrays/from/set-value-abrupt-completion.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/conversion-operation-consistent-nan.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/conversion-operation.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/detached-buffer-realm.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/detached-buffer.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-greater-than-last-index.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-lower-than-zero.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-minus-zero.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-not-integer.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-accessor-desc.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-configurable.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-not-enumerable.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-not-writable.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/set-value.js fails
+built-ins/TypedArrays/internals/DefineOwnProperty/tonumber-value-detached-buffer.js fails
+built-ins/TypedArrays/internals/Get/detached-buffer-key-is-not-numeric-index.js fails
+built-ins/TypedArrays/internals/Get/detached-buffer-key-is-symbol.js fails
+built-ins/TypedArrays/internals/Get/detached-buffer-realm.js fails
+built-ins/TypedArrays/internals/Get/detached-buffer.js fails
+built-ins/TypedArrays/internals/Get/infinity-detached-buffer.js fails
+built-ins/TypedArrays/internals/Get/key-is-not-integer.js fails
+built-ins/TypedArrays/internals/Get/key-is-not-minus-zero.js fails
+built-ins/TypedArrays/internals/Get/key-is-out-of-bounds.js fails
+built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer-key-is-not-number.js fails
+built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer-key-is-symbol.js fails
+built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer-realm.js fails
+built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer.js fails
+built-ins/TypedArrays/internals/GetOwnProperty/enumerate-detached-buffer.js fails
+built-ins/TypedArrays/internals/GetOwnProperty/index-prop-desc.js fails
+built-ins/TypedArrays/internals/HasProperty/detached-buffer-key-is-not-number.js fails
+built-ins/TypedArrays/internals/HasProperty/detached-buffer-key-is-symbol.js fails
+built-ins/TypedArrays/internals/HasProperty/detached-buffer-realm.js fails
+built-ins/TypedArrays/internals/HasProperty/detached-buffer.js fails
+built-ins/TypedArrays/internals/HasProperty/infinity-with-detached-buffer.js sloppyFails
+built-ins/TypedArrays/internals/HasProperty/key-is-lower-than-zero.js fails
+built-ins/TypedArrays/internals/HasProperty/key-is-minus-zero.js fails
+built-ins/TypedArrays/internals/HasProperty/key-is-not-integer.js fails
+built-ins/TypedArrays/internals/OwnPropertyKeys/integer-indexes-and-string-and-symbol-keys-.js fails
+built-ins/TypedArrays/internals/OwnPropertyKeys/integer-indexes-and-string-keys.js fails
+built-ins/TypedArrays/internals/OwnPropertyKeys/integer-indexes.js fails
+built-ins/TypedArrays/internals/OwnPropertyKeys/not-enumerable-keys.js fails
+built-ins/TypedArrays/internals/Set/detached-buffer-key-is-not-numeric-index.js fails
+built-ins/TypedArrays/internals/Set/detached-buffer-key-is-symbol.js fails
+built-ins/TypedArrays/internals/Set/detached-buffer-realm.js fails
+built-ins/TypedArrays/internals/Set/detached-buffer.js fails
+built-ins/TypedArrays/internals/Set/key-is-minus-zero.js fails
+built-ins/TypedArrays/internals/Set/key-is-not-integer.js fails
+built-ins/TypedArrays/internals/Set/key-is-out-of-bounds.js fails
+built-ins/TypedArrays/internals/Set/tonumber-value-detached-buffer.js fails
+built-ins/TypedArrays/internals/Set/tonumber-value-throws.js strictFails
+built-ins/TypedArrays/of/argument-number-value-throws.js fails
+built-ins/TypedArrays/of/custom-ctor-returns-other-instance.js fails
+built-ins/TypedArrays/of/custom-ctor.js fails
+built-ins/TypedArrays/of/nan-conversion.js fails
+built-ins/TypedArrays/of/new-instance-empty.js fails
+built-ins/TypedArrays/of/new-instance-from-zero.js fails
+built-ins/TypedArrays/of/new-instance-using-custom-ctor.js fails
+built-ins/TypedArrays/of/new-instance.js fails
+built-ins/WeakMap/constructor.js fails
+built-ins/WeakMap/empty-iterable.js fails
+built-ins/WeakMap/get-set-method-failure.js fails
+built-ins/WeakMap/iterable-failure.js fails
+built-ins/WeakMap/iterable.js fails
+built-ins/WeakMap/iterator-close-after-set-failure.js fails
+built-ins/WeakMap/iterator-item-first-entry-returns-abrupt.js fails
+built-ins/WeakMap/iterator-item-second-entry-returns-abrupt.js fails
+built-ins/WeakMap/iterator-items-are-not-object-close-iterator.js fails
+built-ins/WeakMap/iterator-items-are-not-object.js fails
+built-ins/WeakMap/iterator-next-failure.js fails
+built-ins/WeakMap/iterator-value-failure.js fails
+built-ins/WeakMap/length.js fails
+built-ins/WeakMap/name.js fails
+built-ins/WeakMap/no-iterable.js fails
+built-ins/WeakMap/properties-of-map-instances.js fails
+built-ins/WeakMap/properties-of-the-weakmap-prototype-object.js fails
+built-ins/WeakMap/proto-from-ctor-realm.js fails
+built-ins/WeakMap/prototype-of-weakmap.js fails
+built-ins/WeakMap/prototype/Symbol.toStringTag.js fails
+built-ins/WeakMap/prototype/constructor.js fails
+built-ins/WeakMap/prototype/delete/delete-entry-initial-iterable.js fails
+built-ins/WeakMap/prototype/delete/delete-entry.js fails
+built-ins/WeakMap/prototype/delete/delete.js fails
+built-ins/WeakMap/prototype/delete/does-not-have-weakmapdata-internal-slot-array.js fails
+built-ins/WeakMap/prototype/delete/does-not-have-weakmapdata-internal-slot-map.js fails
+built-ins/WeakMap/prototype/delete/does-not-have-weakmapdata-internal-slot-object.js fails
+built-ins/WeakMap/prototype/delete/does-not-have-weakmapdata-internal-slot-set.js fails
+built-ins/WeakMap/prototype/delete/does-not-have-weakmapdata-internal-slot-weakmap-prototype.js fails
+built-ins/WeakMap/prototype/delete/length.js fails
+built-ins/WeakMap/prototype/delete/name.js fails
+built-ins/WeakMap/prototype/delete/returns-false-value-is-not-object.js fails
+built-ins/WeakMap/prototype/delete/returns-false-when-delete-is-noop.js fails
+built-ins/WeakMap/prototype/delete/this-not-object-throw-boolean.js fails
+built-ins/WeakMap/prototype/delete/this-not-object-throw-null.js fails
+built-ins/WeakMap/prototype/delete/this-not-object-throw-number.js fails
+built-ins/WeakMap/prototype/delete/this-not-object-throw-string.js fails
+built-ins/WeakMap/prototype/delete/this-not-object-throw-symbol.js fails
+built-ins/WeakMap/prototype/delete/this-not-object-throw-undefined.js fails
+built-ins/WeakMap/prototype/get/does-not-have-weakmapdata-internal-slot-map.js fails
+built-ins/WeakMap/prototype/get/does-not-have-weakmapdata-internal-slot-set.js fails
+built-ins/WeakMap/prototype/get/does-not-have-weakmapdata-internal-slot.js fails
+built-ins/WeakMap/prototype/get/get.js fails
+built-ins/WeakMap/prototype/get/length.js fails
+built-ins/WeakMap/prototype/get/name.js fails
+built-ins/WeakMap/prototype/get/returns-undefined-key-is-not-object.js fails
+built-ins/WeakMap/prototype/get/returns-undefined.js fails
+built-ins/WeakMap/prototype/get/returns-value.js fails
+built-ins/WeakMap/prototype/get/this-not-object-throw.js fails
+built-ins/WeakMap/prototype/has/does-not-have-weakmapdata-internal-slot-array.js fails
+built-ins/WeakMap/prototype/has/does-not-have-weakmapdata-internal-slot-map.js fails
+built-ins/WeakMap/prototype/has/does-not-have-weakmapdata-internal-slot-object.js fails
+built-ins/WeakMap/prototype/has/does-not-have-weakmapdata-internal-slot-set.js fails
+built-ins/WeakMap/prototype/has/does-not-have-weakmapdata-internal-slot-weakmap-prototype.js fails
+built-ins/WeakMap/prototype/has/has.js fails
+built-ins/WeakMap/prototype/has/length.js fails
+built-ins/WeakMap/prototype/has/name.js fails
+built-ins/WeakMap/prototype/has/returns-false-when-value-is-not-object.js fails
+built-ins/WeakMap/prototype/has/returns-false-when-value-not-present.js fails
+built-ins/WeakMap/prototype/has/returns-true-when-value-present.js fails
+built-ins/WeakMap/prototype/has/this-not-object-throw-boolean.js fails
+built-ins/WeakMap/prototype/has/this-not-object-throw-null.js fails
+built-ins/WeakMap/prototype/has/this-not-object-throw-number.js fails
+built-ins/WeakMap/prototype/has/this-not-object-throw-string.js fails
+built-ins/WeakMap/prototype/has/this-not-object-throw-symbol.js fails
+built-ins/WeakMap/prototype/has/this-not-object-throw-undefined.js fails
+built-ins/WeakMap/prototype/prototype-attributes.js fails
+built-ins/WeakMap/prototype/set/adds-element.js fails
+built-ins/WeakMap/prototype/set/does-not-have-weakmapdata-internal-slot-array.js fails
+built-ins/WeakMap/prototype/set/does-not-have-weakmapdata-internal-slot-map.js fails
+built-ins/WeakMap/prototype/set/does-not-have-weakmapdata-internal-slot-object.js fails
+built-ins/WeakMap/prototype/set/does-not-have-weakmapdata-internal-slot-set.js fails
+built-ins/WeakMap/prototype/set/does-not-have-weakmapdata-internal-slot-weakmap-prototype.js fails
+built-ins/WeakMap/prototype/set/key-not-object-throw.js fails
+built-ins/WeakMap/prototype/set/length.js fails
+built-ins/WeakMap/prototype/set/name.js fails
+built-ins/WeakMap/prototype/set/returns-this-when-ignoring-duplicate.js fails
+built-ins/WeakMap/prototype/set/returns-this.js fails
+built-ins/WeakMap/prototype/set/set.js fails
+built-ins/WeakMap/prototype/set/this-not-object-throw-boolean.js fails
+built-ins/WeakMap/prototype/set/this-not-object-throw-null.js fails
+built-ins/WeakMap/prototype/set/this-not-object-throw-number.js fails
+built-ins/WeakMap/prototype/set/this-not-object-throw-string.js fails
+built-ins/WeakMap/prototype/set/this-not-object-throw-symbol.js fails
+built-ins/WeakMap/prototype/set/this-not-object-throw-undefined.js fails
+built-ins/WeakMap/set-not-callable-throws.js fails
+built-ins/WeakMap/undefined-newtarget.js fails
+built-ins/WeakMap/weakmap.js fails
+built-ins/WeakSet/add-not-callable-throws.js fails
+built-ins/WeakSet/constructor.js fails
+built-ins/WeakSet/empty-iterable.js fails
+built-ins/WeakSet/get-add-method-failure.js fails
+built-ins/WeakSet/iterable-failure.js fails
+built-ins/WeakSet/iterable.js fails
+built-ins/WeakSet/iterator-close-after-add-failure.js fails
+built-ins/WeakSet/iterator-next-failure.js fails
+built-ins/WeakSet/iterator-value-failure.js fails
+built-ins/WeakSet/length.js fails
+built-ins/WeakSet/name.js fails
+built-ins/WeakSet/no-iterable.js fails
+built-ins/WeakSet/properties-of-the-weakset-prototype-object.js fails
+built-ins/WeakSet/proto-from-ctor-realm.js fails
+built-ins/WeakSet/prototype-of-weakset.js fails
+built-ins/WeakSet/prototype/Symbol.toStringTag.js fails
+built-ins/WeakSet/prototype/add/add.js fails
+built-ins/WeakSet/prototype/add/adds-element.js fails
+built-ins/WeakSet/prototype/add/does-not-have-weaksetdata-internal-slot-array.js fails
+built-ins/WeakSet/prototype/add/does-not-have-weaksetdata-internal-slot-map.js fails
+built-ins/WeakSet/prototype/add/does-not-have-weaksetdata-internal-slot-object.js fails
+built-ins/WeakSet/prototype/add/does-not-have-weaksetdata-internal-slot-set.js fails
+built-ins/WeakSet/prototype/add/does-not-have-weaksetdata-internal-slot-weakset-prototype.js fails
+built-ins/WeakSet/prototype/add/length.js fails
+built-ins/WeakSet/prototype/add/name.js fails
+built-ins/WeakSet/prototype/add/returns-this-when-ignoring-duplicate.js fails
+built-ins/WeakSet/prototype/add/returns-this.js fails
+built-ins/WeakSet/prototype/add/this-not-object-throw-boolean.js fails
+built-ins/WeakSet/prototype/add/this-not-object-throw-null.js fails
+built-ins/WeakSet/prototype/add/this-not-object-throw-number.js fails
+built-ins/WeakSet/prototype/add/this-not-object-throw-string.js fails
+built-ins/WeakSet/prototype/add/this-not-object-throw-symbol.js fails
+built-ins/WeakSet/prototype/add/this-not-object-throw-undefined.js fails
+built-ins/WeakSet/prototype/add/value-not-object-throw.js fails
+built-ins/WeakSet/prototype/constructor/weakset-prototype-constructor-intrinsic.js fails
+built-ins/WeakSet/prototype/constructor/weakset-prototype-constructor.js fails
+built-ins/WeakSet/prototype/delete/delete-entry-initial-iterable.js fails
+built-ins/WeakSet/prototype/delete/delete-entry.js fails
+built-ins/WeakSet/prototype/delete/delete.js fails
+built-ins/WeakSet/prototype/delete/does-not-have-weaksetdata-internal-slot-array.js fails
+built-ins/WeakSet/prototype/delete/does-not-have-weaksetdata-internal-slot-map.js fails
+built-ins/WeakSet/prototype/delete/does-not-have-weaksetdata-internal-slot-object.js fails
+built-ins/WeakSet/prototype/delete/does-not-have-weaksetdata-internal-slot-set.js fails
+built-ins/WeakSet/prototype/delete/does-not-have-weaksetdata-internal-slot-weakset-prototype.js fails
+built-ins/WeakSet/prototype/delete/length.js fails
+built-ins/WeakSet/prototype/delete/name.js fails
+built-ins/WeakSet/prototype/delete/returns-false-value-is-not-object.js fails
+built-ins/WeakSet/prototype/delete/returns-false-when-delete-is-noop.js fails
+built-ins/WeakSet/prototype/delete/this-not-object-throw-boolean.js fails
+built-ins/WeakSet/prototype/delete/this-not-object-throw-null.js fails
+built-ins/WeakSet/prototype/delete/this-not-object-throw-number.js fails
+built-ins/WeakSet/prototype/delete/this-not-object-throw-string.js fails
+built-ins/WeakSet/prototype/delete/this-not-object-throw-symbol.js fails
+built-ins/WeakSet/prototype/delete/this-not-object-throw-undefined.js fails
+built-ins/WeakSet/prototype/has/does-not-have-weaksetdata-internal-slot-array.js fails
+built-ins/WeakSet/prototype/has/does-not-have-weaksetdata-internal-slot-map.js fails
+built-ins/WeakSet/prototype/has/does-not-have-weaksetdata-internal-slot-object.js fails
+built-ins/WeakSet/prototype/has/does-not-have-weaksetdata-internal-slot-set.js fails
+built-ins/WeakSet/prototype/has/does-not-have-weaksetdata-internal-slot-weakset-prototype.js fails
+built-ins/WeakSet/prototype/has/has.js fails
+built-ins/WeakSet/prototype/has/length.js fails
+built-ins/WeakSet/prototype/has/name.js fails
+built-ins/WeakSet/prototype/has/returns-false-when-value-is-not-object.js fails
+built-ins/WeakSet/prototype/has/returns-false-when-value-not-present.js fails
+built-ins/WeakSet/prototype/has/returns-true-when-value-present.js fails
+built-ins/WeakSet/prototype/has/this-not-object-throw-boolean.js fails
+built-ins/WeakSet/prototype/has/this-not-object-throw-null.js fails
+built-ins/WeakSet/prototype/has/this-not-object-throw-number.js fails
+built-ins/WeakSet/prototype/has/this-not-object-throw-string.js fails
+built-ins/WeakSet/prototype/has/this-not-object-throw-symbol.js fails
+built-ins/WeakSet/prototype/has/this-not-object-throw-undefined.js fails
+built-ins/WeakSet/prototype/prototype-attributes.js fails
+built-ins/WeakSet/symbol-disallowed-as-weakset-key.js fails
+built-ins/WeakSet/undefined-newtarget.js fails
+built-ins/WeakSet/weakset.js fails
+built-ins/global/global-object.js fails
+built-ins/global/property-descriptor.js fails
+built-ins/isFinite/toprimitive-not-callable-throws.js fails
+built-ins/isNaN/toprimitive-not-callable-throws.js fails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-2.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-3.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-4.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-2.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-3.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-4.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-1.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-3.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-4.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-5.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-2.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-3.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-4.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonwritable-nonconfigurable-1.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonwritable-nonconfigurable-3.js sloppyFails
+language/arguments-object/mapped/mapped-arguments-nonwritable-nonconfigurable-4.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-descriptors-set-value-by-arguments.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-descriptors-set-value-with-define-property.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-descriptors-with-param-assign.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-arguments.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-param.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-nonwritable-descriptors-set-by-arguments.js sloppyFails
+language/arguments-object/mapped/nonconfigurable-nonwritable-descriptors-set-by-param.js sloppyFails
+language/arguments-object/mapped/nonwritable-nonconfigurable-descriptors-set-by-arguments.js sloppyFails
+language/computed-property-names/class/static/generator-prototype.js fails
+language/computed-property-names/class/static/getter-prototype.js fails
+language/computed-property-names/class/static/method-prototype.js fails
+language/computed-property-names/class/static/method-number.js fails
+language/computed-property-names/class/static/method-string.js fails
+language/computed-property-names/class/static/method-symbol.js fails
+language/computed-property-names/class/static/setter-prototype.js fails
+language/eval-code/direct/lex-env-no-init-cls.js fails
+language/eval-code/direct/lex-env-no-init-const.js fails
+language/eval-code/direct/lex-env-no-init-let.js fails
+language/eval-code/direct/new.target.js fails
+language/eval-code/direct/new.target-arrow.js fails
+language/eval-code/direct/new.target-fn.js fails
+language/eval-code/direct/non-definable-function-with-function.js sloppyFails
+language/eval-code/direct/non-definable-function-with-variable.js sloppyFails
+language/eval-code/direct/non-definable-global-function.js sloppyFails
+language/eval-code/direct/non-definable-global-generator.js sloppyFails
+language/eval-code/direct/super-call-arrow.js fails
+language/eval-code/direct/super-call-fn.js fails
+language/eval-code/direct/super-call-method.js fails
+language/eval-code/direct/super-call.js fails
+language/eval-code/direct/super-prop-arrow.js fails
+language/eval-code/direct/super-prop-dot-no-home.js fails
+language/eval-code/direct/super-prop-expr-no-home-no-eval.js fails
+language/eval-code/direct/super-prop-expr-no-home.js fails
+language/eval-code/direct/super-prop.js fails
+language/eval-code/direct/this-value-func-strict-source.js sloppyFails
+language/eval-code/direct/var-env-func-init-global-update-configurable.js sloppyFails
+language/eval-code/direct/var-env-global-lex-non-strict.js sloppyFails
+language/eval-code/direct/var-env-lower-lex-catch-non-strict.js sloppyFails
+language/eval-code/direct/var-env-lower-lex-non-strict.js sloppyFails
+language/eval-code/indirect/always-non-strict.js strictFails
+language/eval-code/indirect/lex-env-no-init-cls.js fails
+language/eval-code/indirect/lex-env-no-init-const.js fails
+language/eval-code/indirect/lex-env-no-init-let.js fails
+language/eval-code/indirect/new.target.js fails
+language/eval-code/indirect/non-definable-function-with-function.js sloppyFails
+language/eval-code/indirect/non-definable-function-with-variable.js sloppyFails
+language/eval-code/indirect/non-definable-global-function.js fails
+language/eval-code/indirect/non-definable-global-generator.js fails
+language/eval-code/indirect/realm.js fails
+language/eval-code/indirect/super-call.js fails
+language/eval-code/indirect/super-prop.js fails
+language/eval-code/indirect/this-value-func.js strictFails
+language/eval-code/indirect/var-env-func-init-global-new.js strictFails
+language/eval-code/indirect/var-env-func-init-global-update-configurable.js fails
+language/eval-code/indirect/var-env-func-init-multi.js strictFails
+language/eval-code/indirect/var-env-func-non-strict.js strictFails
+language/eval-code/indirect/var-env-global-lex-non-strict.js fails
+language/eval-code/indirect/var-env-var-init-global-exstng.js strictFails
+language/eval-code/indirect/var-env-var-init-global-new.js strictFails
+language/eval-code/indirect/var-env-var-non-strict.js strictFails
+language/expressions/arrow-function/cannot-override-this-with-thisArg.js fails
+language/expressions/arrow-function/dflt-params-ref-later.js fails
+language/expressions/arrow-function/dflt-params-ref-self.js fails
+language/expressions/arrow-function/lexical-arguments.js fails
+language/expressions/arrow-function/lexical-new.target-closure-returned.js fails
+language/expressions/arrow-function/lexical-new.target.js fails
+language/expressions/arrow-function/lexical-super-call-from-within-constructor.js fails
+language/expressions/arrow-function/lexical-super-property-from-within-constructor.js fails
+language/expressions/arrow-function/lexical-super-property.js fails
+language/expressions/arrow-function/lexical-supercall-from-immediately-invoked-arrow.js fails
+language/expressions/arrow-function/lexical-this.js fails
+language/expressions/arrow-function/prototype-rules.js fails
+language/expressions/arrow-function/scope-body-lex-distinct.js sloppyFails
+language/expressions/arrow-function/scope-param-elem-var-close.js sloppyFails
+language/expressions/arrow-function/scope-param-elem-var-open.js sloppyFails
+language/expressions/arrow-function/scope-param-rest-elem-var-close.js sloppyFails
+language/expressions/arrow-function/scope-param-rest-elem-var-open.js sloppyFails
+language/expressions/arrow-function/scope-paramsbody-var-open.js fails
+language/expressions/arrow-function/throw-new.js fails
+language/expressions/assignment/S11.13.1_A5_T1.js sloppyFails
+language/expressions/assignment/S11.13.1_A5_T2.js sloppyFails
+language/expressions/assignment/S11.13.1_A5_T3.js sloppyFails
+language/expressions/assignment/S11.13.1_A5_T4.js sloppyFails
+language/expressions/assignment/S11.13.1_A5_T5.js fails
+language/expressions/assignment/S11.13.1_A6_T1.js sloppyFails
+language/expressions/assignment/S11.13.1_A6_T2.js sloppyFails
+language/expressions/assignment/S11.13.1_A6_T3.js sloppyFails
+language/expressions/assignment/S11.13.1_A7_T1.js fails
+language/expressions/assignment/S11.13.1_A7_T2.js fails
+language/expressions/assignment/S11.13.1_A7_T3.js fails
+language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js fails
+language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js fails
+language/expressions/assignment/dstr-array-elem-init-let.js fails
+language/expressions/assignment/dstr-array-elem-iter-rtrn-close-err.js fails
+language/expressions/assignment/dstr-array-elem-iter-rtrn-close-null.js fails
+language/expressions/assignment/dstr-array-elem-iter-rtrn-close.js fails
+language/expressions/assignment/dstr-array-elem-iter-thrw-close-err.js fails
+language/expressions/assignment/dstr-array-elem-iter-thrw-close.js fails
+language/expressions/assignment/dstr-array-elem-put-let.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close-err.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close-null.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-list-thrw-close-err.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-list-thrw-close.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close-err.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close-null.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-rest-thrw-close-err.js fails
+language/expressions/assignment/dstr-array-elem-trlg-iter-rest-thrw-close.js fails
+language/expressions/assignment/dstr-array-rest-iter-rtrn-close-err.js fails
+language/expressions/assignment/dstr-array-rest-iter-rtrn-close-null.js fails
+language/expressions/assignment/dstr-array-rest-iter-rtrn-close.js fails
+language/expressions/assignment/dstr-array-rest-iter-thrw-close-err.js fails
+language/expressions/assignment/dstr-array-rest-iter-thrw-close.js fails
+language/expressions/assignment/dstr-array-rest-lref-err.js fails
+language/expressions/assignment/dstr-array-rest-put-let.js fails
+language/expressions/assignment/dstr-obj-empty-null.js fails
+language/expressions/assignment/dstr-obj-empty-undef.js fails
+language/expressions/assignment/dstr-obj-id-init-let.js fails
+language/expressions/assignment/dstr-obj-id-put-let.js fails
+language/expressions/assignment/dstr-obj-prop-elem-init-let.js fails
+language/expressions/assignment/dstr-obj-prop-put-let.js fails
+language/expressions/assignment/fn-name-lhs-cover.js fails
+language/expressions/assignment/fn-name-lhs-member.js fails
+language/expressions/async-function/expression-returns-promise.js fails
+language/expressions/async-function/syntax-expression-is-PrimaryExpression.js fails
+language/expressions/await/await-BindingIdentifier-in-global.js fails
+language/expressions/await/await-in-nested-function.js fails
+language/expressions/await/await-in-nested-generator.js fails
+language/expressions/await/await-throws-rejections.js fails
+language/expressions/call/11.2.3-3_3.js fails
+language/expressions/call/eval-realm-indirect.js sloppyFails
+language/expressions/call/eval-spread-empty-leading.js fails
+language/expressions/call/eval-spread-empty-trailing.js fails
+language/expressions/call/eval-spread.js fails
+language/expressions/call/scope-lex-open.js fails
+language/expressions/call/tco-call-args.js strictFails
+language/expressions/call/tco-cross-realm-class-construct.js fails
+language/expressions/call/tco-cross-realm-class-derived-construct.js fails
+language/expressions/call/tco-cross-realm-fun-call.js fails
+language/expressions/call/tco-cross-realm-fun-construct.js fails
+language/expressions/call/tco-member-args.js strictFails
+language/expressions/call/tco-non-eval-function-dynamic.js sloppyFails
+language/expressions/call/tco-non-eval-function.js sloppyFails
+language/expressions/call/tco-non-eval-global.js sloppyFails
+language/expressions/call/tco-non-eval-with.js sloppyFails
+language/expressions/class/gen-meth-dflt-params-ref-later.js fails
+language/expressions/class/gen-meth-dflt-params-ref-self.js fails
+language/expressions/class/gen-meth-static-dflt-params-ref-later.js fails
+language/expressions/class/gen-meth-static-dflt-params-ref-self.js fails
+language/expressions/class/meth-dflt-params-ref-later.js fails
+language/expressions/class/meth-dflt-params-ref-self.js fails
+language/expressions/class/meth-static-dflt-params-ref-later.js fails
+language/expressions/class/meth-static-dflt-params-ref-self.js fails
+language/expressions/class/name.js fails
+language/expressions/class/scope-gen-meth-paramsbody-var-open.js fails
+language/expressions/class/scope-meth-paramsbody-var-open.js fails
+language/expressions/class/scope-setter-paramsbody-var-open.js fails
+language/expressions/class/scope-static-gen-meth-paramsbody-var-open.js fails
+language/expressions/class/scope-static-meth-paramsbody-var-open.js fails
+language/expressions/class/scope-static-setter-paramsbody-var-open.js fails
+language/expressions/comma/tco-final.js strictFails
+language/expressions/compound-assignment/S11.13.2_A5.10_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.10_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.10_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.10_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.10_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.11_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.11_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.11_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.11_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.11_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.1_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.1_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.1_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.1_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.1_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.2_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.2_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.2_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.2_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.2_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.3_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.3_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.3_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.3_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.3_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.4_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.4_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.4_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.4_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.4_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.5_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.5_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.5_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.5_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.5_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.6_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.6_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.6_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.6_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.6_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.7_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.7_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.7_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.7_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.7_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.8_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.8_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.8_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.8_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.8_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A5.9_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.9_T2.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.9_T3.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.9_T4.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A5.9_T5.js fails
+language/expressions/compound-assignment/S11.13.2_A6.10_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.11_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.1_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.2_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.3_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.4_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.5_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.6_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.7_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.8_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A6.9_T1.js sloppyFails
+language/expressions/compound-assignment/S11.13.2_A7.10_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.11_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.1_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.2_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.3_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.4_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.5_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.6_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.7_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.8_T4.js fails
+language/expressions/compound-assignment/S11.13.2_A7.9_T4.js fails
+language/expressions/delete/super-property.js fails
+language/expressions/conditional/tco-cond.js strictFails
+language/expressions/conditional/tco-pos.js strictFails
+language/expressions/function/arguments-with-arguments-fn.js sloppyFails
+language/expressions/function/arguments-with-arguments-lex.js sloppyFails
+language/expressions/function/dflt-params-ref-later.js fails
+language/expressions/function/dflt-params-ref-self.js fails
+language/expressions/function/name.js fails
+language/expressions/function/param-dflt-yield-non-strict.js sloppyFails
+language/expressions/function/scope-body-lex-distinct.js sloppyFails
+language/expressions/function/scope-name-var-open-non-strict.js sloppyFails
+language/expressions/function/scope-name-var-open-strict.js strictFails
+language/expressions/function/scope-param-elem-var-close.js sloppyFails
+language/expressions/function/scope-param-elem-var-open.js sloppyFails
+language/expressions/function/scope-param-rest-elem-var-close.js sloppyFails
+language/expressions/function/scope-param-rest-elem-var-open.js sloppyFails
+language/expressions/function/scope-paramsbody-var-open.js fails
+language/expressions/generators/arguments-with-arguments-fn.js sloppyFails
+language/expressions/generators/arguments-with-arguments-lex.js sloppyFails
+language/expressions/generators/default-proto.js fails
+language/expressions/generators/dflt-params-ref-later.js fails
+language/expressions/generators/dflt-params-ref-self.js fails
+language/expressions/generators/eval-body-proto-realm.js fails
+language/expressions/generators/name.js fails
+language/expressions/generators/named-yield-identifier-non-strict.js sloppyFails
+language/expressions/generators/scope-body-lex-distinct.js sloppyFails
+language/expressions/generators/scope-name-var-open-non-strict.js sloppyFails
+language/expressions/generators/scope-name-var-open-strict.js strictFails
+language/expressions/generators/scope-param-elem-var-close.js sloppyFails
+language/expressions/generators/scope-param-elem-var-open.js sloppyFails
+language/expressions/generators/scope-param-rest-elem-var-close.js sloppyFails
+language/expressions/generators/scope-param-rest-elem-var-open.js sloppyFails
+language/expressions/generators/scope-paramsbody-var-open.js fails
+language/expressions/generators/yield-as-function-expression-binding-identifier.js sloppyFails
+language/expressions/generators/yield-as-identifier-in-nested-function.js sloppyFails
+language/expressions/generators/yield-as-literal-property-name.js fails
+language/expressions/generators/yield-as-property-name.js fails
+language/expressions/generators/yield-identifier-non-strict.js sloppyFails
+language/expressions/generators/yield-star-before-newline.js fails
+language/expressions/instanceof/prototype-getter-with-object-throws.js fails
+language/expressions/instanceof/prototype-getter-with-object.js fails
+language/expressions/logical-and/tco-right.js strictFails
+language/expressions/logical-or/tco-right.js strictFails
+language/expressions/new.target/value-via-reflect-construct.js fails
+language/expressions/new.target/value-via-super-call.js fails
+language/expressions/new.target/value-via-super-property.js fails
+language/expressions/new/non-ctor-err-realm.js fails
+language/expressions/object/fn-name-accessor-get.js fails
+language/expressions/object/fn-name-accessor-set.js fails
+language/expressions/object/fn-name-arrow.js fails
+language/expressions/object/fn-name-class.js fails
+language/expressions/object/fn-name-cover.js fails
+language/expressions/object/fn-name-fn.js fails
+language/expressions/object/fn-name-gen.js fails
+language/expressions/object/let-non-strict-access.js sloppyFails
+language/expressions/object/let-non-strict-syntax.js sloppyFails
+language/expressions/object/method-definition/fn-name-fn.js fails
+language/expressions/object/method-definition/fn-name-gen.js fails
+language/expressions/object/method-definition/gen-meth-dflt-params-ref-later.js fails
+language/expressions/object/method-definition/gen-meth-dflt-params-ref-self.js fails
+language/expressions/object/method-definition/gen-yield-identifier-non-strict.js sloppyFails
+language/expressions/object/method-definition/generator-name-prop-symbol.js fails
+language/expressions/object/method-definition/meth-dflt-params-ref-later.js fails
+language/expressions/object/method-definition/meth-dflt-params-ref-self.js fails
+language/expressions/object/method-definition/name-invoke-ctor.js fails
+language/expressions/object/method-definition/name-name-prop-symbol.js fails
+language/expressions/object/method-definition/name-prototype-prop.js fails
+language/expressions/object/method-definition/object-method-returns-promise.js fails
+language/expressions/object/method-definition/yield-as-function-expression-binding-identifier.js sloppyFails
+language/expressions/object/method-definition/yield-as-identifier-in-nested-function.js sloppyFails
+language/expressions/object/method-definition/yield-as-literal-property-name.js fails
+language/expressions/object/method-definition/yield-as-property-name.js fails
+language/expressions/object/method-definition/yield-star-before-newline.js fails
+language/expressions/object/prop-def-id-eval-error-2.js sloppyFails
+language/expressions/object/properties-names-eval-arguments.js strictFails
+language/expressions/object/scope-gen-meth-body-lex-distinct.js sloppyFails
+language/expressions/object/scope-gen-meth-param-elem-var-close.js sloppyFails
+language/expressions/object/scope-gen-meth-param-elem-var-open.js sloppyFails
+language/expressions/object/scope-gen-meth-param-rest-elem-var-close.js sloppyFails
+language/expressions/object/scope-gen-meth-param-rest-elem-var-open.js sloppyFails
+language/expressions/object/scope-gen-meth-paramsbody-var-open.js fails
+language/expressions/object/scope-getter-body-lex-distinc.js sloppyFails
+language/expressions/object/scope-meth-body-lex-distinct.js sloppyFails
+language/expressions/object/scope-meth-param-elem-var-close.js sloppyFails
+language/expressions/object/scope-meth-param-elem-var-open.js sloppyFails
+language/expressions/object/scope-meth-param-rest-elem-var-close.js sloppyFails
+language/expressions/object/scope-meth-param-rest-elem-var-open.js sloppyFails
+language/expressions/object/scope-meth-paramsbody-var-open.js fails
+language/expressions/object/scope-setter-body-lex-distinc.js sloppyFails
+language/expressions/object/scope-setter-paramsbody-var-open.js fails
+language/expressions/postfix-decrement/S11.3.2_A5_T1.js sloppyFails
+language/expressions/postfix-decrement/S11.3.2_A5_T2.js sloppyFails
+language/expressions/postfix-decrement/S11.3.2_A5_T3.js sloppyFails
+language/expressions/postfix-decrement/S11.3.2_A5_T4.js sloppyFails
+language/expressions/postfix-decrement/S11.3.2_A5_T5.js fails
+language/expressions/postfix-decrement/S11.3.2_A6_T3.js fails
+language/expressions/postfix-increment/S11.3.1_A5_T1.js sloppyFails
+language/expressions/postfix-increment/S11.3.1_A5_T2.js sloppyFails
+language/expressions/postfix-increment/S11.3.1_A5_T3.js sloppyFails
+language/expressions/postfix-increment/S11.3.1_A5_T4.js sloppyFails
+language/expressions/postfix-increment/S11.3.1_A5_T5.js fails
+language/expressions/postfix-increment/S11.3.1_A6_T3.js fails
+language/expressions/prefix-decrement/S11.4.5_A5_T1.js sloppyFails
+language/expressions/prefix-decrement/S11.4.5_A5_T2.js sloppyFails
+language/expressions/prefix-decrement/S11.4.5_A5_T3.js sloppyFails
+language/expressions/prefix-decrement/S11.4.5_A5_T4.js sloppyFails
+language/expressions/prefix-decrement/S11.4.5_A5_T5.js fails
+language/expressions/prefix-decrement/S11.4.5_A6_T3.js fails
+language/expressions/prefix-increment/S11.4.4_A5_T1.js sloppyFails
+language/expressions/prefix-increment/S11.4.4_A5_T2.js sloppyFails
+language/expressions/prefix-increment/S11.4.4_A5_T3.js sloppyFails
+language/expressions/prefix-increment/S11.4.4_A5_T4.js sloppyFails
+language/expressions/prefix-increment/S11.4.4_A5_T5.js fails
+language/expressions/prefix-increment/S11.4.4_A6_T3.js fails
+language/expressions/super/call-bind-this-value-twice.js fails
+language/expressions/super/call-construct-invocation.js fails
+language/expressions/super/call-proto-not-ctor.js fails
+language/expressions/super/prop-dot-cls-null-proto.js fails
+language/expressions/super/prop-dot-cls-ref-strict.js fails
+language/expressions/super/prop-dot-cls-ref-this.js fails
+language/expressions/super/prop-dot-cls-this-uninit.js fails
+language/expressions/super/prop-dot-cls-val-from-arrow.js fails
+language/expressions/super/prop-dot-obj-null-proto.js fails
+language/expressions/super/prop-dot-obj-ref-non-strict.js sloppyFails
+language/expressions/super/prop-dot-obj-ref-strict.js strictFails
+language/expressions/super/prop-dot-obj-ref-this.js fails
+language/expressions/super/prop-dot-obj-val-from-arrow.js fails
+language/expressions/super/prop-expr-cls-key-err.js fails
+language/expressions/super/prop-expr-cls-null-proto.js fails
+language/expressions/super/prop-expr-cls-ref-strict.js fails
+language/expressions/super/prop-expr-cls-ref-this.js fails
+language/expressions/super/prop-expr-cls-this-uninit.js fails
+language/expressions/super/prop-expr-cls-val-from-arrow.js fails
+language/expressions/super/prop-expr-obj-key-err.js fails
+language/expressions/super/prop-expr-obj-null-proto.js fails
+language/expressions/super/prop-expr-obj-ref-non-strict.js sloppyFails
+language/expressions/super/prop-expr-obj-ref-strict.js strictFails
+language/expressions/super/prop-expr-obj-ref-this.js fails
+language/expressions/super/prop-expr-obj-val-from-arrow.js fails
+language/expressions/super/realm.js fails
+language/expressions/tagged-template/cache-different-functions-same-site.js fails
+language/expressions/tagged-template/cache-eval-inner-function.js fails
+language/expressions/tagged-template/cache-realm.js fails
+language/expressions/tagged-template/cache-same-site-top-level.js fails
+language/expressions/tagged-template/cache-same-site.js fails
+language/expressions/tagged-template/invalid-escape-sequences.js fails
+language/expressions/tagged-template/tco-call.js strictFails
+language/expressions/tagged-template/tco-member.js strictFails
+language/expressions/tagged-template/template-object-frozen-non-strict.js sloppyFails
+language/expressions/tagged-template/template-object-frozen-strict.js strictFails
+language/expressions/tagged-template/template-object.js fails
+language/expressions/tco-pos.js strictFails
+language/expressions/template-literal/tv-character-escape-sequence.js fails
+language/expressions/template-literal/tv-hex-escape-sequence.js fails
+language/expressions/template-literal/tv-line-continuation.js fails
+language/expressions/template-literal/tv-line-terminator-sequence.js fails
+language/expressions/template-literal/tv-no-substitution.js fails
+language/expressions/template-literal/tv-null-character-escape-sequence.js fails
+language/expressions/template-literal/tv-template-character.js fails
+language/expressions/template-literal/tv-template-characters.js fails
+language/expressions/template-literal/tv-template-head.js fails
+language/expressions/template-literal/tv-template-middle.js fails
+language/expressions/template-literal/tv-template-tail.js fails
+language/expressions/template-literal/tv-utf16-escape-sequence.js fails
+language/expressions/template-literal/tv-zwnbsp.js fails
+language/expressions/yield/star-array.js fails
+language/expressions/yield/star-in-rltn-expr.js fails
+language/expressions/yield/star-iterable.js fails
+language/expressions/yield/star-rhs-iter-get-call-err.js fails
+language/expressions/yield/star-rhs-iter-get-call-non-obj.js fails
+language/expressions/yield/star-rhs-iter-get-get-err.js fails
+language/expressions/yield/star-rhs-iter-nrml-next-call-err.js fails
+language/expressions/yield/star-rhs-iter-nrml-next-call-non-obj.js fails
+language/expressions/yield/star-rhs-iter-nrml-next-get-err.js fails
+language/expressions/yield/star-rhs-iter-nrml-next-invoke.js fails
+language/expressions/yield/star-rhs-iter-nrml-res-done-err.js fails
+language/expressions/yield/star-rhs-iter-nrml-res-done-no-value.js fails
+language/expressions/yield/star-rhs-iter-nrml-res-value-err.js fails
+language/expressions/yield/star-rhs-iter-nrml-res-value-final.js fails
+language/expressions/yield/star-rhs-iter-rtrn-no-rtrn.js fails
+language/expressions/yield/star-rhs-iter-rtrn-res-done-err.js fails
+language/expressions/yield/star-rhs-iter-rtrn-res-done-no-value.js fails
+language/expressions/yield/star-rhs-iter-rtrn-res-value-err.js fails
+language/expressions/yield/star-rhs-iter-rtrn-res-value-final.js fails
+language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-err.js fails
+language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-non-obj.js fails
+language/expressions/yield/star-rhs-iter-rtrn-rtrn-get-err.js fails
+language/expressions/yield/star-rhs-iter-rtrn-rtrn-invoke.js fails
+language/expressions/yield/star-rhs-iter-thrw-res-done-err.js fails
+language/expressions/yield/star-rhs-iter-thrw-res-done-no-value.js fails
+language/expressions/yield/star-rhs-iter-thrw-res-value-err.js fails
+language/expressions/yield/star-rhs-iter-thrw-res-value-final.js fails
+language/expressions/yield/star-rhs-iter-thrw-thrw-call-err.js fails
+language/expressions/yield/star-rhs-iter-thrw-thrw-call-non-obj.js fails
+language/expressions/yield/star-rhs-iter-thrw-thrw-get-err.js fails
+language/expressions/yield/star-rhs-iter-thrw-thrw-invoke.js fails
+language/expressions/yield/star-rhs-iter-thrw-violation-no-rtrn.js fails
+language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-err.js fails
+language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-non-obj.js fails
+language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-get-err.js fails
+language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-invoke.js fails
+language/expressions/yield/star-rhs-unresolvable.js fails
+language/expressions/yield/star-string.js fails
+language/function-code/each-param-has-own-non-shared-eval-scope.js sloppyFails
+language/function-code/each-param-has-own-scope.js sloppyFails
+language/function-code/eval-param-env-with-computed-key.js sloppyFails
+language/function-code/eval-param-env-with-prop-initializer.js sloppyFails
+language/global-code/decl-lex-restricted-global.js fails
+language/global-code/script-decl-func-dups.js fails
+language/global-code/script-decl-func-err-non-configurable.js fails
+language/global-code/script-decl-func-err-non-extensible.js fails
+language/global-code/script-decl-func.js fails
+language/global-code/script-decl-lex-deletion.js sloppyFails
+language/global-code/script-decl-lex-lex.js fails
+language/global-code/script-decl-lex-restricted-global.js fails
+language/global-code/script-decl-lex-var.js fails
+language/global-code/script-decl-lex.js fails
+language/global-code/script-decl-var-collision.js fails
+language/global-code/script-decl-var-err.js fails
+language/global-code/script-decl-var.js fails
+language/identifiers/other_id_continue.js fails
+language/identifiers/other_id_start-escaped.js fails
+language/identifiers/other_id_start.js fails
+language/literals/regexp/u-astral.js fails
+language/literals/regexp/u-case-mapping.js fails
+language/literals/regexp/u-surrogate-pairs-atom-char-class.js fails
+language/literals/regexp/u-surrogate-pairs-atom-dot.js fails
+language/literals/regexp/u-surrogate-pairs-atom-escape-char-class.js fails
+language/literals/regexp/u-surrogate-pairs-atom-escape-decimal.js fails
+language/literals/regexp/u-surrogate-pairs.js fails
+language/literals/regexp/u-unicode-esc.js fails
+language/literals/regexp/y-assertion-start.js fails
+language/module-code/eval-gtbndng-indirect-trlng-comma_FIXTURE.js fails
+language/module-code/eval-gtbndng-indirect-update-as_FIXTURE.js fails
+language/module-code/eval-gtbndng-indirect-update-dflt_FIXTURE.js fails
+language/module-code/eval-gtbndng-indirect-update_FIXTURE.js fails
+language/module-code/eval-rqstd-abrupt-err-type_FIXTURE.js fails
+language/module-code/eval-rqstd-abrupt-err-uri_FIXTURE.js fails
+language/module-code/eval-rqstd-once_FIXTURE.js fails
+language/module-code/eval-rqstd-order-4_FIXTURE.js fails
+language/module-code/eval-rqstd-order-6_FIXTURE.js fails
+language/module-code/eval-rqstd-order-8_FIXTURE.js fails
+language/module-code/instn-iee-bndng-cls_FIXTURE.js fails
+language/module-code/instn-iee-bndng-const_FIXTURE.js fails
+language/module-code/instn-iee-bndng-fun_FIXTURE.js fails
+language/module-code/instn-iee-bndng-gen_FIXTURE.js fails
+language/module-code/instn-iee-bndng-let_FIXTURE.js fails
+language/module-code/instn-iee-bndng-var_FIXTURE.js fails
+language/module-code/instn-iee-err-ambiguous-1_FIXTURE.js fails
+language/module-code/instn-iee-err-ambiguous-2_FIXTURE.js fails
+language/module-code/instn-iee-err-ambiguous_FIXTURE.js fails
+language/module-code/instn-iee-err-circular_FIXTURE.js fails
+language/module-code/instn-iee-err-dflt-thru-star-dflt_FIXTURE.js fails
+language/module-code/instn-iee-err-dflt-thru-star-int_FIXTURE.js fails
+language/module-code/instn-iee-iee-cycle-2_FIXTURE.js fails
+language/module-code/instn-iee-star-cycle-2_FIXTURE.js fails
+language/module-code/instn-iee-star-cycle-indirect-x_FIXTURE.js fails
+language/module-code/instn-iee-trlng-comma_FIXTURE.js fails
+language/module-code/instn-named-err-ambiguous-1_FIXTURE.js fails
+language/module-code/instn-named-err-ambiguous-2_FIXTURE.js fails
+language/module-code/instn-named-err-ambiguous_FIXTURE.js fails
+language/module-code/instn-named-err-dflt-thru-star-dflt_FIXTURE.js fails
+language/module-code/instn-named-err-dflt-thru-star-int_FIXTURE.js fails
+language/module-code/instn-named-iee-cycle-2_FIXTURE.js fails
+language/module-code/instn-named-star-cycle-2_FIXTURE.js fails
+language/module-code/instn-named-star-cycle-indirect-x_FIXTURE.js fails
+language/module-code/instn-resolve-empty-export_FIXTURE.js fails
+language/module-code/instn-resolve-empty-import_FIXTURE.js fails
+language/module-code/instn-resolve-err-reference_FIXTURE.js fails
+language/module-code/instn-resolve-err-syntax_FIXTURE.js fails
+language/module-code/instn-resolve-order-depth-child_FIXTURE.js fails
+language/module-code/instn-resolve-order-depth-reference_FIXTURE.js fails
+language/module-code/instn-resolve-order-depth-syntax_FIXTURE.js fails
+language/module-code/instn-resolve-order-src-reference_FIXTURE.js fails
+language/module-code/instn-resolve-order-src-syntax_FIXTURE.js fails
+language/module-code/instn-star-ambiguous-1_FIXTURE.js fails
+language/module-code/instn-star-ambiguous-2_FIXTURE.js fails
+language/module-code/instn-star-ambiguous_FIXTURE.js fails
+language/module-code/instn-star-equality-other_FIXTURE.js fails
+language/module-code/instn-star-err-not-found-faulty_FIXTURE.js fails
+language/module-code/instn-star-iee-cycle-2_FIXTURE.js fails
+language/module-code/instn-star-props-circular-a_FIXTURE.js fails
+language/module-code/instn-star-props-circular-b_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-keep-indirect-def_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-keep-indirect-reexport_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-keep-local-named_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-keep-local-prod_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-skip-named_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-skip-prod_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-skip-star-named_FIXTURE.js fails
+language/module-code/instn-star-props-dflt-skip-star-prod_FIXTURE.js fails
+language/module-code/instn-star-props-nrml-1_FIXTURE.js fails
+language/module-code/instn-star-props-nrml-indirect_FIXTURE.js fails
+language/module-code/instn-star-props-nrml-star_FIXTURE.js fails
+language/module-code/instn-star-star-cycle-2_FIXTURE.js fails
+language/module-code/instn-star-star-cycle-indirect-x_FIXTURE.js fails
+language/module-code/namespace/internals/own-property-keys-binding-types_FIXTURE.js fails
+language/statements/async-function/cptn-decl.js fails
+language/statements/async-function/declaration-returns-promise.js fails
+language/statements/async-function/evaluation-body.js fails
+language/statements/async-function/syntax-declaration-line-terminators-allowed.js fails
+language/statements/block/tco-stmt-list.js strictFails
+language/statements/block/tco-stmt.js strictFails
+language/statements/class/constructor-inferred-observable-iteration.js fails
+language/statements/class/cptn-decl.js fails
+language/statements/class/definition/accessors.js fails
+language/statements/class/definition/class-method-returns-promise.js fails
+language/statements/class/definition/fn-name-accessor-get.js fails
+language/statements/class/definition/fn-name-accessor-set.js fails
+language/statements/class/definition/fn-name-gen-method.js fails
+language/statements/class/definition/fn-name-method.js fails
+language/statements/class/definition/getters-non-configurable-err.js fails
+language/statements/class/definition/getters-prop-desc.js fails
+language/statements/class/definition/getters-restricted-ids.js fails
+language/statements/class/definition/invalid-extends.js strictFails
+language/statements/class/definition/methods-gen-yield-as-literal-property-name.js fails
+language/statements/class/definition/methods-gen-yield-as-property-name.js fails
+language/statements/class/definition/methods-gen-yield-star-before-newline.js fails
+language/statements/class/definition/methods-named-eval-arguments.js fails
+language/statements/class/definition/methods.js fails
+language/statements/class/definition/numeric-property-names.js fails
+language/statements/class/definition/prototype-getter.js fails
+language/statements/class/definition/prototype-property.js fails
+language/statements/class/definition/prototype-setter.js fails
+language/statements/class/definition/prototype-wiring.js fails
+language/statements/class/definition/setters-non-configurable-err.js fails
+language/statements/class/definition/setters-prop-desc.js fails
+language/statements/class/definition/setters-restricted-ids.js fails
+language/statements/class/definition/this-access-restriction-2.js fails
+language/statements/class/definition/this-access-restriction.js fails
+language/statements/class/definition/this-check-ordering.js fails
+language/statements/class/gen-meth-dflt-params-ref-later.js fails
+language/statements/class/gen-meth-dflt-params-ref-self.js fails
+language/statements/class/gen-meth-static-dflt-params-ref-later.js fails
+language/statements/class/gen-meth-static-dflt-params-ref-self.js fails
+language/statements/class/meth-dflt-params-ref-later.js fails
+language/statements/class/meth-dflt-params-ref-self.js fails
+language/statements/class/meth-static-dflt-params-ref-later.js fails
+language/statements/class/meth-static-dflt-params-ref-self.js fails
+language/statements/class/name-binding/in-extends-expression-assigned.js fails
+language/statements/class/name-binding/in-extends-expression-grouped.js fails
+language/statements/class/name-binding/in-extends-expression.js fails
+language/statements/class/scope-gen-meth-paramsbody-var-open.js fails
+language/statements/class/scope-meth-paramsbody-var-open.js fails
+language/statements/class/scope-setter-paramsbody-var-open.js fails
+language/statements/class/scope-static-gen-meth-paramsbody-var-open.js fails
+language/statements/class/scope-static-meth-paramsbody-var-open.js fails
+language/statements/class/scope-static-setter-paramsbody-var-open.js fails
+language/statements/class/static-method-gen-non-configurable-err.js fails
+language/statements/class/static-method-non-configurable-err.js fails
+language/statements/class/subclass/bound-function.js fails
+language/statements/class/subclass/builtin-objects/Array/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing.js fails
+language/statements/class/subclass/builtin-objects/ArrayBuffer/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Boolean/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/DataView/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Date/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Error/message-property-assignment.js fails
+language/statements/class/subclass/builtin-objects/Error/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Function/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/GeneratorFunction/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Map/regular-subclassing.js fails
+language/statements/class/subclass/builtin-objects/Map/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/NativeError/EvalError-message.js fails
+language/statements/class/subclass/builtin-objects/NativeError/EvalError-super.js fails
+language/statements/class/subclass/builtin-objects/NativeError/RangeError-message.js fails
+language/statements/class/subclass/builtin-objects/NativeError/RangeError-super.js fails
+language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-message.js fails
+language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-super.js fails
+language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-message.js fails
+language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-super.js fails
+language/statements/class/subclass/builtin-objects/NativeError/TypeError-message.js fails
+language/statements/class/subclass/builtin-objects/NativeError/TypeError-super.js fails
+language/statements/class/subclass/builtin-objects/NativeError/URIError-message.js fails
+language/statements/class/subclass/builtin-objects/NativeError/URIError-super.js fails
+language/statements/class/subclass/builtin-objects/Number/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Object/constructor-return-undefined-throws.js fails
+language/statements/class/subclass/builtin-objects/Promise/regular-subclassing.js fails
+language/statements/class/subclass/builtin-objects/Promise/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/RegExp/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/Set/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/String/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/TypedArray/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/WeakMap/regular-subclassing.js fails
+language/statements/class/subclass/builtin-objects/WeakMap/super-must-be-called.js fails
+language/statements/class/subclass/builtin-objects/WeakSet/regular-subclassing.js fails
+language/statements/class/subclass/builtin-objects/WeakSet/super-must-be-called.js fails
+language/statements/class/subclass/builtins.js fails
+language/statements/class/subclass/class-definition-null-proto-super.js fails
+language/statements/class/subclass/class-definition-null-proto-this.js fails
+language/statements/class/subclass/class-definition-superclass-generator.js fails
+language/statements/class/subclass/default-constructor-spread-override.js fails
+language/statements/class/super/in-methods.js fails
+language/statements/const/block-local-closure-get-before-initialization.js fails
+language/statements/const/block-local-use-before-initialization-in-declaration-statement.js fails
+language/statements/const/block-local-use-before-initialization-in-prior-statement.js fails
+language/statements/const/function-local-closure-get-before-initialization.js fails
+language/statements/const/function-local-use-before-initialization-in-declaration-statement.js fails
+language/statements/const/function-local-use-before-initialization-in-prior-statement.js fails
+language/statements/const/global-closure-get-before-initialization.js fails
+language/statements/const/global-use-before-initialization-in-declaration-statement.js fails
+language/statements/const/global-use-before-initialization-in-prior-statement.js fails
+language/statements/const/syntax/const-invalid-assignment-statement-body-for-in.js fails
+language/statements/const/syntax/const-invalid-assignment-statement-body-for-of.js fails
+language/statements/do-while/tco-body.js strictFails
+language/statements/for-in/head-const-bound-names-fordecl-tdz.js fails
+language/statements/for-in/head-const-fresh-binding-per-iteration.js fails
+language/statements/for-in/head-let-bound-names-fordecl-tdz.js fails
+language/statements/for-in/head-lhs-let.js sloppyFails
+language/statements/for-in/head-var-bound-names-let.js sloppyFails
+language/statements/for-in/identifier-let-allowed-as-lefthandside-expression-not-strict.js sloppyFails
+language/statements/for-in/scope-body-lex-open.js fails
+language/statements/for-in/scope-head-lex-close.js fails
+language/statements/for-in/scope-head-lex-open.js fails
+language/statements/for-of/body-dstr-assign-error.js fails
+language/statements/for-of/body-put-error.js fails
+language/statements/for-of/dstr-array-elem-init-let.js fails
+language/statements/for-of/dstr-array-elem-iter-rtrn-close-err.js fails
+language/statements/for-of/dstr-array-elem-iter-rtrn-close-null.js fails
+language/statements/for-of/dstr-array-elem-iter-rtrn-close.js fails
+language/statements/for-of/dstr-array-elem-iter-thrw-close-err.js fails
+language/statements/for-of/dstr-array-elem-iter-thrw-close.js fails
+language/statements/for-of/dstr-array-elem-put-let.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close-err.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close-null.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-list-thrw-close-err.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-list-thrw-close.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close-err.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close-null.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-rest-thrw-close-err.js fails
+language/statements/for-of/dstr-array-elem-trlg-iter-rest-thrw-close.js fails
+language/statements/for-of/dstr-array-rest-iter-rtrn-close-err.js fails
+language/statements/for-of/dstr-array-rest-iter-rtrn-close-null.js fails
+language/statements/for-of/dstr-array-rest-iter-rtrn-close.js fails
+language/statements/for-of/dstr-array-rest-iter-thrw-close-err.js fails
+language/statements/for-of/dstr-array-rest-iter-thrw-close.js fails
+language/statements/for-of/dstr-array-rest-lref-err.js fails
+language/statements/for-of/dstr-array-rest-put-let.js fails
+language/statements/for-of/dstr-obj-empty-null.js fails
+language/statements/for-of/dstr-obj-empty-undef.js fails
+language/statements/for-of/dstr-obj-id-init-let.js fails
+language/statements/for-of/dstr-obj-id-put-let.js fails
+language/statements/for-of/dstr-obj-prop-elem-init-let.js fails
+language/statements/for-of/dstr-obj-prop-put-let.js fails
+language/statements/for-of/generator-close-via-continue.js fails
+language/statements/for-of/generator-close-via-return.js fails
+language/statements/for-of/generator-close-via-throw.js fails
+language/statements/for-of/head-const-bound-names-fordecl-tdz.js fails
+language/statements/for-of/head-const-fresh-binding-per-iteration.js fails
+language/statements/for-of/head-let-bound-names-fordecl-tdz.js fails
+language/statements/for-of/head-var-bound-names-let.js sloppyFails
+language/statements/for-of/iterator-close-via-continue.js fails
+language/statements/for-of/iterator-close-via-return.js fails
+language/statements/for-of/iterator-close-via-throw.js fails
+language/statements/for-of/iterator-next-reference.js fails
+language/statements/for-of/scope-body-lex-open.js fails
+language/statements/for-of/scope-head-lex-close.js fails
+language/statements/for-of/scope-head-lex-open.js fails
+language/statements/for-of/yield-star-from-catch.js fails
+language/statements/for-of/yield-star-from-finally.js fails
+language/statements/for-of/yield-star-from-try.js fails
+language/statements/for-of/yield-star.js fails
+language/statements/for/head-lhs-let.js sloppyFails
+language/statements/for/scope-body-lex-open.js fails
+language/statements/for/tco-const-body.js strictFails
+language/statements/for/tco-let-body.js strictFails
+language/statements/for/tco-lhs-body.js strictFails
+language/statements/for/tco-var-body.js strictFails
+language/statements/function/13.2-30-s.js fails
+language/statements/function/S13_A15_T4.js sloppyFails
+language/statements/function/arguments-with-arguments-fn.js sloppyFails
+language/statements/function/arguments-with-arguments-lex.js sloppyFails
+language/statements/function/dflt-params-ref-later.js fails
+language/statements/function/dflt-params-ref-self.js fails
+language/statements/function/param-dflt-yield-non-strict.js sloppyFails
+language/statements/function/scope-body-lex-distinct.js sloppyFails
+language/statements/function/scope-param-elem-var-close.js sloppyFails
+language/statements/function/scope-param-elem-var-open.js sloppyFails
+language/statements/function/scope-param-rest-elem-var-close.js sloppyFails
+language/statements/function/scope-param-rest-elem-var-open.js sloppyFails
+language/statements/function/scope-paramsbody-var-open.js fails
+language/statements/generators/arguments-with-arguments-fn.js sloppyFails
+language/statements/generators/arguments-with-arguments-lex.js sloppyFails
+language/statements/generators/default-proto.js fails
+language/statements/generators/dflt-params-ref-later.js fails
+language/statements/generators/dflt-params-ref-self.js fails
+language/statements/generators/scope-body-lex-distinct.js sloppyFails
+language/statements/generators/scope-param-elem-var-close.js sloppyFails
+language/statements/generators/scope-param-elem-var-open.js sloppyFails
+language/statements/generators/scope-param-rest-elem-var-close.js sloppyFails
+language/statements/generators/scope-param-rest-elem-var-open.js sloppyFails
+language/statements/generators/scope-paramsbody-var-open.js fails
+language/statements/generators/yield-as-function-expression-binding-identifier.js sloppyFails
+language/statements/generators/yield-as-identifier-in-nested-function.js sloppyFails
+language/statements/generators/yield-as-literal-property-name.js fails
+language/statements/generators/yield-as-property-name.js fails
+language/statements/generators/yield-identifier-non-strict.js sloppyFails
+language/statements/generators/yield-star-before-newline.js fails
+language/statements/if/tco-else-body.js strictFails
+language/statements/if/tco-if-body.js strictFails
+language/statements/labeled/tco.js strictFails
+language/statements/let/block-local-closure-get-before-initialization.js fails
+language/statements/let/block-local-closure-set-before-initialization.js fails
+language/statements/let/block-local-use-before-initialization-in-declaration-statement.js fails
+language/statements/let/block-local-use-before-initialization-in-prior-statement.js fails
+language/statements/let/function-local-closure-get-before-initialization.js fails
+language/statements/let/function-local-closure-set-before-initialization.js fails
+language/statements/let/function-local-use-before-initialization-in-declaration-statement.js fails
+language/statements/let/function-local-use-before-initialization-in-prior-statement.js fails
+language/statements/let/global-closure-get-before-initialization.js fails
+language/statements/let/global-closure-set-before-initialization.js fails
+language/statements/let/global-use-before-initialization-in-declaration-statement.js fails
+language/statements/let/global-use-before-initialization-in-prior-statement.js fails
+language/statements/let/syntax/let.js fails
+language/statements/return/tco.js strictFails
+language/statements/switch/scope-lex-open-case.js fails
+language/statements/switch/scope-lex-open-dflt.js fails
+language/statements/switch/tco-case-body-dflt.js strictFails
+language/statements/switch/tco-case-body.js strictFails
+language/statements/switch/tco-dftl-body.js strictFails
+language/statements/throw/S12.13_A2_T6.js strictFails
+language/statements/try/S12.14_A18_T6.js strictFails
+language/statements/try/scope-catch-block-lex-open.js fails
+language/statements/try/tco-catch-finally.js strictFails
+language/statements/try/tco-catch.js strictFails
+language/statements/try/tco-finally.js strictFails
+language/statements/variable/binding-resolution.js sloppyFails
+language/statements/while/tco-body.js strictFails
+language/statements/with/binding-blocked-by-unscopables.js sloppyFails
+language/statements/with/has-property-err.js sloppyFails
+language/statements/with/unscopables-inc-dec.js sloppyFails
+language/types/reference/get-value-prop-base-primitive-realm.js fails
+language/types/reference/put-value-prop-base-primitive-realm.js fails
+language/types/reference/put-value-prop-base-primitive.js fails
diff --git a/tests/auto/qml/ecmascripttests/ecmascripttests.pro b/tests/auto/qml/ecmascripttests/ecmascripttests.pro
index 6d3ee12307..9c09ee701e 100644
--- a/tests/auto/qml/ecmascripttests/ecmascripttests.pro
+++ b/tests/auto/qml/ecmascripttests/ecmascripttests.pro
@@ -1,20 +1,13 @@
-CONFIG += testcase
-TARGET = tst_ecmascripttests
-QT += testlib
-macos:CONFIG -= app_bundle
-SOURCES += tst_ecmascripttests.cpp
-DEFINES += SRCDIR=\\\"$$PWD\\\"
-
-TESTSCRIPT=$$PWD/test262.py
-isEmpty(V4CMD): V4CMD = qmljs
+TEMPLATE = subdirs
+SUBDIRS = testcase.pro qjstest
checkjittarget.target = check-jit
-checkjittarget.commands = python $$TESTSCRIPT --command=$$V4CMD --parallel --with-test-expectations --update-expectations
+checkjittarget.commands = qjstest --jit --parallel --with-test-expectations --update-expectations
checkjittarget.depends = all
QMAKE_EXTRA_TARGETS += checkjittarget
checkmothtarget.target = check-interpreter
-checkmothtarget.commands = python $$TESTSCRIPT --command=\"$$V4CMD --interpret\" --parallel --with-test-expectations
+checkmothtarget.commands = qjstest --interpret --parallel --with-test-expectations
checkmothtarget.depends = all
QMAKE_EXTRA_TARGETS += checkmothtarget
diff --git a/tests/auto/qml/ecmascripttests/qjstest/main.cpp b/tests/auto/qml/ecmascripttests/qjstest/main.cpp
new file mode 100644
index 0000000000..4a3541d892
--- /dev/null
+++ b/tests/auto/qml/ecmascripttests/qjstest/main.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QJSEngine>
+#include <QCoreApplication>
+#include <QCommandLineParser>
+#include <qdebug.h>
+#include <stdlib.h>
+
+#include "test262runner.h"
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+
+ QCommandLineParser parser;
+ parser.addHelpOption();
+ parser.addVersionOption();
+ QCommandLineOption verbose("verbose", "Verbose output");
+ parser.addOption(verbose);
+ QCommandLineOption commandOption("command", "Javascript command line interpreter", "command");
+ parser.addOption(commandOption);
+ QCommandLineOption testDir("tests", "path to the tests", "tests", "test262");
+ parser.addOption(testDir);
+ QCommandLineOption cat("cat", "Print packaged test code that would be run");
+ parser.addOption(cat);
+ QCommandLineOption parallel("parallel", "Run tests in parallel");
+ parser.addOption(parallel);
+ QCommandLineOption jit("jit", "JIT all code");
+ parser.addOption(jit);
+ QCommandLineOption bytecode("interpret", "Run using the bytecode interpreter");
+ parser.addOption(bytecode);
+ QCommandLineOption withExpectations("with-test-expectations", "Parse TestExpectations to deal with known failures");
+ parser.addOption(withExpectations);
+ QCommandLineOption updateExpectations("update-expectations", "Update TestExpectations to remove unexepected passes");
+ parser.addOption(updateExpectations);
+ QCommandLineOption writeExpectations("write-expectations", "Generate a new TestExpectations file based on the results of the run");
+ parser.addOption(writeExpectations);
+ parser.addPositionalArgument("[filter]", "Only run tests that contain filter in their name");
+
+ parser.process(app);
+
+ Test262Runner testRunner(parser.value(commandOption), parser.value(testDir));
+
+ QStringList otherArgs = parser.positionalArguments();
+ if (otherArgs.size() > 1) {
+ qWarning() << "too many arguments";
+ return 1;
+ } else if (otherArgs.size()) {
+ testRunner.setFilter(otherArgs.at(0));
+ }
+
+ if (parser.isSet(cat)) {
+ testRunner.cat();
+ return 0;
+ }
+
+ if (parser.isSet(updateExpectations) && parser.isSet(writeExpectations)) {
+ qWarning() << "Can only specify one of --update-expectations and --write-expectations.";
+ exit(1);
+ }
+
+ if (parser.isSet(jit) && parser.isSet(bytecode)) {
+ qWarning() << "Can only specify one of --jit and --interpret.";
+ exit(1);
+ }
+
+ int flags = 0;
+ if (parser.isSet(verbose))
+ flags |= Test262Runner::Verbose;
+ if (parser.isSet(parallel))
+ flags |= Test262Runner::Parallel;
+ if (parser.isSet(jit))
+ flags |= Test262Runner::ForceJIT;
+ if (parser.isSet(bytecode))
+ flags |= Test262Runner::ForceBytecode;
+ if (parser.isSet(withExpectations))
+ flags |= Test262Runner::WithTestExpectations;
+ if (parser.isSet(updateExpectations))
+ flags |= Test262Runner::UpdateTestExpectations;
+ if (parser.isSet(writeExpectations))
+ flags |= Test262Runner::WriteTestExpectations;
+ testRunner.setFlags(flags);
+
+ if (testRunner.run())
+ return EXIT_SUCCESS;
+ else
+ return EXIT_FAILURE;
+}
diff --git a/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro b/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro
new file mode 100644
index 0000000000..6dec5f8f23
--- /dev/null
+++ b/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = qjstest
+QT += qml-private
+INCLUDEPATH += .
+
+DEFINES += QT_DEPRECATED_WARNINGS
+
+HEADERS += test262runner.h
+SOURCES += main.cpp test262runner.cpp
+
+QMAKE_TARGET_DESCRIPTION = Javascript test runner
+
+load(qt_tool)
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
new file mode 100644
index 0000000000..bd945047c1
--- /dev/null
+++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
@@ -0,0 +1,760 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "test262runner.h"
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qdiriterator.h>
+#include <qdebug.h>
+#include <qprocess.h>
+#include <qtemporaryfile.h>
+
+#include <private/qv4script_p.h>
+#include "private/qv4globalobject_p.h"
+#include "private/qqmlbuiltinfunctions_p.h"
+
+#include "qrunnable.h"
+
+static const char *excludedFeatures[] = {
+ "BigInt",
+ "class-fields-public",
+ "class-fields-private",
+ "Promise.prototype.finally",
+ "async-iteration",
+ "Symbol.asyncIterator",
+ "object-rest",
+ "object-spread",
+ "optional-catch-binding",
+ "regexp-dotall",
+ "regexp-lookbehind",
+ "regexp-named-groups",
+ "regexp-unicode-property-escapes",
+ "Atomics",
+ "SharedArrayBuffer",
+ "Array.prototype.flatten",
+ "Array.prototype.flatMap",
+ "string-trimming",
+ "String.prototype.trimEnd",
+ "String.prototype.trimStart",
+ "numeric-separator-literal",
+
+ // optional features, not supported by us
+ "caller",
+ nullptr
+};
+
+Test262Runner::Test262Runner(const QString &command, const QString &dir)
+ : command(command), testDir(dir)
+{
+ if (testDir.endsWith(QLatin1Char('/')))
+ testDir = testDir.chopped(1);
+}
+
+Test262Runner::~Test262Runner()
+{
+ delete threadPool;
+}
+
+void Test262Runner::cat()
+{
+ if (!loadTests())
+ return;
+
+ if (testCases.size() != 1)
+ qWarning() << "test262 --cat: Ambiguous test case, using" << testCases.begin().key();
+ TestData data = getTestData(testCases.begin().value());
+ printf("%s", data.content.constData());
+}
+
+bool Test262Runner::run()
+{
+ if (!loadTests())
+ return false;
+
+ if (flags & Parallel) {
+ threadPool = new QThreadPool;
+ threadPool->setStackSize(16*1024*1024);
+ if (flags & Verbose)
+ qDebug() << "Running in parallel with" << QThread::idealThreadCount() << "threads.";
+ }
+
+ if (flags & ForceJIT)
+ qputenv("QV4_JIT_CALL_THRESHOLD", QByteArray("0"));
+ else if (flags & ForceBytecode)
+ qputenv("QV4_FORCE_INTERPRETER", QByteArray("1"));
+
+ if (flags & WithTestExpectations)
+ loadTestExpectations();
+
+ for (auto it = testCases.constBegin(); it != testCases.constEnd(); ++it) {
+ auto c = it.value();
+ if (!c.skipTestCase) {
+ int result = runSingleTest(c);
+ if (result == -2)
+ return false;
+ }
+ }
+
+ if (threadPool)
+ threadPool->waitForDone();
+
+ const bool testsOk = report();
+
+ if (flags & WriteTestExpectations)
+ writeTestExpectations();
+ else if (flags & UpdateTestExpectations)
+ updateTestExpectations();
+
+ return testsOk;
+}
+
+bool Test262Runner::report()
+{
+ qDebug() << "Test execution summary:";
+ qDebug() << " Executed" << testCases.size() << "test cases.";
+ QStringList crashes;
+ QStringList unexpectedFailures;
+ QStringList unexpectedPasses;
+ for (auto it = testCases.constBegin(); it != testCases.constEnd(); ++it) {
+ const auto c = it.value();
+ if (c.strictResult == c.strictExpectation && c.sloppyResult == c.sloppyExpectation)
+ continue;
+ auto report = [&] (TestCase::Result expected, TestCase::Result result, const char *s) {
+ if (result == TestCase::Crashes)
+ crashes << (it.key() + " crashed in " + s + " mode");
+ if (result == TestCase::Fails && expected == TestCase::Passes)
+ unexpectedFailures << (it.key() + " failed in " + s + " mode");
+ if (result == TestCase::Passes && expected == TestCase::Fails)
+ unexpectedPasses << (it.key() + " unexpectedly passed in " + s + " mode");
+ };
+ report(c.strictExpectation, c.strictResult, "strict");
+ report(c.sloppyExpectation, c.sloppyResult, "sloppy");
+ }
+ if (!crashes.isEmpty()) {
+ qDebug() << " Encountered" << crashes.size() << "crashes in the following files:";
+ for (const QString &f : qAsConst(crashes))
+ qDebug() << " " << f;
+ }
+ if (!unexpectedFailures.isEmpty()) {
+ qDebug() << " Encountered" << unexpectedFailures.size() << "unexpected failures in the following files:";
+ for (const QString &f : qAsConst(unexpectedFailures))
+ qDebug() << " " << f;
+ }
+ if (!unexpectedPasses.isEmpty()) {
+ qDebug() << " Encountered" << unexpectedPasses.size() << "unexpected passes in the following files:";
+ for (const QString &f : qAsConst(unexpectedPasses))
+ qDebug() << " " << f;
+ }
+ return crashes.isEmpty() && unexpectedFailures.isEmpty() && unexpectedPasses.isEmpty();
+}
+
+bool Test262Runner::loadTests()
+{
+ QDir dir(testDir + "/test");
+ if (!dir.exists()) {
+ qWarning() << "Could not load tests," << dir.path() << "does not exist.";
+ return false;
+ }
+
+ QString annexB = "annexB";
+ QString harness = "harness";
+ QString intl402 = "intl402";
+
+ int pathlen = dir.path().length() + 1;
+ QDirIterator it(dir, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ QString file = it.next().mid(pathlen);
+ if (!file.endsWith(".js"))
+ continue;
+ if (!filter.isEmpty() && !file.contains(filter))
+ continue;
+ if (file.startsWith(annexB) || file.startsWith(harness) || file.startsWith(intl402))
+ continue;
+
+ testCases.insert(file, TestCase{ file });
+ }
+ if (testCases.isEmpty()) {
+ qWarning() << "No tests to run.";
+ return false;
+ }
+
+ return true;
+}
+
+
+struct TestExpectationLine {
+ TestExpectationLine(const QByteArray &line);
+ enum State {
+ Fails,
+ SloppyFails,
+ StrictFails,
+ Skip,
+ Passes
+ } state;
+ QString testCase;
+
+ QByteArray toLine() const;
+ void update(const TestCase &testCase);
+
+ static TestExpectationLine fromTestCase(const TestCase &testCase);
+private:
+ TestExpectationLine() = default;
+ static State stateFromTestCase(const TestCase &testCase);
+};
+
+TestExpectationLine::TestExpectationLine(const QByteArray &line)
+{
+ int space = line.indexOf(' ');
+
+ testCase = QString::fromUtf8(space > 0 ? line.left(space) : line);
+ if (!testCase.endsWith(".js"))
+ testCase += ".js";
+
+ state = Fails;
+ if (space < 0)
+ return;
+ QByteArray qualifier = line.mid(space + 1);
+ if (qualifier == "skip")
+ state = Skip;
+ else if (qualifier == "strictFails")
+ state = StrictFails;
+ else if (qualifier == "sloppyFails")
+ state = SloppyFails;
+ else if (qualifier == "fails")
+ state = Fails;
+ else
+ qWarning() << "illegal format in TestExpectations, line" << line;
+}
+
+QByteArray TestExpectationLine::toLine() const {
+ const char *res = nullptr;
+ switch (state) {
+ case Fails:
+ res = " fails\n";
+ break;
+ case SloppyFails:
+ res = " sloppyFails\n";
+ break;
+ case StrictFails:
+ res = " strictFails\n";
+ break;
+ case Skip:
+ res = " skip\n";
+ break;
+ case Passes:
+ // no need for an entry
+ return QByteArray();
+ }
+ QByteArray result = testCase.toUtf8() + res;
+ return result;
+}
+
+void TestExpectationLine::update(const TestCase &testCase)
+{
+ Q_ASSERT(testCase.test == this->testCase);
+
+ State resultState = stateFromTestCase(testCase);
+ switch (resultState) {
+ case Fails:
+ // no improvement, don't update
+ break;
+ case SloppyFails:
+ if (state == Fails)
+ state = SloppyFails;
+ else if (state == StrictFails)
+ // we have a regression in sloppy mode, but strict now passes
+ state = Passes;
+ break;
+ case StrictFails:
+ if (state == Fails)
+ state = StrictFails;
+ else if (state == SloppyFails)
+ // we have a regression in strict mode, but sloppy now passes
+ state = Passes;
+ break;
+ case Skip:
+ Q_ASSERT(state == Skip);
+ // nothing to do
+ break;
+ case Passes:
+ state = Passes;
+ }
+}
+
+TestExpectationLine TestExpectationLine::fromTestCase(const TestCase &testCase)
+{
+ TestExpectationLine l;
+ l.testCase = testCase.test;
+ l.state = stateFromTestCase(testCase);
+ return l;
+}
+
+TestExpectationLine::State TestExpectationLine::stateFromTestCase(const TestCase &testCase)
+{
+ // keep skipped tests
+ if (testCase.skipTestCase)
+ return Skip;
+
+ bool strictFails = (testCase.strictResult == TestCase::Crashes || testCase.strictResult == TestCase::Fails);
+ bool sloppyFails = (testCase.sloppyResult == TestCase::Crashes || testCase.sloppyResult == TestCase::Fails);
+ if (strictFails && sloppyFails)
+ return Fails;
+ if (strictFails)
+ return StrictFails;
+ if (sloppyFails)
+ return SloppyFails;
+ return Passes;
+}
+
+
+void Test262Runner::loadTestExpectations()
+{
+ QFile file("TestExpectations");
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "Could not open TestExpectations file.";
+ return;
+ }
+
+ int line = 0;
+ while (!file.atEnd()) {
+ ++line;
+ QByteArray line = file.readLine().trimmed();
+ if (line.startsWith('#') || line.isEmpty())
+ continue;
+ TestExpectationLine expectation(line);
+ if (!filter.isEmpty() && !expectation.testCase.contains(filter))
+ continue;
+
+ if (!testCases.contains(expectation.testCase))
+ qWarning() << "Unknown test case" << expectation.testCase << "in TestExpectations file.";
+ //qDebug() << "TestExpectations:" << expectation.testCase << expectation.state;
+ TestCase &s = testCases[expectation.testCase];
+ switch (expectation.state) {
+ case TestExpectationLine::Fails:
+ s.strictExpectation = TestCase::Fails;
+ s.sloppyExpectation = TestCase::Fails;
+ break;
+ case TestExpectationLine::SloppyFails:
+ s.strictExpectation = TestCase::Passes;
+ s.sloppyExpectation = TestCase::Fails;
+ break;
+ case TestExpectationLine::StrictFails:
+ s.strictExpectation = TestCase::Fails;
+ s.sloppyExpectation = TestCase::Passes;
+ break;
+ case TestExpectationLine::Skip:
+ s.skipTestCase = true;
+ break;
+ case TestExpectationLine::Passes:
+ Q_UNREACHABLE();
+ }
+ }
+}
+
+void Test262Runner::updateTestExpectations()
+{
+ QFile file("TestExpectations");
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "Could not open TestExpectations file.";
+ return;
+ }
+
+ QTemporaryFile updatedExpectations;
+ updatedExpectations.open();
+
+ int line = 0;
+ while (!file.atEnd()) {
+ ++line;
+ QByteArray originalLine = file.readLine();
+ QByteArray line = originalLine.trimmed();
+ if (line.startsWith('#') || line.isEmpty()) {
+ updatedExpectations.write(originalLine);
+ continue;
+ }
+
+ TestExpectationLine expectation(line);
+// qDebug() << "checking: " << expectation.testCase;
+ if (!testCases.contains(expectation.testCase)) {
+ updatedExpectations.write(originalLine);
+ continue;
+ }
+ const TestCase &testcase = testCases.value(expectation.testCase);
+ expectation.update(testcase);
+
+ line = expectation.toLine();
+// qDebug() << "updated line:" << line;
+ updatedExpectations.write(line);
+ }
+ file.close();
+ updatedExpectations.close();
+ file.remove();
+ qDebug() << updatedExpectations.fileName() << file.fileName();
+ updatedExpectations.copy(file.fileName());
+ qDebug() << "Updated TestExpectations file written!";
+}
+
+void Test262Runner::writeTestExpectations()
+{
+ QFile file("TestExpectations");
+
+ QTemporaryFile expectations;
+ expectations.open();
+
+ for (auto c : qAsConst(testCases)) {
+ TestExpectationLine line = TestExpectationLine::fromTestCase(c);
+ expectations.write(line.toLine());
+ }
+
+ expectations.close();
+ if (file.exists())
+ file.remove();
+ qDebug() << expectations.fileName() << file.fileName();
+ expectations.copy(file.fileName());
+ qDebug() << "new TestExpectations file written!";
+
+}
+
+static bool executeTest(const QByteArray &data)
+{
+ QString testData = QString::fromUtf8(data);
+
+ QV4::ExecutionEngine vm;
+
+ QV4::Scope scope(&vm);
+ QV4::ScopedContext ctx(scope, vm.rootContext());
+
+ QV4::GlobalExtensions::init(vm.globalObject, QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
+
+ QV4::Script script(ctx, QV4::Compiler::ContextType::Global, testData, QString());
+ script.parse();
+
+ QV4::ScopedValue result(scope);
+ if (!scope.engine->hasException)
+ result = script.run();
+
+ if (scope.engine->hasException)
+ return false;
+ return true;
+}
+
+class SingleTest : public QRunnable
+{
+public:
+ SingleTest(Test262Runner *runner, const TestData &data)
+ : runner(runner), data(data)
+ {
+ command = runner->command;
+ }
+ void run();
+
+ void runExternalTest();
+
+ QString command;
+ Test262Runner *runner;
+ TestData data;
+};
+
+void SingleTest::run()
+{
+ if (!command.isEmpty()) {
+ runExternalTest();
+ return;
+ }
+
+ if (data.runInSloppyMode) {
+ bool ok = ::executeTest(data.content);
+ if (data.negative)
+ ok = !ok;
+
+ data.sloppyResult = ok ? TestCase::Passes : TestCase::Fails;
+ } else {
+ data.sloppyResult = TestCase::Skipped;
+ }
+ if (data.runInStrictMode) {
+ QByteArray c = "'use strict';\n" + data.content;
+ bool ok = ::executeTest(c);
+ if (data.negative)
+ ok = !ok;
+
+ data.strictResult = ok ? TestCase::Passes : TestCase::Fails;
+ } else {
+ data.strictResult = TestCase::Skipped;
+ }
+ runner->addResult(data);
+}
+
+void SingleTest::runExternalTest()
+{
+ auto runTest = [=] (const char *header, TestCase::Result *result) {
+ QTemporaryFile tempFile;
+ tempFile.open();
+ tempFile.write(header);
+ tempFile.write(data.content);
+ tempFile.close();
+
+ QProcess process;
+// if (flags & Verbose)
+// process.setReadChannelMode(QProcess::ForwardedChannels);
+
+ process.start(command, QStringList(tempFile.fileName()));
+ if (!process.waitForFinished(-1) || process.error() == QProcess::FailedToStart) {
+ qWarning() << "Could not execute" << command;
+ *result = TestCase::Crashes;
+ }
+ if (process.exitStatus() != QProcess::NormalExit) {
+ *result = TestCase::Crashes;
+ }
+ bool ok = (process.exitCode() == EXIT_SUCCESS);
+ if (data.negative)
+ ok = !ok;
+ *result = ok ? TestCase::Passes : TestCase::Fails;
+ };
+
+ if (data.runInSloppyMode)
+ runTest("", &data.sloppyResult);
+ if (data.runInStrictMode)
+ runTest("'use strict';\n", &data.strictResult);
+
+ runner->addResult(data);
+}
+
+int Test262Runner::runSingleTest(TestCase testCase)
+{
+ TestData data = getTestData(testCase);
+// qDebug() << "starting test" << data.test;
+
+ if (data.isExcluded || data.async || data.runAsModuleCode)
+ return 0;
+
+ if (threadPool) {
+ SingleTest *test = new SingleTest(this, data);
+ threadPool->start(test);
+ return 0;
+ }
+ SingleTest test(this, data);
+ test.run();
+ return 0;
+}
+
+void Test262Runner::addResult(TestCase result)
+{
+ {
+ QMutexLocker locker(&mutex);
+ Q_ASSERT(result.strictExpectation == testCases[result.test].strictExpectation);
+ Q_ASSERT(result.sloppyExpectation == testCases[result.test].sloppyExpectation);
+ testCases[result.test] = result;
+ }
+
+ if (!(flags & Verbose))
+ return;
+
+ QString test = result.test;
+ if (result.strictResult == TestCase::Skipped) {
+ ;
+ } else if (result.strictResult == TestCase::Crashes) {
+ qDebug() << "FAIL:" << test << "crashed in strict mode!";
+ } else if ((result.strictResult == TestCase::Fails) && (result.strictExpectation == TestCase::Fails)) {
+ qDebug() << "PASS:" << test << "failed in strict mode as expected";
+ } else if ((result.strictResult == TestCase::Passes) == (result.strictExpectation == TestCase::Passes)) {
+ qDebug() << "PASS:" << test << "passed in strict mode";
+ } else if (!(result.strictExpectation == TestCase::Fails)) {
+ qDebug() << "FAIL:" << test << "failed in strict mode";
+ } else {
+ qDebug() << "XPASS:" << test << "unexpectedly passed in strict mode";
+ }
+
+ if (result.sloppyResult == TestCase::Skipped) {
+ ;
+ } else if (result.sloppyResult == TestCase::Crashes) {
+ qDebug() << "FAIL:" << test << "crashed in sloppy mode!";
+ } else if ((result.sloppyResult == TestCase::Fails) && (result.sloppyExpectation == TestCase::Fails)) {
+ qDebug() << "PASS:" << test << "failed in sloppy mode as expected";
+ } else if ((result.sloppyResult == TestCase::Passes) == (result.sloppyExpectation == TestCase::Passes)) {
+ qDebug() << "PASS:" << test << "passed in sloppy mode";
+ } else if (!(result.sloppyExpectation == TestCase::Fails)) {
+ qDebug() << "FAIL:" << test << "failed in sloppy mode";
+ } else {
+ qDebug() << "XPASS:" << test << "unexpectedly passed in sloppy mode";
+ }
+}
+
+TestData Test262Runner::getTestData(const TestCase &testCase)
+{
+ QFile testFile(testDir + "/test/" + testCase.test);
+ if (!testFile.open(QFile::ReadOnly)) {
+ qWarning() << "wrong test file" << testCase.test;
+ exit(1);
+ }
+ QByteArray content = testFile.readAll();
+ content.replace(QByteArrayLiteral("\r\n"), "\n");
+
+// qDebug() << "parsing test file" << test;
+
+ TestData data(testCase);
+ parseYaml(content, &data);
+
+ data.content += harness("assert.js");
+ data.content += harness("sta.js");
+
+ for (QByteArray inc : qAsConst(data.includes)) {
+ inc = inc.trimmed();
+ data.content += harness(inc);
+ }
+
+ if (data.async)
+ data.content += harness("doneprintHandle.js");
+
+ data.content += content;
+
+ return data;
+}
+
+struct YamlSection {
+ YamlSection(const QByteArray &yaml, const char *sectionName);
+
+ bool contains(const char *keyword) const;
+ QList<QByteArray> keywords() const;
+
+ QByteArray yaml;
+ int start = -1;
+ int length = 0;
+ bool shortSection = false;
+};
+
+YamlSection::YamlSection(const QByteArray &yaml, const char *sectionName)
+ : yaml(yaml)
+{
+ start = yaml.indexOf(sectionName);
+ if (start < 0)
+ return;
+ start += static_cast<int>(strlen(sectionName));
+ int end = yaml.indexOf('\n', start + 1);
+ if (end < 0)
+ end = yaml.length();
+
+ int s = yaml.indexOf('[', start);
+ if (s > 0 && s < end) {
+ shortSection = true;
+ start = s + 1;
+ end = yaml.indexOf(']', s);
+ } else {
+ while (end < yaml.size() - 1 && yaml.at(end + 1) == ' ')
+ end = yaml.indexOf('\n', end + 1);
+ }
+ length = end - start;
+}
+
+bool YamlSection::contains(const char *keyword) const
+{
+ if (start < 0)
+ return false;
+ int idx = yaml.indexOf(keyword, start);
+ if (idx >= start && idx < start + length)
+ return true;
+ return false;
+}
+
+QList<QByteArray> YamlSection::keywords() const
+{
+ if (start < 0)
+ return QList<QByteArray>();
+
+ QByteArray content = yaml.mid(start, length);
+ QList<QByteArray> keywords;
+ if (shortSection) {
+ keywords = content.split(',');
+ } else {
+ const QList<QByteArray> list = content.split('\n');
+ for (const QByteArray &l : list) {
+ int i = 0;
+ while (i < l.size() && (l.at(i) == ' ' || l.at(i) == '-'))
+ ++i;
+ QByteArray entry = l.mid(i);
+ if (!entry.isEmpty())
+ keywords.append(entry);
+ }
+ }
+// qDebug() << "keywords:" << keywords;
+ return keywords;
+}
+
+
+void Test262Runner::parseYaml(const QByteArray &content, TestData *data)
+{
+ int start = content.indexOf("/*---");
+ if (start < 0)
+ return;
+ start += sizeof("/*---");
+
+ int end = content.indexOf("---*/");
+ if (end < 0)
+ return;
+
+ QByteArray yaml = content.mid(start, end - start);
+
+ if (yaml.contains("negative:"))
+ data->negative = true;
+
+ YamlSection flags(yaml, "flags:");
+ data->runInSloppyMode = !flags.contains("onlyStrict");
+ data->runInStrictMode = !flags.contains("noStrict") && !flags.contains("raw");
+ data->runAsModuleCode = flags.contains("module");
+ data->async = flags.contains("async");
+
+ YamlSection includes(yaml, "includes:");
+ data->includes = includes.keywords();
+
+ YamlSection features = YamlSection(yaml, "features:");
+
+ const char **f = excludedFeatures;
+ while (*f) {
+ if (features.contains(*f)) {
+ data->isExcluded = true;
+ break;
+ }
+ ++f;
+ }
+
+// qDebug() << "Yaml:\n" << yaml;
+}
+
+QByteArray Test262Runner::harness(const QByteArray &name)
+{
+ if (harnessFiles.contains(name))
+ return harnessFiles.value(name);
+
+ QFile h(testDir + QLatin1String("/harness/") + name);
+ if (!h.open(QFile::ReadOnly)) {
+ qWarning() << "Illegal test harness file" << name;
+ exit(1);
+ }
+
+ QByteArray content = h.readAll();
+ harnessFiles.insert(name, content);
+ return content;
+}
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.h b/tests/auto/qml/ecmascripttests/qjstest/test262runner.h
new file mode 100644
index 0000000000..6b64298f42
--- /dev/null
+++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the V4VM module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TEST262RUNNER_H
+#define TEST262RUNNER_H
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qset.h>
+#include <qmap.h>
+#include <qmutex.h>
+#include <qthreadpool.h>
+
+struct TestCase {
+ TestCase() = default;
+ TestCase(const QString &test)
+ : test(test) {}
+ enum Result {
+ Skipped,
+ Passes,
+ Fails,
+ Crashes
+ };
+ bool skipTestCase = false;
+ Result strictExpectation = Passes;
+ Result sloppyExpectation = Passes;
+ Result strictResult = Skipped;
+ Result sloppyResult = Skipped;
+
+ QString test;
+};
+
+struct TestData : TestCase {
+ TestData(const TestCase &testCase)
+ : TestCase(testCase) {}
+ // flags
+ bool negative = false;
+ bool runInStrictMode = true;
+ bool runInSloppyMode = true;
+ bool runAsModuleCode = false;
+ bool async = false;
+
+ bool isExcluded = false;
+
+ QList<QByteArray> includes;
+
+ QByteArray content;
+};
+
+class Test262Runner
+{
+public:
+ Test262Runner(const QString &command, const QString &testDir);
+ ~Test262Runner();
+
+ enum Mode {
+ Sloppy = 0,
+ Strict = 1
+ };
+
+ enum Flags {
+ Verbose = 0x1,
+ Parallel = 0x2,
+ ForceBytecode = 0x4,
+ ForceJIT = 0x8,
+ WithTestExpectations = 0x10,
+ UpdateTestExpectations = 0x20,
+ WriteTestExpectations = 0x40,
+ };
+ void setFlags(int f) { flags = f; }
+
+ void setFilter(const QString &f) { filter = f; }
+
+ void cat();
+ bool run();
+
+ bool report();
+
+private:
+ friend class SingleTest;
+ bool loadTests();
+ void loadTestExpectations();
+ void updateTestExpectations();
+ void writeTestExpectations();
+ int runSingleTest(TestCase testCase);
+
+ TestData getTestData(const TestCase &testCase);
+ void parseYaml(const QByteArray &content, TestData *data);
+
+ QByteArray harness(const QByteArray &name);
+
+ void addResult(TestCase result);
+
+ QString command;
+ QString testDir;
+ int flags = 0;
+
+ QMutex mutex;
+ QString filter;
+
+ QMap<QString, TestCase> testCases;
+ QHash<QByteArray, QByteArray> harnessFiles;
+
+ QThreadPool *threadPool = nullptr;
+};
+
+
+#endif
diff --git a/tests/auto/qml/ecmascripttests/test262 b/tests/auto/qml/ecmascripttests/test262
-Subproject 40b4f28e98c416a092e26aa17489bf94ccb8bf4
+Subproject 3c69133cc419840c1be34638039cd8c48a7ef58
diff --git a/tests/auto/qml/ecmascripttests/test262.py b/tests/auto/qml/ecmascripttests/test262.py
index e055c7a8e7..19551e3ba2 100755
--- a/tests/auto/qml/ecmascripttests/test262.py
+++ b/tests/auto/qml/ecmascripttests/test262.py
@@ -61,6 +61,35 @@ from parseTestRecord import parseTestRecord, stripHeader
from packagerConfig import *
+# excluded features that are still experimental and not part of any official standard
+# see also the features.txt file in test262/
+excludedFeatures = [
+ "BigInt",
+ "class-fields-public",
+ "class-fields-private",
+ "Promise.prototype.finally",
+ "async-iteration",
+ "Symbol.asyncIterator",
+ "object-rest",
+ "object-spread",
+ "optional-catch-binding",
+ "regexp-dotall",
+ "regexp-lookbehind",
+ "regexp-named-groups",
+ "regexp-unicode-property-escapes",
+ "Atomics",
+ "SharedArrayBuffer",
+ "Array.prototype.flatten",
+ "Array.prototype.flatMap",
+ "string-trimming",
+ "String.prototype.trimEnd",
+ "String.prototype.trimStart",
+ "numeric-separator-literal",
+
+ # optional features, not supported by us
+ "caller"
+]
+
# ############# Helpers needed for parallel multi-process test execution ############
def runTest(case, args):
@@ -95,19 +124,19 @@ class TestExpectations:
continue
record = line.split()
if len(record) == 1:
- self.testsToSkip.append(record[0])
+ self.failingTests.append(record[0])
else:
test = record[0]
expectation = record[1]
- if expectation == "failing":
- self.failingTests.append(test)
+ if expectation == "skip":
+ self.testsToSkip.append(test)
f.close()
def update(self, progress):
- unexpectedPasses = [c.case.name[-1] for c in progress.failed_tests if c.case.IsNegative()]
+ unexpectedPasses = [c.case.name for c in progress.failed_tests if c.case.IsNegative()]
# If a test fails that we expected to fail, then it actually passed unexpectedly.
- failures = [c.case.name[-1] for c in progress.failed_tests if not c.case.IsNegative()]
+ failures = [c.case.name for c in progress.failed_tests if not c.case.IsNegative()]
for failure in failures:
if failure in self.failingTests:
unexpectedPasses.append(failure)
@@ -116,7 +145,7 @@ class TestExpectations:
lines = f.read().splitlines()
oldLen = len(lines)
for result in unexpectedPasses:
- expectationLine = result + " failing"
+ expectationLine = result
try:
lines.remove(expectationLine)
except ValueError:
@@ -277,14 +306,17 @@ class TestCase(object):
f.close()
testRecord = parseTestRecord(self.contents, name)
self.test = testRecord["test"]
+ if 'features' in testRecord:
+ self.features = testRecord["features"];
+ else:
+ self.features = []
del testRecord["test"]
del testRecord["header"]
- del testRecord["commentary"]
self.testRecord = testRecord;
def GetName(self):
- return path.join(*self.name)
+ return self.name
def GetMode(self):
if self.strict_mode:
@@ -310,14 +342,20 @@ class TestCase(object):
def IsNoStrict(self):
return 'noStrict' in self.testRecord
+ def IsExperimental(self):
+ for f in self.features:
+ if excludedFeatures.count(f) >= 1:
+ return True;
+ return False
+
def GetSource(self):
# "var testDescrip = " + str(self.testRecord) + ';\n\n' + \
- source = self.suite.GetInclude("cth.js") + \
+ source = self.suite.GetInclude("assert.js") + \
self.suite.GetInclude("sta.js") + \
- self.suite.GetInclude("ed.js") + \
- self.suite.GetInclude("testBuiltInObject.js") + \
- self.suite.GetInclude("testIntl.js") + \
self.test + '\n'
+ if 'includes' in self.testRecord:
+ for inc in self.testRecord['includes']:
+ source += self.suite.GetInclude(inc);
if self.strict_mode:
source = '"use strict";\nvar strict_mode = true;\n' + source
@@ -403,14 +441,23 @@ class TestSuite(object):
def __init__(self, root, strict_only, non_strict_only, unmarked_default, load_expectations):
# TODO: derive from packagerConfig.py
- self.test_root = path.join(root, 'test', 'suite')
- self.lib_root = path.join(root, 'test', 'harness')
+ self.test_root = path.join(root, 'test')
+ self.lib_root = path.join(root, 'harness')
self.strict_only = strict_only
self.non_strict_only = non_strict_only
self.unmarked_default = unmarked_default
self.include_cache = { }
self.expectations = TestExpectations(load_expectations)
+ def IsExcludedTest(self, path):
+ if path.startswith('annexB'):
+ return True;
+ if path.startswith('harness'):
+ return True;
+ if path.startswith('intl402'):
+ return True;
+ return False;
+
def Validate(self):
if not path.exists(self.test_root):
ReportError("No test repository found")
@@ -459,25 +506,25 @@ class TestSuite(object):
else:
logging.warning("Unexpected path %s", full_path)
rel_path = full_path
- if self.ShouldRun(rel_path, tests) and not rel_path.startswith("intl402" + os.sep):
+ if self.ShouldRun(rel_path, tests) and not self.IsExcludedTest(rel_path):
basename = path.basename(full_path)[:-3]
- name = rel_path.split(path.sep)[:-1] + [basename]
- if EXCLUDE_LIST.count(basename) >= 1 or self.expectations.testsToSkip.count(basename) >= 1:
- print 'Excluded: ' + basename
+ name = rel_path.replace('.js', '')
+ if EXCLUDE_LIST.count(basename) >= 1 or self.expectations.testsToSkip.count(name) >= 1:
+ print 'Excluded: ' + rel_path
else:
if not self.non_strict_only:
strict_case = TestCase(self, name, full_path, True)
- if self.expectations.failingTests.count(basename) >= 1:
+ if self.expectations.failingTests.count(name) >= 1:
strict_case.NegateResult()
- if not strict_case.IsNoStrict():
+ if not strict_case.IsNoStrict() and not strict_case.IsExperimental():
if strict_case.IsOnlyStrict() or \
self.unmarked_default in ['both', 'strict']:
cases.append(strict_case)
if not self.strict_only:
non_strict_case = TestCase(self, name, full_path, False)
- if self.expectations.failingTests.count(basename) >= 1:
+ if self.expectations.failingTests.count(name) >= 1:
non_strict_case.NegateResult()
- if not non_strict_case.IsOnlyStrict():
+ if not non_strict_case.IsOnlyStrict() and not non_strict_case.IsExperimental():
if non_strict_case.IsNoStrict() or \
self.unmarked_default in ['both', 'non_strict']:
cases.append(non_strict_case)
diff --git a/tests/auto/qml/ecmascripttests/testcase.pro b/tests/auto/qml/ecmascripttests/testcase.pro
new file mode 100644
index 0000000000..5bf7ecd696
--- /dev/null
+++ b/tests/auto/qml/ecmascripttests/testcase.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+TARGET = tst_ecmascripttests
+QT += testlib qml-private
+macos:CONFIG -= app_bundle
+SOURCES += tst_ecmascripttests.cpp qjstest/test262runner.cpp
+HEADERS += qjstest/test262runner.h
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+# The ES test suite takes approximately 5 mins to run, on a fairly
+# vanilla developer machine, so the default watchdog timer kills the
+# test some of the time. Fix by raising time-out to 400s when
+# invoking tst_ecmascripttests:
+checkenv.name = QTEST_FUNCTION_TIMEOUT
+checkenv.value = 500000
+QT_TOOL_ENV += checkenv
diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
index 0d58d045b9..418dd4dc53 100644
--- a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
+++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
@@ -30,55 +30,37 @@
#include <QtTest/QtTest>
#include <QProcess>
#include <QLibraryInfo>
+#include <qjstest/test262runner.h>
class tst_EcmaScriptTests : public QObject
{
Q_OBJECT
- void runTests(bool interpret);
-
private slots:
void runInterpreted();
void runJitted();
};
-void tst_EcmaScriptTests::runTests(bool interpret)
-{
-#if defined(Q_OS_LINUX) && defined(Q_PROCESSOR_X86_64)
- QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
- if (interpret)
- env.insert("QV4_FORCE_INTERPRETER", "1");
- else
- env.insert("QV4_JIT_CALL_THRESHOLD", "0");
-
- QProcess process;
- process.setProcessChannelMode(QProcess::ForwardedChannels);
- process.setWorkingDirectory(QLatin1String(SRCDIR));
- process.setProgram("python");
- process.setProcessEnvironment(env);
- process.setArguments(QStringList() << "test262.py" << "--command=" + QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmljs" << "--parallel" << "--with-test-expectations");
-
- qDebug() << "Going to run" << process.program() << process.arguments() << "in" << process.workingDirectory();
-
- process.start();
- QVERIFY(process.waitForStarted());
- const int timeoutInMSecs = 20 * 60 * 1000;
- QVERIFY2(process.waitForFinished(timeoutInMSecs), "Tests did not terminate in time -- see output above for details");
- QVERIFY2(process.exitStatus() == QProcess::NormalExit, "Running the test harness failed -- see output above for details");
- QVERIFY2(process.exitCode() == 0, "Tests failed -- see output above for details");
-#else
- QSKIP("Currently the ecmascript tests are only run on Linux/x86-64");
-#endif
-}
-
void tst_EcmaScriptTests::runInterpreted()
{
- runTests(true);
+#if defined(Q_PROCESSOR_X86_64) && !defined(Q_OS_DARWIN)
+ QDir::setCurrent(QLatin1String(SRCDIR));
+ Test262Runner runner(QString(), "test262");
+ runner.setFlags(Test262Runner::ForceBytecode|Test262Runner::WithTestExpectations|Test262Runner::Parallel|Test262Runner::Verbose);
+ bool result = runner.run();
+ QVERIFY(result);
+#endif
}
void tst_EcmaScriptTests::runJitted()
{
- runTests(false);
+#if defined(Q_PROCESSOR_X86_64) && !defined(Q_OS_DARWIN)
+ QDir::setCurrent(QLatin1String(SRCDIR));
+ Test262Runner runner(QString(), "test262");
+ runner.setFlags(Test262Runner::ForceJIT|Test262Runner::WithTestExpectations|Test262Runner::Parallel|Test262Runner::Verbose);
+ bool result = runner.run();
+ QVERIFY(result);
+#endif
}
QTEST_GUILESS_MAIN(tst_EcmaScriptTests)
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index bb923951a8..935fd53a42 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -39,6 +39,7 @@
#include <qqmlcomponent.h>
#include <stdlib.h>
#include <private/qv4alloca_p.h>
+#include <private/qjsvalue_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -206,7 +207,24 @@ private slots:
void scriptScopes();
+ void binaryNumbers();
+ void octalNumbers();
+
+ void incrementAfterNewline();
+
+ void deleteInsideForIn();
+
+ void functionToString_data();
+ void functionToString();
+
void protoChanges_QTBUG68369();
+ void multilineStrings();
+
+ void throwError();
+ void mathMinMax();
+
+public:
+ Q_INVOKABLE QJSValue throwingCppMethod();
signals:
void testSignal();
@@ -942,6 +960,7 @@ void tst_QJSEngine::globalObjectProperties_enumerate()
<< "decodeURIComponent"
<< "Date"
<< "Array"
+ << "Symbol"
<< "escape"
<< "unescape"
<< "SyntaxError"
@@ -958,6 +977,10 @@ void tst_QJSEngine::globalObjectProperties_enumerate()
<< "Uint32Array"
<< "Float32Array"
<< "Float64Array"
+ << "Set"
+ << "Map"
+ << "Reflect"
+ << "Proxy"
;
QSet<QString> actualNames;
{
@@ -3207,9 +3230,7 @@ void tst_QJSEngine::threadedEngine()
void tst_QJSEngine::functionDeclarationsInConditionals()
{
- // Even though this is bad practice (and test262 covers it with best practices test cases),
- // we do allow for function declarations in if and while statements, as unfortunately that's
- // real world JavaScript. (QTBUG-33064 for example)
+ // Visibility of function declarations inside blocks is limited to the block
QJSEngine eng;
QJSValue result = eng.evaluate("if (true) {\n"
" function blah() { return false; }\n"
@@ -3217,8 +3238,7 @@ void tst_QJSEngine::functionDeclarationsInConditionals()
" function blah() { return true; }\n"
"}\n"
"blah();");
- QVERIFY(result.isBool());
- QCOMPARE(result.toBool(), true);
+ QVERIFY(result.isError());
}
void tst_QJSEngine::arrayPop_QTBUG_35979()
@@ -4169,6 +4189,88 @@ void tst_QJSEngine::scriptScopes()
QCOMPARE(use.toInt(), 42);
}
+void tst_QJSEngine::binaryNumbers()
+{
+ QJSEngine engine;
+
+ QJSValue result = engine.evaluate("0b1001");
+ QVERIFY(result.isNumber());
+ QVERIFY(result.toNumber() == 9);
+
+ result = engine.evaluate("0B1001");
+ QVERIFY(result.isNumber());
+ QVERIFY(result.toNumber() == 9);
+
+ result = engine.evaluate("0b2");
+ QVERIFY(result.isError());
+}
+
+void tst_QJSEngine::octalNumbers()
+{
+ QJSEngine engine;
+
+ QJSValue result = engine.evaluate("0o11");
+ QVERIFY(result.isNumber());
+ QVERIFY(result.toNumber() == 9);
+
+ result = engine.evaluate("0O11");
+ QVERIFY(result.isNumber());
+ QVERIFY(result.toNumber() == 9);
+
+ result = engine.evaluate("0o9");
+ QVERIFY(result.isError());
+}
+
+void tst_QJSEngine::incrementAfterNewline()
+{
+ QJSEngine engine;
+
+ QJSValue result = engine.evaluate("var x = 0; if (\n++x) x; else -x;");
+ QVERIFY(result.isNumber());
+ QVERIFY(result.toNumber() == 1);
+
+ result = engine.evaluate("var x = 0; if (\n--x) x; else -x;");
+ QVERIFY(result.isNumber());
+ QVERIFY(result.toNumber() == -1);
+}
+
+void tst_QJSEngine::deleteInsideForIn()
+{
+ QJSEngine engine;
+
+ QJSValue iterationCount = engine.evaluate(
+ "var o = { a: 1, b: 2, c: 3, d: 4};\n"
+ "var count = 0;\n"
+ "for (var prop in o) { count++; delete o[prop]; }\n"
+ "count");
+ QVERIFY(iterationCount.isNumber());
+ QCOMPARE(iterationCount.toInt(), 4);
+}
+
+void tst_QJSEngine::functionToString_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("expectedString");
+
+ QTest::newRow("named function") << QString::fromLatin1("function f() {}; f.toString()")
+ << QString::fromLatin1("function f() { [code] }");
+ QTest::newRow("anonymous function") << QString::fromLatin1("(function() {}).toString()")
+ << QString::fromLatin1("function() { [code] }");
+}
+
+// Tests that function.toString() prints the function's name.
+void tst_QJSEngine::functionToString()
+{
+ QFETCH(QString, source);
+ QFETCH(QString, expectedString);
+
+ QJSEngine engine;
+ engine.installExtensions(QJSEngine::AllExtensions);
+ QJSValue evaluationResult = engine.evaluate(source);
+ QVERIFY(!evaluationResult.isError());
+ QCOMPARE(evaluationResult.toString(), expectedString);
+}
+
void tst_QJSEngine::protoChanges_QTBUG68369()
{
QJSEngine engine;
@@ -4185,6 +4287,62 @@ void tst_QJSEngine::protoChanges_QTBUG68369()
QVERIFY(ok.toBool() == true);
}
+void tst_QJSEngine::multilineStrings()
+{
+ QJSEngine engine;
+ QJSValue result = engine.evaluate(
+ "var x = `a\nb`; x;"
+ );
+ QVERIFY(result.isString());
+ QVERIFY(result.toString() == QStringLiteral("a\nb"));
+
+}
+
+void tst_QJSEngine::throwError()
+{
+ QJSEngine engine;
+ QJSValue wrappedThis = engine.newQObject(this);
+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
+ engine.globalObject().setProperty("testCase", wrappedThis);
+
+ QJSValue result = engine.evaluate(
+ "function test(){\n"
+ "try {\n"
+ " return testCase.throwingCppMethod();\n"
+ "} catch (error) {\n"
+ " return error;\n"
+ "}\n"
+ "return \"not reached!\";\n"
+ "}\n"
+ "test();"
+ );
+ QVERIFY(result.isError());
+ QCOMPARE(result.property("lineNumber").toString(), "3");
+ QCOMPARE(result.property("message").toString(), "blub");
+ QVERIFY(!result.property("stack").isUndefined());
+}
+
+QJSValue tst_QJSEngine::throwingCppMethod()
+{
+ qjsEngine(this)->throwError("blub");
+ return QJSValue(47);
+}
+
+void tst_QJSEngine::mathMinMax()
+{
+ QJSEngine engine;
+
+ QJSValue result = engine.evaluate("var a = .5; Math.min(1, 2, 3.5 + a, '5')");
+ QCOMPARE(result.toNumber(), 1.0);
+ QVERIFY(QJSValuePrivate::getValue(&result) != nullptr);
+ QVERIFY(QJSValuePrivate::getValue(&result)->isInteger());
+
+ result = engine.evaluate("var a = .5; Math.max('0', 1, 2, 3.5 + a)");
+ QCOMPARE(result.toNumber(), 4.0);
+ QVERIFY(QJSValuePrivate::getValue(&result) != nullptr);
+ QVERIFY(QJSValuePrivate::getValue(&result)->isInteger());
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 6587408ae4..6384369ef0 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -1638,7 +1638,7 @@ void tst_QJSValue::getSetPrototype_evalCyclicPrototype()
QJSEngine eng;
QJSValue ret = eng.evaluate("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
QCOMPARE(ret.isError(), true);
- QCOMPARE(ret.toString(), QLatin1String("TypeError: Cyclic __proto__ value"));
+ QCOMPARE(ret.toString(), QLatin1String("TypeError: Could not change prototype."));
}
void tst_QJSValue::getSetPrototype_eval()
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 3433b56864..1bd23573b0 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -71,6 +71,7 @@ PRIVATETESTS += \
qqmlobjectmodel \
qv4assembler \
qv4mm \
+ qv4identifiertable \
ecmascripttests \
bindingdependencyapi
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index f5905758f3..d363180c06 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -106,7 +106,7 @@ struct TestCompiler
{
closeMapping();
testFilePath = baseDirectory + QStringLiteral("/test.qml");
- cacheFilePath = baseDirectory + QStringLiteral("/test.qmlc");
+ cacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
mappedFile.setFileName(cacheFilePath);
}
@@ -499,7 +499,7 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 42);
- QFile cacheFile(testFilePath + "c");
+ QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
@@ -514,7 +514,7 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 100);
- QFile cacheFile(selectedTestFilePath + "c");
+ QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(selectedTestFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
}
@@ -667,7 +667,7 @@ void tst_qmldiskcache::stableOrderOfDependentCompositeTypes()
QVERIFY2(firstDependentTypeClassName.contains("QMLTYPE"), firstDependentTypeClassName.constData());
QVERIFY2(secondDependentTypeClassName.contains("QMLTYPE"), secondDependentTypeClassName.constData());
- const QString testFileCachePath = testFilePath + QLatin1Char('c');
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -745,7 +745,7 @@ void tst_qmldiskcache::singletonDependency()
QCOMPARE(obj->property("value").toInt(), 42);
}
- const QString testFileCachePath = testFilePath + QLatin1Char('c');
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -802,7 +802,7 @@ void tst_qmldiskcache::cppRegisteredSingletonDependency()
QCOMPARE(value.toInt(), 42);
}
- const QString testFileCachePath = testFilePath + QLatin1Char('c');
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
index 5941385c80..c393149f59 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -125,6 +125,9 @@ void tst_qmlmin::initTestCase()
invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml";
invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.1.qml";
invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.2.qml";
+ invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/FunExpr/fe-001.js";
+ invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js";
+ invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
}
QStringList tst_qmlmin::findFiles(const QDir &d)
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 3a70890362..efd5bb571b 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -116,6 +116,7 @@ private slots:
void onDestructionCount();
void recursion();
void recursionContinuation();
+ void partialComponentCreation();
void callingContextForInitialProperties();
void setNonExistentInitialProperty();
void relativeUrl_data();
@@ -527,6 +528,29 @@ void tst_qqmlcomponent::recursionContinuation()
QVERIFY(object->property("success").toBool());
}
+void tst_qqmlcomponent::partialComponentCreation()
+{
+ const int maxCount = 17;
+ QQmlEngine engine;
+ QScopedPointer<QQmlComponent> components[maxCount];
+ QScopedPointer<QObject> objects[maxCount];
+ QQmlTestMessageHandler messageHandler;
+
+ QCOMPARE(engine.outputWarningsToStandardError(), true);
+
+ for (int i = 0; i < maxCount; i++) {
+ components[i].reset(new QQmlComponent(&engine, testFileUrl("QtObjectComponent.qml")));
+ objects[i].reset(components[i]->beginCreate(engine.rootContext()));
+ QVERIFY(objects[i].isNull() == false);
+ }
+ QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
+
+ for (int i = 0; i < maxCount; i++) {
+ components[i]->completeCreate();
+ }
+ QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
+}
+
class CallingContextCheckingClass : public QObject
{
Q_OBJECT
diff --git a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
index d19b6ecc41..d593f0dfa1 100644
--- a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
@@ -37,7 +37,7 @@
**
****************************************************************************/
-import QtQuick 2.8
+import QtQuick 2.12
Item {
id:root
@@ -48,6 +48,12 @@ Item {
}
LoggingCategory {
+ id: testCategoryStartingFromWarning
+ name: "qt.test.warning"
+ defaultLogLevel: LoggingCategory.Warning
+ }
+
+ LoggingCategory {
id: emptyCategory
}
@@ -57,8 +63,14 @@ Item {
console.info(testCategory, "console.info");
console.warn(testCategory, "console.warn");
console.error(testCategory, "console.error");
+ console.debug(testCategoryStartingFromWarning, "console.debug");
+ console.log(testCategoryStartingFromWarning, "console.log");
+ console.info(testCategoryStartingFromWarning, "console.info");
+ console.warn(testCategoryStartingFromWarning, "console.warn");
+ console.error(testCategoryStartingFromWarning, "console.error");
testCategory.name = "qt.test2";
+ testCategory.defaultLogLevel = LoggingCategory.Debug;
console.error(emptyCategory, "console.error");
}
diff --git a/tests/auto/qml/qqmlconsole/data/logging.qml b/tests/auto/qml/qqmlconsole/data/logging.qml
index d55c99bcbd..0764ad7545 100644
--- a/tests/auto/qml/qqmlconsole/data/logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/logging.qml
@@ -67,6 +67,8 @@ QtObject {
console.log(1, "pong!", new Object);
console.log(1, ["ping","pong"], new Object, 2);
+ console.log(contextStringListProperty);
+
try {
console.log(exception);
} catch (e) {
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index 0d915f98f8..77805bbbac 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -29,6 +29,7 @@
#include <QDebug>
#include <QQmlEngine>
#include <QQmlComponent>
+#include <QQmlContext>
#include <QLoggingCategory>
#include "../../shared/util.h"
@@ -74,18 +75,22 @@ void tst_qqmlconsole::logging()
QTest::ignoreMessage(QtDebugMsg, "{\"a\":\"hello\",\"d\":1}");
QTest::ignoreMessage(QtDebugMsg, "undefined");
QTest::ignoreMessage(QtDebugMsg, "12");
- QTest::ignoreMessage(QtDebugMsg, "function() { [code] }");
+ QTest::ignoreMessage(QtDebugMsg, "function e() { [code] }");
QTest::ignoreMessage(QtDebugMsg, "true");
// Printing QML object prints out the class/type of QML object with the memory address
// QTest::ignoreMessage(QtDebugMsg, "QtObject_QML_0(0xABCD..)");
// QTest::ignoreMessage(QtDebugMsg, "[object Object]");
QTest::ignoreMessage(QtDebugMsg, "1 pong! [object Object]");
QTest::ignoreMessage(QtDebugMsg, "1 [ping,pong] [object Object] 2");
+ QTest::ignoreMessage(QtDebugMsg, "[Hello,World]");
+
+ QScopedPointer<QQmlContext> loggingContext(new QQmlContext(engine.rootContext()));
+ QStringList stringList; stringList << QStringLiteral("Hello") << QStringLiteral("World");
+ loggingContext->setContextProperty("contextStringListProperty", stringList);
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
+ QScopedPointer<QObject> object(component.create(loggingContext.data()));
QVERIFY(object != nullptr);
- delete object;
}
void tst_qqmlconsole::categorized_logging()
@@ -107,8 +112,13 @@ void tst_qqmlconsole::categorized_logging()
QVERIFY(messageHandler.messages().contains("qt.test: console.info"));
QVERIFY(messageHandler.messages().contains("qt.test: console.warn"));
QVERIFY(messageHandler.messages().contains("qt.test: console.error"));
+ QVERIFY(!messageHandler.messages().contains("qt.test.warning: console.debug"));
+ QVERIFY(!messageHandler.messages().contains("qt.test.warning: console.log"));
+ QVERIFY(!messageHandler.messages().contains("qt.test.warning: console.info"));
+ QVERIFY(messageHandler.messages().contains("qt.test.warning: console.warn"));
+ QVERIFY(messageHandler.messages().contains("qt.test.warning: console.error"));
- QString emptyCategory = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(50).arg(5) +
+ QString emptyCategory = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(56).arg(5) +
"QML LoggingCategory: Declaring the name of the LoggingCategory is mandatory and cannot be changed later !";
QVERIFY(messageHandler.messages().contains(emptyCategory));
@@ -116,7 +126,11 @@ void tst_qqmlconsole::categorized_logging()
"QML LoggingCategory: The name of a LoggingCategory cannot be changed after the Item is created";
QVERIFY(messageHandler.messages().contains(changedCategory));
- QString useEmptyCategory = "default: " + QString::fromLatin1("%1:%2: ").arg(testUrl.toString()).arg(63) +
+ QString changedDefaultLogLevel = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(45).arg(5) +
+ "QML LoggingCategory: The defaultLogLevel of a LoggingCategory cannot be changed after the Item is created";
+ QVERIFY(messageHandler.messages().contains(changedDefaultLogLevel));
+
+ QString useEmptyCategory = "default: " + QString::fromLatin1("%1:%2: ").arg(testUrl.toString()).arg(75) +
"Error: A QmlLoggingCatgory was provided without a valid name";
QVERIFY(messageHandler.messages().contains(useEmptyCategory));
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 5999bc42e9..990e364c76 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -803,7 +803,7 @@ void tst_qqmlcontext::contextLeak()
{
QV4::Scope scope(ddata->jsWrapper.engine());
QV4::ScopedValue scriptContextWrapper(scope);
- scriptContextWrapper = context->importedScripts.valueRef()->as<QV4::Object>()->getIndexed(0);
+ scriptContextWrapper = context->importedScripts.valueRef()->as<QV4::Object>()->get(uint(0));
scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext();
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.8.qml b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.8.qml
new file mode 100644
index 0000000000..3f838fe8f2
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.8.qml
@@ -0,0 +1,16 @@
+import QtQml 2.0
+QtObject {
+ function tryWritingReadOnlySequence() {
+ try {
+ Qt.application.arguments.push("hello")
+ } catch (e) {
+
+ try {
+ Qt.application.arguments.sort()
+ } catch (e) {
+ return true
+ }
+ }
+ return false
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js
new file mode 100644
index 0000000000..500f04bec7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.js
@@ -0,0 +1,7 @@
+.pragma library
+var Shadowed = 2;
+var global = (function(){return this})()
+
+// set Shadowed on the global object as well. This should be different from
+// the variable above, as the library has it's on context
+global.Shadowed = 1;
diff --git a/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml
new file mode 100644
index 0000000000..7cac09d342
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/include_pragma_shadow.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+import "include_pragma_shadow.js" as Shadowed
+import "include_pragma_shadow.js" as Other
+
+Item {
+ property bool result
+
+ Component.onCompleted: {
+ result = false;
+ var global = (function(){return this})()
+ if (Shadowed.Shadowed === 2 && Other.Shadowed === 2 && global.Shadowed === 1)
+ result = true;
+ }
+}
+
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/importPragmaLibraryWithPragmaLibraryImports.js b/tests/auto/qml/qqmlecmascript/data/jsimport/importPragmaLibraryWithPragmaLibraryImports.js
index fa6497d99b..66e18ac2a9 100644
--- a/tests/auto/qml/qqmlecmascript/data/jsimport/importPragmaLibraryWithPragmaLibraryImports.js
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/importPragmaLibraryWithPragmaLibraryImports.js
@@ -7,5 +7,5 @@ function importIncrementedValue() {
i = i + 1;
// because LibraryImport is shared, and used in previous tests,
// the value will be large (already incremented a bunch of times).
- return (i + LibraryImport.importIncrementedValue());
+ return (i + LibraryImport.importIncrementedValue()); // 11 + 5
}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml
index 01f08dbdc3..8264b7229d 100644
--- a/tests/auto/qml/qqmlecmascript/data/jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml
@@ -3,5 +3,5 @@ import "importPragmaLibraryWithPragmaLibraryImports.js" as LibraryImport
QtObject {
id: root
- property int testValue: LibraryImport.importIncrementedValue(); // 10 + 1 + (7 due to previous tests) = 18
+ property int testValue: LibraryImport.importIncrementedValue(); // 16
}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml
index ae43e90210..0e314b20ea 100644
--- a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml
@@ -1,7 +1,7 @@
import QtQuick 2.0
-import com.nokia.JsModule 1.0
-import com.nokia.JsModule 1.0 as RenamedModule
+import com.qt.JsModule 1.0
+import com.qt.JsModule 1.0 as RenamedModule
import "testJsModuleImport.js" as TestJsModuleImport
QtObject {
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js
index 2d21953d2c..7440f610c1 100644
--- a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js
@@ -1,4 +1,4 @@
-.import com.nokia.JsModule 1.0 as JsModule
+.import com.qt.JsModule 1.0 as JsModule
function importedValue() {
return JsModule.ScriptAPI.greeting();
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleRemoteImport.js b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleRemoteImport.js
index e6e41bc6b2..6826f09da2 100644
--- a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleRemoteImport.js
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleRemoteImport.js
@@ -1,4 +1,4 @@
-.import com.nokia.JsRemoteModule 1.0 as JsModule
+.import com.qt.JsRemoteModule 1.0 as JsModule
function importedValue() {
return JsModule.ScriptAPI.greeting();
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsRemoteImport.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsRemoteImport.qml
index 4199bb022d..f49b38df23 100644
--- a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsRemoteImport.qml
+++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsRemoteImport.qml
@@ -1,7 +1,7 @@
import QtQuick 2.0
-import com.nokia.JsModule 1.0
-import com.nokia.JsModule 1.0 as RenamedModule
+import com.qt.JsModule 1.0
+import com.qt.JsModule 1.0 as RenamedModule
import "testJsModuleRemoteImport.js" as TestJsModuleImport
QtObject {
diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js b/tests/auto/qml/qqmlecmascript/data/lib/com/qt/JsModule/ScriptAPI.js
index b90033eeb4..b90033eeb4 100644
--- a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js
+++ b/tests/auto/qml/qqmlecmascript/data/lib/com/qt/JsModule/ScriptAPI.js
diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir b/tests/auto/qml/qqmlecmascript/data/lib/com/qt/JsModule/qmldir
index c33d1e7a0d..c33d1e7a0d 100644
--- a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir
+++ b/tests/auto/qml/qqmlecmascript/data/lib/com/qt/JsModule/qmldir
diff --git a/tests/auto/qml/qqmlecmascript/data/remote/com/nokia/JsRemoteModule/ScriptAPI.js b/tests/auto/qml/qqmlecmascript/data/remote/com/qt/JsRemoteModule/ScriptAPI.js
index b90033eeb4..b90033eeb4 100644
--- a/tests/auto/qml/qqmlecmascript/data/remote/com/nokia/JsRemoteModule/ScriptAPI.js
+++ b/tests/auto/qml/qqmlecmascript/data/remote/com/qt/JsRemoteModule/ScriptAPI.js
diff --git a/tests/auto/qml/qqmlecmascript/data/remote/com/nokia/JsRemoteModule/qmldir b/tests/auto/qml/qqmlecmascript/data/remote/com/qt/JsRemoteModule/qmldir
index c33d1e7a0d..c33d1e7a0d 100644
--- a/tests/auto/qml/qqmlecmascript/data/remote/com/nokia/JsRemoteModule/qmldir
+++ b/tests/auto/qml/qqmlecmascript/data/remote/com/qt/JsRemoteModule/qmldir
diff --git a/tests/auto/qml/qqmlecmascript/data/removeBindingsWithNoDependencies.qml b/tests/auto/qml/qqmlecmascript/data/removeBindingsWithNoDependencies.qml
new file mode 100644
index 0000000000..aacf16474d
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/removeBindingsWithNoDependencies.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+Item {
+ property rect placement: Qt.rect(0, 0, 100, 100)
+
+ function someFunction() { return 42; }
+
+ property rect partialPlacement
+ partialPlacement.x: someFunction()
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/tryStatement.3.qml b/tests/auto/qml/qqmlecmascript/data/tryStatement.3.qml
index 04b39f73d5..7f5a22a459 100644
--- a/tests/auto/qml/qqmlecmascript/data/tryStatement.3.qml
+++ b/tests/auto/qml/qqmlecmascript/data/tryStatement.3.qml
@@ -8,6 +8,6 @@ MyQmlObject {
return 321
}
- value: try { var p = go() } catch(e) { var p = defaultValue } finally { p == 123 }
+ qjsvalue: try { var p = go() } catch(e) { var p = defaultValue } finally { p == 123 }
}
diff --git a/tests/auto/qml/qqmlecmascript/data/tryStatement.4.qml b/tests/auto/qml/qqmlecmascript/data/tryStatement.4.qml
index 231aaf0683..39d4f74e97 100644
--- a/tests/auto/qml/qqmlecmascript/data/tryStatement.4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/tryStatement.4.qml
@@ -7,6 +7,6 @@ MyQmlObject {
return 321
}
- value: try { var p = go() } catch(e) { var p = defaultValue } finally { p == 321 }
+ qjsvalue: try { var p = go() } catch(e) { var p = defaultValue } finally { p == 321 }
}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index f40a9758f7..69b62c733c 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -49,6 +49,8 @@
#include <private/qv4object_p.h>
#include <private/qqmlcomponentattached_p.h>
#include <private/qv4objectiterator_p.h>
+#include <private/qqmlabstractbinding_p.h>
+#include <private/qqmlvaluetypeproxybinding_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -353,11 +355,11 @@ private slots:
void anotherNaN();
void callPropertyOnUndefined();
void jumpStrictNotEqualUndefined();
+ void removeBindingsWithNoDependencies();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
static void verifyContextLifetime(QQmlContextData *ctxt);
- QQmlEngine engine;
// When calling into JavaScript, the specific type of the return value can differ if that return
// value is a number. This is not only the case for non-integral numbers, or numbers that do not
@@ -384,13 +386,11 @@ void tst_qqmlecmascript::initTestCase()
{
QQmlDataTest::initTestCase();
registerTypes();
-
- QString dataDir(dataDirectory() + QLatin1Char('/') + QLatin1String("lib"));
- engine.addImportPath(dataDir);
}
void tst_qqmlecmascript::assignBasicTypes()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("assignBasicTypes.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
@@ -470,6 +470,7 @@ void tst_qqmlecmascript::assignDate()
QFETCH(QUrl, source);
QFETCH(int, timeOffset);
+ QQmlEngine engine;
QQmlComponent component(&engine, source);
QScopedPointer<QObject> obj(component.create());
MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data());
@@ -550,6 +551,7 @@ void tst_qqmlecmascript::exportDate()
void tst_qqmlecmascript::idShortcutInvalidates()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("idShortcutInvalidates.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -573,6 +575,7 @@ void tst_qqmlecmascript::idShortcutInvalidates()
void tst_qqmlecmascript::boolPropertiesEvaluateAsBool()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("boolPropertiesEvaluateAsBool.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -591,6 +594,7 @@ void tst_qqmlecmascript::boolPropertiesEvaluateAsBool()
void tst_qqmlecmascript::signalAssignment()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("signalAssignment.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -628,6 +632,7 @@ void tst_qqmlecmascript::signalAssignment()
void tst_qqmlecmascript::signalArguments()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("signalArguments.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -653,6 +658,7 @@ void tst_qqmlecmascript::signalArguments()
void tst_qqmlecmascript::methods()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("methods.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -706,6 +712,7 @@ void tst_qqmlecmascript::methods()
void tst_qqmlecmascript::bindingLoop()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("bindingLoop.qml"));
QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
@@ -747,6 +754,8 @@ void tst_qqmlecmascript::basicExpressions()
QFETCH(QVariant, result);
QFETCH(bool, nest);
+ QQmlEngine engine;
+
MyQmlObject object1;
MyQmlObject object2;
MyQmlObject object3;
@@ -779,6 +788,7 @@ void tst_qqmlecmascript::arrayExpressions()
QObject obj2;
QObject obj3;
+ QQmlEngine engine;
QQmlContext context(engine.rootContext());
context.setContextProperty("a", &obj1);
context.setContextProperty("b", &obj2);
@@ -798,6 +808,7 @@ void tst_qqmlecmascript::arrayExpressions()
// Tests that modifying a context property will reevaluate expressions
void tst_qqmlecmascript::contextPropertiesTriggerReeval()
{
+ QQmlEngine engine;
QQmlContext context(engine.rootContext());
MyQmlObject object1;
MyQmlObject object2;
@@ -861,6 +872,7 @@ void tst_qqmlecmascript::contextPropertiesTriggerReeval()
void tst_qqmlecmascript::objectPropertiesTriggerReeval()
{
+ QQmlEngine engine;
QQmlContext context(engine.rootContext());
MyQmlObject object1;
MyQmlObject object2;
@@ -927,6 +939,7 @@ void tst_qqmlecmascript::dependenciesWithFunctions()
void tst_qqmlecmascript::deferredProperties()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deferredProperties.qml"));
MyDeferredObject *object =
qobject_cast<MyDeferredObject *>(component.create());
@@ -950,6 +963,7 @@ void tst_qqmlecmascript::deferredProperties()
// Check errors on deferred properties are correctly emitted
void tst_qqmlecmascript::deferredPropertiesErrors()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deferredPropertiesErrors.qml"));
MyDeferredObject *object =
qobject_cast<MyDeferredObject *>(component.create());
@@ -958,7 +972,7 @@ void tst_qqmlecmascript::deferredPropertiesErrors()
QVERIFY(!object->objectProperty());
QVERIFY(!object->objectProperty2());
- QString warning = component.url().toString() + ":6:21: Unable to assign [undefined] to QObject*";
+ QString warning = component.url().toString() + ":6:5: Unable to assign [undefined] to QObject*";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
qmlExecuteDeferred(object);
@@ -969,6 +983,7 @@ void tst_qqmlecmascript::deferredPropertiesErrors()
void tst_qqmlecmascript::deferredPropertiesInComponents()
{
// Test that it works when the property is set inside and outside component
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deferredPropertiesInComponents.qml"));
QObject *object = component.create();
if (!object)
@@ -1002,6 +1017,7 @@ void tst_qqmlecmascript::deferredPropertiesInDestruction()
//Test that the component does not get created at all if creation is deferred until the containing context is destroyed
//Very specific operation ordering is needed for this to occur, currently accessing object from object destructor.
//
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deferredPropertiesInDestruction.qml"));
QObject *object = component.create();
if (!object)
@@ -1012,6 +1028,7 @@ void tst_qqmlecmascript::deferredPropertiesInDestruction()
void tst_qqmlecmascript::extensionObjects()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("extensionObjects.qml"));
MyExtendedObject *object =
qobject_cast<MyExtendedObject *>(component.create());
@@ -1037,6 +1054,7 @@ void tst_qqmlecmascript::extensionObjects()
void tst_qqmlecmascript::overrideExtensionProperties()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("extensionObjectsPropertyOverride.qml"));
OverrideDefaultPropertyObject *object =
qobject_cast<OverrideDefaultPropertyObject *>(component.create());
@@ -1049,6 +1067,8 @@ void tst_qqmlecmascript::overrideExtensionProperties()
void tst_qqmlecmascript::attachedProperties()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("attachedProperty.qml"));
QObject *object = component.create();
@@ -1090,6 +1110,8 @@ void tst_qqmlecmascript::attachedProperties()
void tst_qqmlecmascript::enums()
{
+ QQmlEngine engine;
+
// Existent enums
{
QQmlComponent component(&engine, testFileUrl("enums.1.qml"));
@@ -1119,13 +1141,13 @@ void tst_qqmlecmascript::enums()
{
QUrl file = testFileUrl("enums.2.qml");
QString w1 = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'MyEnum' for property 'MyUnregisteredEnumTypeObject::enumProperty'");
- QString w2 = QLatin1String("QQmlExpression: Expression ") + testFileUrl("enums.2.qml").toString() + QLatin1String(":9:21 depends on non-NOTIFYable properties:");
+ QString w2 = QLatin1String("QQmlExpression: Expression ") + testFileUrl("enums.2.qml").toString() + QLatin1String(":9:5 depends on non-NOTIFYable properties:");
QString w3 = QLatin1String(" MyUnregisteredEnumTypeObject::enumProperty");
- QString w4 = file.toString() + ":7:21: Unable to assign [undefined] to int";
- QString w5 = file.toString() + ":8:21: Unable to assign [undefined] to int";
- QString w6 = file.toString() + ":9:21: Unable to assign [undefined] to int";
- QString w7 = file.toString() + ":13:23: Unable to assign [undefined] to [unknown property type]";
- QString w8 = file.toString() + ":31:23: Unable to assign int to [unknown property type]";
+ QString w4 = file.toString() + ":7:5: Unable to assign [undefined] to int";
+ QString w5 = file.toString() + ":8:5: Unable to assign [undefined] to int";
+ QString w6 = file.toString() + ":9:5: Unable to assign [undefined] to int";
+ QString w7 = file.toString() + ":13:9: Unable to assign [undefined] to [unknown property type]";
+ QString w8 = file.toString() + ":31:9: Unable to assign int to [unknown property type]";
QTest::ignoreMessage(QtWarningMsg, qPrintable(w1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(w2));
QTest::ignoreMessage(QtWarningMsg, qPrintable(w3));
@@ -1196,6 +1218,7 @@ void tst_qqmlecmascript::enums()
void tst_qqmlecmascript::valueTypeFunctions()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("valueTypeFunctions.qml"));
MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
QVERIFY(obj != nullptr);
@@ -1211,6 +1234,8 @@ binding.
*/
void tst_qqmlecmascript::constantsOverrideBindings()
{
+ QQmlEngine engine;
+
// From ECMAScript
{
QQmlComponent component(&engine, testFileUrl("constantsOverrideBindings.1.qml"));
@@ -1288,6 +1313,7 @@ the original binding to be disabled.
*/
void tst_qqmlecmascript::outerBindingOverridesInnerBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine,
testFileUrl("outerBindingOverridesInnerBinding.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -1317,9 +1343,10 @@ Tests for a regression where this used to crash.
*/
void tst_qqmlecmascript::nonExistentAttachedObject()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nonExistentAttachedObject.qml"));
- QString warning = component.url().toString() + ":4:21: Unable to assign [undefined] to QString";
+ QString warning = component.url().toString() + ":4:5: Unable to assign [undefined] to QString";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QObject *object = component.create();
@@ -1330,6 +1357,8 @@ void tst_qqmlecmascript::nonExistentAttachedObject()
void tst_qqmlecmascript::scope()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("scope.qml"));
QObject *object = component.create();
@@ -1420,6 +1449,7 @@ void tst_qqmlecmascript::scope()
// importing context
void tst_qqmlecmascript::importScope()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("importScope.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -1435,6 +1465,7 @@ is essentially a test of QQmlMetaType::copy()
*/
void tst_qqmlecmascript::signalParameterTypes()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalParameterTypes.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(object != nullptr);
@@ -1462,6 +1493,7 @@ Test that two JS objects for the same QObject compare as equal.
*/
void tst_qqmlecmascript::objectsCompareAsEqual()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectsCompareAsEqual.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -1482,6 +1514,7 @@ Tests for a regression where the binding would not reevaluate.
*/
void tst_qqmlecmascript::aliasPropertyAndBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("aliasPropertyAndBinding.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -1503,6 +1536,7 @@ and that the aliased property is reset correctly if possible.
*/
void tst_qqmlecmascript::aliasPropertyReset()
{
+ QQmlEngine engine;
QObject *object = nullptr;
// test that a manual write (of undefined) to a resettable aliased property succeeds
@@ -1631,6 +1665,7 @@ void tst_qqmlecmascript::componentCreation()
QFETCH(QString, creationError);
QFETCH(QString, createdParent);
+ QQmlEngine engine;
QUrl testUrl(testFileUrl("componentCreation.qml"));
if (!creationError.isEmpty()) {
@@ -1677,6 +1712,7 @@ void tst_qqmlecmascript::dynamicCreation()
QFETCH(QString, method);
QFETCH(QString, createdName);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("dynamicCreation.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != nullptr);
@@ -1694,6 +1730,8 @@ void tst_qqmlecmascript::dynamicCreation()
*/
void tst_qqmlecmascript::dynamicDestruction()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("dynamicDeletion.qml"));
QPointer<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
@@ -1777,6 +1815,7 @@ void tst_qqmlecmascript::dynamicDestruction()
*/
void tst_qqmlecmascript::objectToString()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qmlToString.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != nullptr);
@@ -1797,6 +1836,7 @@ void tst_qqmlecmascript::objectHasOwnProperty()
QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
+ QQmlEngine engine;
QQmlComponent component(&engine, url);
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -1843,6 +1883,8 @@ This test is best run under valgrind to ensure no invalid memory access occur.
*/
void tst_qqmlecmascript::selfDeletingBinding()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("selfDeletingBinding.qml"));
QObject *object = component.create();
@@ -1869,6 +1911,7 @@ and no synthesiszed properties).
*/
void tst_qqmlecmascript::extendedObjectPropertyLookup()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("extendedObjectPropertyLookup.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -1880,6 +1923,7 @@ Test that extended object properties can be accessed correctly.
*/
void tst_qqmlecmascript::extendedObjectPropertyLookup2()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("extendedObjectPropertyLookup2.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -1896,6 +1940,7 @@ Test failure when trying to create and uncreatable extended type object.
*/
void tst_qqmlecmascript::uncreatableExtendedObjectFailureCheck()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("uncreatableExtendedObjectFailureCheck.qml"));
QObject *object = component.create();
@@ -1907,6 +1952,7 @@ Test that an subclass of an uncreatable extended object contains all the require
*/
void tst_qqmlecmascript::extendedObjectPropertyLookup3()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("extendedObjectPropertyLookup3.qml"));
QObject *object = component.create();
@@ -1927,6 +1973,7 @@ Test file/lineNumbers for binding/Script errors.
*/
void tst_qqmlecmascript::scriptErrors()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("scriptErrors.qml"));
QString url = component.url().toString();
@@ -1935,7 +1982,7 @@ void tst_qqmlecmascript::scriptErrors()
QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
QString warning4 = url + ":13: ReferenceError: a is not defined";
QString warning5 = url + ":11: ReferenceError: a is not defined";
- QString warning6 = url + ":10:21: Unable to assign [undefined] to int";
+ QString warning6 = url + ":10:5: Unable to assign [undefined] to int";
QString warning7 = url + ":15: TypeError: Cannot assign to read-only property \"trueProperty\"";
QString warning8 = url + ":16: Error: Cannot assign to non-existent property \"fakeProperty\"";
@@ -1964,6 +2011,7 @@ Test file/lineNumbers for inline functions.
*/
void tst_qqmlecmascript::functionErrors()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("functionErrors.qml"));
QString url = component.url().toString();
@@ -1994,6 +2042,7 @@ Test various errors that can occur when assigning a property from script
*/
void tst_qqmlecmascript::propertyAssignmentErrors()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyAssignmentErrors.qml"));
QString url = component.url().toString();
@@ -2013,6 +2062,7 @@ a signal script.
*/
void tst_qqmlecmascript::signalTriggeredBindings()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalTriggeredBindings.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != nullptr);
@@ -2041,6 +2091,7 @@ Test that list properties can be iterated from ECMAScript
*/
void tst_qqmlecmascript::listProperties()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("listProperties.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != nullptr);
@@ -2055,6 +2106,7 @@ void tst_qqmlecmascript::listProperties()
void tst_qqmlecmascript::exceptionClearsOnReeval()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("exceptionClearsOnReeval.qml"));
QString url = component.url().toString();
@@ -2078,6 +2130,7 @@ void tst_qqmlecmascript::exceptionClearsOnReeval()
void tst_qqmlecmascript::exceptionSlotProducesWarning()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("exceptionProducesWarning.qml"));
QString url = component.url().toString();
@@ -2091,6 +2144,7 @@ void tst_qqmlecmascript::exceptionSlotProducesWarning()
void tst_qqmlecmascript::exceptionBindingProducesWarning()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("exceptionProducesWarning2.qml"));
QString url = component.url().toString();
@@ -2105,6 +2159,7 @@ void tst_qqmlecmascript::exceptionBindingProducesWarning()
void tst_qqmlecmascript::compileInvalidBinding()
{
// QTBUG-23387: ensure that invalid bindings don't cause a crash.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("v8bindingException.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -2114,6 +2169,8 @@ void tst_qqmlecmascript::compileInvalidBinding()
// Check that transient binding errors are not displayed
void tst_qqmlecmascript::transientErrors()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("transientErrors.qml"));
@@ -2145,6 +2202,7 @@ void tst_qqmlecmascript::transientErrors()
// Check that errors during shutdown are minimized
void tst_qqmlecmascript::shutdownErrors()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("shutdownErrors.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -2158,6 +2216,7 @@ void tst_qqmlecmascript::shutdownErrors()
void tst_qqmlecmascript::compositePropertyType()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("compositePropertyType.qml"));
QTest::ignoreMessage(QtDebugMsg, "hello world");
@@ -2168,6 +2227,7 @@ void tst_qqmlecmascript::compositePropertyType()
// QTBUG-5759
void tst_qqmlecmascript::jsObject()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("jsObject.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -2179,6 +2239,8 @@ void tst_qqmlecmascript::jsObject()
void tst_qqmlecmascript::undefinedResetsProperty()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("undefinedResetsProperty.qml"));
QObject *object = component.create();
@@ -2214,6 +2276,7 @@ void tst_qqmlecmascript::undefinedResetsProperty()
// Aliases to variant properties should work
void tst_qqmlecmascript::qtbug_22464()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_22464.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -2225,6 +2288,7 @@ void tst_qqmlecmascript::qtbug_22464()
void tst_qqmlecmascript::qtbug_21580()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_21580.qml"));
QObject *object = component.create();
@@ -2238,6 +2302,7 @@ void tst_qqmlecmascript::qtbug_21580()
// Causes a v8 binding, but not all v8 bindings to be destroyed during evaluation
void tst_qqmlecmascript::singleV8BindingDestroyedDuringEvaluation()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("singleV8BindingDestroyedDuringEvaluation.qml"));
QObject *object = component.create();
@@ -2248,6 +2313,7 @@ void tst_qqmlecmascript::singleV8BindingDestroyedDuringEvaluation()
// QTBUG-6781
void tst_qqmlecmascript::bug1()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("bug.1.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -2268,6 +2334,7 @@ void tst_qqmlecmascript::bug1()
#ifndef QT_NO_WIDGETS
void tst_qqmlecmascript::bug2()
{
+ QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
@@ -2281,6 +2348,7 @@ void tst_qqmlecmascript::bug2()
// Don't crash in createObject when the component has errors.
void tst_qqmlecmascript::dynamicCreationCrash()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("dynamicCreation.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != nullptr);
@@ -2331,6 +2399,8 @@ void tst_qqmlecmascript::dynamicCreationOwnership()
void tst_qqmlecmascript::regExpBug()
{
+ QQmlEngine engine;
+
//QTBUG-9367
{
QQmlComponent component(&engine, testFileUrl("regExp.qml"));
@@ -2357,7 +2427,7 @@ static inline bool evaluate_error(QV4::ExecutionEngine *v4, const QV4::Value &o,
QLatin1String(source) + QLatin1String(" })");
QV4::Scope scope(v4);
- QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::EvalCode, functionSource);
+ QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::ContextType::Eval, functionSource);
program.inheritContext = true;
QV4::ScopedFunctionObject function(scope, program.run());
@@ -2383,7 +2453,7 @@ static inline bool evaluate_value(QV4::ExecutionEngine *v4, const QV4::Value &o,
QLatin1String(source) + QLatin1String(" })");
QV4::Scope scope(v4);
- QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::EvalCode, functionSource);
+ QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::ContextType::Eval, functionSource);
program.inheritContext = true;
QV4::ScopedFunctionObject function(scope, program.run());
@@ -2414,7 +2484,7 @@ static inline QV4::ReturnedValue evaluate(QV4::ExecutionEngine *v4, const QV4::V
QV4::Scope scope(v4);
- QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::EvalCode, functionSource);
+ QV4::Script program(QV4::ScopedContext(scope, scope.engine->rootContext()), QV4::Compiler::ContextType::Eval, functionSource);
program.inheritContext = true;
QV4::ScopedFunctionObject function(scope, program.run());
@@ -3058,6 +3128,7 @@ void tst_qqmlecmascript::resolveClashingProperties()
// QTBUG-13047 (check that you can pass registered object types as args)
void tst_qqmlecmascript::invokableObjectArg()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("invokableObjectArg.qml"));
QObject *o = component.create();
@@ -3072,6 +3143,7 @@ void tst_qqmlecmascript::invokableObjectArg()
// QTBUG-13047 (check that you can return registered object types from methods)
void tst_qqmlecmascript::invokableObjectRet()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("invokableObjectRet.qml"));
QObject *o = component.create();
@@ -3082,6 +3154,7 @@ void tst_qqmlecmascript::invokableObjectRet()
void tst_qqmlecmascript::invokableEnumRet()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("invokableEnumRet.qml"));
QObject *o = component.create();
@@ -3093,6 +3166,7 @@ void tst_qqmlecmascript::invokableEnumRet()
// QTBUG-5675
void tst_qqmlecmascript::listToVariant()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("listToVariant.qml"));
MyQmlContainer container;
@@ -3113,6 +3187,7 @@ void tst_qqmlecmascript::listToVariant()
// QTBUG-16316
void tst_qqmlecmascript::listAssignment()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("listAssignment.qml"));
QObject *obj = component.create();
QCOMPARE(obj->property("list1length").toInt(), 2);
@@ -3151,6 +3226,7 @@ void tst_qqmlecmascript::multiEngineObject()
// Test that references to QObjects are cleanup when the object is destroyed
void tst_qqmlecmascript::deletedObject()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deletedObject.qml"));
QObject *object = component.create();
@@ -3165,6 +3241,7 @@ void tst_qqmlecmascript::deletedObject()
void tst_qqmlecmascript::attachedPropertyScope()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("attachedPropertyScope.qml"));
QObject *object = component.create();
@@ -3185,6 +3262,8 @@ void tst_qqmlecmascript::attachedPropertyScope()
void tst_qqmlecmascript::scriptConnect()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("scriptConnect.1.qml"));
@@ -3266,6 +3345,8 @@ void tst_qqmlecmascript::scriptConnect()
void tst_qqmlecmascript::scriptDisconnect()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine, testFileUrl("scriptDisconnect.1.qml"));
@@ -3356,6 +3437,7 @@ public slots:
void tst_qqmlecmascript::ownership()
{
+ QQmlEngine engine;
OwnershipObject own;
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextObject(&own);
@@ -3453,6 +3535,7 @@ void tst_qqmlecmascript::cppOwnershipReturnValue()
// QTBUG-15697
void tst_qqmlecmascript::ownershipCustomReturnValue()
{
+ QQmlEngine engine;
CppOwnershipReturnValue source;
{
@@ -3496,6 +3579,7 @@ public slots:
void tst_qqmlecmascript::ownershipRootObject()
{
+ QQmlEngine engine;
OwnershipChangingObject own;
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextObject(&own);
@@ -3517,6 +3601,7 @@ void tst_qqmlecmascript::ownershipRootObject()
void tst_qqmlecmascript::ownershipConsistency()
{
+ QQmlEngine engine;
OwnershipChangingObject own;
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextObject(&own);
@@ -3547,6 +3632,7 @@ void tst_qqmlecmascript::ownershipConsistency()
void tst_qqmlecmascript::ownershipQmlIncubated()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("ownershipQmlIncubated.qml"));
QObject *object = component.create();
QVERIFY(object);
@@ -3586,6 +3672,7 @@ private:
// Tests that returning a QList<QObject*> from a method works
void tst_qqmlecmascript::qlistqobjectMethods()
{
+ QQmlEngine engine;
QListQObjectMethodsObject obj;
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextObject(&obj);
@@ -3604,6 +3691,7 @@ void tst_qqmlecmascript::qlistqobjectMethods()
// QTBUG-9205
void tst_qqmlecmascript::strictlyEquals()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("strictlyEquals.qml"));
QObject *object = component.create();
@@ -3623,6 +3711,7 @@ void tst_qqmlecmascript::strictlyEquals()
void tst_qqmlecmascript::compiled()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("compiled.qml"));
QObject *object = component.create();
@@ -3663,6 +3752,7 @@ void tst_qqmlecmascript::compiled()
// Test that numbers assigned in bindings as strings work consistently
void tst_qqmlecmascript::numberAssignment()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("numberAssignment.qml"));
QObject *object = component.create();
@@ -3689,6 +3779,7 @@ void tst_qqmlecmascript::numberAssignment()
void tst_qqmlecmascript::propertySplicing()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertySplicing.qml"));
QObject *object = component.create();
@@ -3702,6 +3793,7 @@ void tst_qqmlecmascript::propertySplicing()
// QTBUG-16683
void tst_qqmlecmascript::signalWithUnknownTypes()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalWithUnknownTypes.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -3755,6 +3847,7 @@ void tst_qqmlecmascript::signalWithJSValueInVariant()
QFETCH(QString, expression);
QFETCH(QString, compare);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalWithJSValueInVariant.qml"));
QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
QVERIFY(object != nullptr);
@@ -3779,6 +3872,7 @@ void tst_qqmlecmascript::signalWithJSValueInVariant_twoEngines()
QFETCH(QString, expression);
QFETCH(QString, compare);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalWithJSValueInVariant.qml"));
QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
QVERIFY(object != nullptr);
@@ -3809,6 +3903,7 @@ void tst_qqmlecmascript::signalWithQJSValue()
QFETCH(QString, expression);
QFETCH(QString, compare);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalWithQJSValue.qml"));
QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
QVERIFY(object != nullptr);
@@ -4029,6 +4124,7 @@ void tst_qqmlecmascript::singletonTypeCaching()
void tst_qqmlecmascript::singletonTypeImportOrder()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("singletontype/singletonTypeImportOrder.qml"));
QObject *object = component.create();
QVERIFY(object);
@@ -4038,6 +4134,7 @@ void tst_qqmlecmascript::singletonTypeImportOrder()
void tst_qqmlecmascript::singletonTypeResolution()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("singletontype/singletonTypeResolution.qml"));
QObject *object = component.create();
QVERIFY(object);
@@ -4055,7 +4152,7 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
QV4::Scoped<QV4::QQmlContextWrapper> qml(scope);
for (quint32 i = 0; i < scripts->getLength(); ++i) {
QQmlContextData *scriptContext, *newContext;
- qml = scripts->getIndexed(i);
+ qml = scripts->get(i);
scriptContext = qml ? qml->getContext() : nullptr;
qml = QV4::Encode::undefined();
@@ -4067,7 +4164,7 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
}
ctxt->engine->collectGarbage();
- qml = scripts->getIndexed(i);
+ qml = scripts->get(i);
newContext = qml ? qml->getContext() : nullptr;
QCOMPARE(scriptContext, newContext);
}
@@ -4181,7 +4278,7 @@ void tst_qqmlecmascript::importScripts_data()
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("testValue"))
- << (QVariantList() << QVariant(18));
+ << (QVariantList() << QVariant(16));
QTest::newRow("import singleton type into js import")
<< testFileUrl("jsimport/testImportSingletonType.qml")
@@ -4315,6 +4412,10 @@ void tst_qqmlecmascript::importScripts()
ThreadedTestHTTPServer server(dataDirectory() + "/remote");
+ QQmlEngine engine;
+ QString dataDir(dataDirectory() + QLatin1Char('/') + QLatin1String("lib"));
+ engine.addImportPath(dataDir);
+
QStringList importPathList = engine.importPathList();
QString remotePath(server.urlString("/"));
@@ -4358,6 +4459,7 @@ void tst_qqmlecmascript::importScripts()
void tst_qqmlecmascript::importCreationContext()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("jsimport/creationContext.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -4378,6 +4480,7 @@ void tst_qqmlecmascript::scarceResources_other()
QPixmap origPixmap(100, 100);
origPixmap.fill(Qt::blue);
QString srp_name, expectedWarning;
+ QQmlEngine engine;
QV4::ExecutionEngine *v4 = engine.handle();
ScarceResourceObject *eo = nullptr;
QObject *srsc = nullptr;
@@ -4749,6 +4852,7 @@ void tst_qqmlecmascript::scarceResources()
QFETCH(QVariantList, expectedValues);
QFETCH(QStringList, expectedErrors);
+ QQmlEngine engine;
QV4::ExecutionEngine *v4 = engine.handle();
ScarceResourceObject *eo = nullptr;
QObject *object = nullptr;
@@ -4781,6 +4885,7 @@ void tst_qqmlecmascript::scarceResources()
void tst_qqmlecmascript::propertyChangeSlots()
{
// ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("changeslots/propertyChangeSlots.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -4847,6 +4952,7 @@ void tst_qqmlecmascript::propertyVar()
{
QFETCH(QUrl, qmlFile);
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -4886,6 +4992,7 @@ void tst_qqmlecmascript::propertyQJSValue()
{
QFETCH(QUrl, qmlFile);
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -4903,6 +5010,7 @@ void tst_qqmlecmascript::propertyVarCpp()
// ensure that writing to and reading from a var property from cpp works as required.
// Literal values stored in var properties can be read and written as QVariants
// of a specific type, whereas object values are read as QVariantMaps.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVarCpp.qml"));
object = component.create();
QVERIFY(object != nullptr);
@@ -4924,6 +5032,8 @@ void tst_qqmlecmascript::propertyVarCpp()
void tst_qqmlecmascript::propertyVarOwnership()
{
+ QQmlEngine engine;
+
// Referenced JS objects are not collected
{
QQmlComponent component(&engine, testFileUrl("propertyVarOwnership.qml"));
@@ -5005,6 +5115,7 @@ void tst_qqmlecmascript::propertyVarImplicitOwnership()
// The childObject has a reference to a different QObject. We want to ensure
// that the different item will not be cleaned up until required. IE, the childObject
// has implicit ownership of the constructed QObject.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVarImplicitOwnership.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5032,6 +5143,7 @@ void tst_qqmlecmascript::propertyVarImplicitOwnership()
void tst_qqmlecmascript::propertyVarReparent()
{
// ensure that nothing breaks if we re-parent objects
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVar.reparent.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5074,6 +5186,7 @@ void tst_qqmlecmascript::propertyVarReparentNullContext()
// sometimes reparenting can cause problems
// (eg, if the ctxt is collected, varproperties are no longer available)
// this test ensures that no crash occurs in that situation.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVar.reparent.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5110,6 +5223,7 @@ void tst_qqmlecmascript::propertyVarReparentNullContext()
void tst_qqmlecmascript::propertyVarCircular()
{
// enforce behaviour regarding circular references - ensure qdvmemo deletion.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVar.circular.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5142,6 +5256,7 @@ void tst_qqmlecmascript::propertyVarCircular2()
{
// track deletion of JS-owned parent item with Cpp-owned child
// where the child has a var property referencing its parent.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVar.circular.2.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5170,6 +5285,7 @@ void tst_qqmlecmascript::propertyVarInheritance()
{
// enforce behaviour regarding element inheritance - ensure handle disposal.
// The particular component under test here has a chain of references.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVar.inherit.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5215,6 +5331,7 @@ void tst_qqmlecmascript::propertyVarInheritance2()
{
// The particular component under test here does NOT have a chain of references; the
// only link between rootObject and childObject is that rootObject is the parent of childObject.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyVar.circular.2.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5248,6 +5365,7 @@ void tst_qqmlecmascript::propertyVarInheritance2()
// Ensure that QObject type conversion works on binding assignment
void tst_qqmlecmascript::elementAssign()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("elementAssign.qml"));
QObject *object = component.create();
@@ -5261,6 +5379,7 @@ void tst_qqmlecmascript::elementAssign()
// QTBUG-12457
void tst_qqmlecmascript::objectPassThroughSignals()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectsPassThroughSignals.qml"));
QObject *object = component.create();
@@ -5274,6 +5393,7 @@ void tst_qqmlecmascript::objectPassThroughSignals()
// QTBUG-21626
void tst_qqmlecmascript::objectConversion()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectConversion.qml"));
QObject *object = component.create();
@@ -5289,6 +5409,7 @@ void tst_qqmlecmascript::objectConversion()
// QTBUG-20242
void tst_qqmlecmascript::booleanConversion()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("booleanConversion.qml"));
QObject *object = component.create();
@@ -5401,6 +5522,7 @@ void tst_qqmlecmascript::handleReferenceManagement()
void tst_qqmlecmascript::stringArg()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stringArg.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5417,6 +5539,7 @@ void tst_qqmlecmascript::stringArg()
void tst_qqmlecmascript::readonlyDeclaration()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("readonlyDeclaration.qml"));
QObject *object = component.create();
@@ -5434,6 +5557,8 @@ Q_DECLARE_METATYPE(QList<QString>)
Q_DECLARE_METATYPE(QList<QUrl>)
void tst_qqmlecmascript::sequenceConversionRead()
{
+ QQmlEngine engine;
+
{
QUrl qmlFile = testFileUrl("sequenceConversion.read.qml");
QQmlComponent component(&engine, qmlFile);
@@ -5514,6 +5639,7 @@ void tst_qqmlecmascript::sequenceConversionRead()
void tst_qqmlecmascript::sequenceConversionWrite()
{
+ QQmlEngine engine;
{
QUrl qmlFile = testFileUrl("sequenceConversion.write.qml");
QQmlComponent component(&engine, qmlFile);
@@ -5562,6 +5688,7 @@ void tst_qqmlecmascript::sequenceConversionArray()
{
// ensure that in JS the returned sequences act just like normal JS Arrays.
QUrl qmlFile = testFileUrl("sequenceConversion.array.qml");
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
@@ -5583,6 +5710,7 @@ void tst_qqmlecmascript::sequenceConversionIndexes()
// ensure that we gracefully fail if unsupported index values are specified.
// Qt container classes only support non-negative, signed integer index values.
QUrl qmlFile = testFileUrl("sequenceConversion.indexes.qml");
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5604,6 +5732,7 @@ void tst_qqmlecmascript::sequenceConversionThreads()
// ensure that sequence conversion operations work correctly in a worker thread
// and that serialisation between the main and worker thread succeeds.
QUrl qmlFile = testFileUrl("sequenceConversion.threads.qml");
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5641,6 +5770,7 @@ void tst_qqmlecmascript::sequenceConversionThreads()
void tst_qqmlecmascript::sequenceConversionBindings()
{
+ QQmlEngine engine;
{
QUrl qmlFile = testFileUrl("sequenceConversion.bindings.qml");
QQmlComponent component(&engine, qmlFile);
@@ -5656,7 +5786,7 @@ void tst_qqmlecmascript::sequenceConversionBindings()
{
QUrl qmlFile = testFileUrl("sequenceConversion.bindings.error.qml");
- QString warning = QString(QLatin1String("%1:17:27: Unable to assign QList<int> to QList<bool>")).arg(qmlFile.toString());
+ QString warning = QString(QLatin1String("%1:17:9: Unable to assign QList<int> to QList<bool>")).arg(qmlFile.toString());
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
QQmlComponent component(&engine, qmlFile);
QObject *object = component.create();
@@ -5668,6 +5798,7 @@ void tst_qqmlecmascript::sequenceConversionBindings()
void tst_qqmlecmascript::sequenceConversionCopy()
{
QUrl qmlFile = testFileUrl("sequenceConversion.copy.qml");
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -5686,6 +5817,8 @@ void tst_qqmlecmascript::sequenceConversionCopy()
void tst_qqmlecmascript::assignSequenceTypes()
{
+ QQmlEngine engine;
+
// test binding array to sequence type property
{
QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.1.qml"));
@@ -5784,12 +5917,23 @@ void tst_qqmlecmascript::assignSequenceTypes()
QCOMPARE(msco5->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html")) << QUrl(testFileUrl("example2.html"))));
delete object;
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.8.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
+ QVariant result;
+ QMetaObject::invokeMethod(object.data(), "tryWritingReadOnlySequence", Q_RETURN_ARG(QVariant, result));
+ QVERIFY(result.type() == QVariant::Bool);
+ QVERIFY(result.toBool());
+ }
}
// Test that assigning a null object works
// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
void tst_qqmlecmascript::nullObjectBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nullObjectBinding.qml"));
QObject *object = component.create();
@@ -5802,6 +5946,7 @@ void tst_qqmlecmascript::nullObjectBinding()
void tst_qqmlecmascript::nullObjectInitializer()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("nullObjectInitializer.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -5832,7 +5977,7 @@ void tst_qqmlecmascript::nullObjectInitializer()
{
const int propertyIndex = obj->metaObject()->indexOfProperty("testProperty");
QVERIFY(propertyIndex > 0);
- QVERIFY(ddata->hasBindingBit(propertyIndex));
+ QVERIFY(!ddata->hasBindingBit(propertyIndex));
}
QVERIFY(obj->property("success").toBool());
@@ -5869,6 +6014,7 @@ void tst_qqmlecmascript::deletedEngine()
// Test the crashing part of QTBUG-9705
void tst_qqmlecmascript::libraryScriptAssert()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("libraryScriptAssert.qml"));
QObject *object = component.create();
@@ -5879,6 +6025,7 @@ void tst_qqmlecmascript::libraryScriptAssert()
void tst_qqmlecmascript::variantsAssignedUndefined()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("variantsAssignedUndefined.qml"));
QObject *object = component.create();
@@ -5898,6 +6045,7 @@ void tst_qqmlecmascript::variantsAssignedUndefined()
void tst_qqmlecmascript::variants()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("variants.qml"));
QObject *object = component.create();
@@ -5921,6 +6069,7 @@ void tst_qqmlecmascript::variants()
void tst_qqmlecmascript::qtbug_9792()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_9792.qml"));
QQmlContext *context = new QQmlContext(engine.rootContext());
@@ -5945,6 +6094,7 @@ void tst_qqmlecmascript::qtbug_9792()
// Verifies that QPointer<>s used in the vmemetaobject are cleaned correctly
void tst_qqmlecmascript::qtcreatorbug_1289()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtcreatorbug_1289.qml"));
QObject *o = component.create();
@@ -5966,6 +6116,7 @@ void tst_qqmlecmascript::qtcreatorbug_1289()
// Test that we shut down without stupid warnings
void tst_qqmlecmascript::noSpuriousWarningsAtShutdown()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("noSpuriousWarningsAtShutdown.qml"));
@@ -5994,6 +6145,7 @@ void tst_qqmlecmascript::noSpuriousWarningsAtShutdown()
void tst_qqmlecmascript::canAssignNullToQObject()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("canAssignNullToQObject.1.qml"));
@@ -6023,13 +6175,14 @@ void tst_qqmlecmascript::canAssignNullToQObject()
void tst_qqmlecmascript::functionAssignment_fromBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("functionAssignment.1.qml"));
QString url = component.url().toString();
- QString w1 = url + ":4:25: Unable to assign a function to a property of any type other than var.";
- QString w2 = url + ":5:25: Invalid use of Qt.binding() in a binding declaration.";
- QString w3 = url + ":6:21: Invalid use of Qt.binding() in a binding declaration.";
- QString w4 = url + ":7:15: Invalid use of Qt.binding() in a binding declaration.";
+ QString w1 = url + ":4:5: Unable to assign a function to a property of any type other than var.";
+ QString w2 = url + ":5:5: Invalid use of Qt.binding() in a binding declaration.";
+ QString w3 = url + ":6:5: Invalid use of Qt.binding() in a binding declaration.";
+ QString w4 = url + ":7:5: Invalid use of Qt.binding() in a binding declaration.";
QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData());
QTest::ignoreMessage(QtWarningMsg, w2.toLatin1().constData());
QTest::ignoreMessage(QtWarningMsg, w3.toLatin1().constData());
@@ -6047,6 +6200,7 @@ void tst_qqmlecmascript::functionAssignment_fromJS()
{
QFETCH(QString, triggerProperty);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("functionAssignment.2.qml"));
QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
@@ -6079,6 +6233,7 @@ void tst_qqmlecmascript::functionAssignment_fromJS_data()
void tst_qqmlecmascript::functionAssignmentfromJS_invalid()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("functionAssignment.2.qml"));
QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
@@ -6103,6 +6258,7 @@ void tst_qqmlecmascript::functionAssignmentfromJS_invalid()
void tst_qqmlecmascript::functionAssignment_afterBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("functionAssignment.3.qml"));
QString url = component.url().toString();
@@ -6119,6 +6275,7 @@ void tst_qqmlecmascript::functionAssignment_afterBinding()
void tst_qqmlecmascript::eval()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("eval.qml"));
QObject *o = component.create();
@@ -6135,6 +6292,7 @@ void tst_qqmlecmascript::eval()
void tst_qqmlecmascript::function()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("function.qml"));
QObject *o = component.create();
@@ -6150,6 +6308,7 @@ void tst_qqmlecmascript::function()
// Test the "Qt.include" method
void tst_qqmlecmascript::include()
{
+ QQmlEngine engine;
// Non-library relative include
{
QQmlComponent component(&engine, testFileUrl("include.qml"));
@@ -6208,6 +6367,14 @@ void tst_qqmlecmascript::include()
delete o;
}
+ // Including file with ".pragma library", shadowing a global var
+ {
+ QQmlComponent component(&engine, testFileUrl("include_pragma_shadow.qml"));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("result").toBool(), true);
+ }
+
// Remote - error
{
TestHTTPServer server;
@@ -6254,6 +6421,7 @@ void tst_qqmlecmascript::includeRemoteSuccess()
QVERIFY2(server.listen(), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("include_remote.qml"));
QObject *o = component.beginCreate(engine.rootContext());
QVERIFY(o != nullptr);
@@ -6280,6 +6448,7 @@ void tst_qqmlecmascript::includeRemoteSuccess()
void tst_qqmlecmascript::signalHandlers()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signalHandlers.qml"));
QScopedPointer<QObject> o(component.create());
QVERIFY(o != nullptr);
@@ -6340,6 +6509,7 @@ void tst_qqmlecmascript::qtbug_37351()
void tst_qqmlecmascript::qtbug_10696()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_10696.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6348,6 +6518,7 @@ void tst_qqmlecmascript::qtbug_10696()
void tst_qqmlecmascript::qtbug_11606()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_11606.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6357,6 +6528,7 @@ void tst_qqmlecmascript::qtbug_11606()
void tst_qqmlecmascript::qtbug_11600()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_11600.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6366,6 +6538,7 @@ void tst_qqmlecmascript::qtbug_11600()
void tst_qqmlecmascript::qtbug_21864()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_21864.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6375,6 +6548,7 @@ void tst_qqmlecmascript::qtbug_21864()
void tst_qqmlecmascript::rewriteMultiLineStrings()
{
+ QQmlEngine engine;
{
// QTBUG-23387
QQmlComponent component(&engine, testFileUrl("rewriteMultiLineStrings.qml"));
@@ -6395,6 +6569,7 @@ void tst_qqmlecmascript::rewriteMultiLineStrings()
void tst_qqmlecmascript::qobjectConnectionListExceptionHandling()
{
// QTBUG-23375
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qobjectConnectionListExceptionHandling.qml"));
QString warning = component.url().toString() + QLatin1String(":13: TypeError: Cannot read property 'undefined' of undefined");
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
@@ -6409,6 +6584,7 @@ void tst_qqmlecmascript::qobjectConnectionListExceptionHandling()
// Reading and writing non-scriptable properties should fail
void tst_qqmlecmascript::nonscriptable()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nonscriptable.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6420,6 +6596,7 @@ void tst_qqmlecmascript::nonscriptable()
// deleteLater() should not be callable from QML
void tst_qqmlecmascript::deleteLater()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deleteLater.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6430,6 +6607,7 @@ void tst_qqmlecmascript::deleteLater()
// objectNameChanged() should be usable from QML
void tst_qqmlecmascript::objectNameChangedSignal()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectNameChangedSignal.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6442,6 +6620,7 @@ void tst_qqmlecmascript::objectNameChangedSignal()
// destroyed() should not be usable from QML
void tst_qqmlecmascript::destroyedSignal()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("destroyedSignal.qml"));
QVERIFY(component.isError());
@@ -6451,6 +6630,7 @@ void tst_qqmlecmascript::destroyedSignal()
void tst_qqmlecmascript::in()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("in.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6461,6 +6641,7 @@ void tst_qqmlecmascript::in()
void tst_qqmlecmascript::typeOf()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("typeOf.qml"));
QObject *o = component.create();
@@ -6481,6 +6662,7 @@ void tst_qqmlecmascript::typeOf()
void tst_qqmlecmascript::qtbug_24448()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_24448.qml"));
QScopedPointer<QObject> o(component.create());
QVERIFY(o != nullptr);
@@ -6489,6 +6671,7 @@ void tst_qqmlecmascript::qtbug_24448()
void tst_qqmlecmascript::sharedAttachedObject()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("sharedAttachedObject.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6500,6 +6683,7 @@ void tst_qqmlecmascript::sharedAttachedObject()
// QTBUG-13999
void tst_qqmlecmascript::objectName()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("objectName.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6517,6 +6701,7 @@ void tst_qqmlecmascript::objectName()
void tst_qqmlecmascript::writeRemovesBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("writeRemovesBinding.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6529,6 +6714,7 @@ void tst_qqmlecmascript::writeRemovesBinding()
// Test bindings assigned to alias properties actually assign to the alias' target
void tst_qqmlecmascript::aliasBindingsAssignCorrectly()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("aliasBindingsAssignCorrectly.qml"));
QObject *o = component.create();
QVERIFY(o != nullptr);
@@ -6541,6 +6727,7 @@ void tst_qqmlecmascript::aliasBindingsAssignCorrectly()
// Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
void tst_qqmlecmascript::aliasBindingsOverrideTarget()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("aliasBindingsOverrideTarget.qml"));
QObject *o = component.create();
@@ -6575,6 +6762,7 @@ void tst_qqmlecmascript::aliasBindingsOverrideTarget()
// Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
void tst_qqmlecmascript::aliasWritesOverrideBindings()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("aliasWritesOverrideBindings.qml"));
QObject *o = component.create();
@@ -6610,6 +6798,7 @@ void tst_qqmlecmascript::aliasWritesOverrideBindings()
// QTBUG-20200
void tst_qqmlecmascript::aliasToCompositeElement()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("aliasToCompositeElement.qml"));
QObject *object = component.create();
@@ -6620,6 +6809,7 @@ void tst_qqmlecmascript::aliasToCompositeElement()
void tst_qqmlecmascript::qtbug_20344()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_20344.qml"));
QString warning = component.url().toString() + ":5: Error: Exception thrown from within QObject slot";
@@ -6633,6 +6823,7 @@ void tst_qqmlecmascript::qtbug_20344()
void tst_qqmlecmascript::revisionErrors()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("metaobjectRevisionErrors.qml"));
QString url = component.url().toString();
@@ -6690,6 +6881,7 @@ void tst_qqmlecmascript::revisionErrors()
void tst_qqmlecmascript::revision()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("metaobjectRevision.qml"));
QString url = component.url().toString();
@@ -6736,6 +6928,7 @@ void tst_qqmlecmascript::revision()
void tst_qqmlecmascript::realToInt()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("realToInt.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != nullptr);
@@ -6748,6 +6941,7 @@ void tst_qqmlecmascript::realToInt()
void tst_qqmlecmascript::urlProperty()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("urlProperty.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
@@ -6762,6 +6956,7 @@ void tst_qqmlecmascript::urlProperty()
void tst_qqmlecmascript::urlPropertyWithEncoding()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("urlProperty.2.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
@@ -6776,6 +6971,7 @@ void tst_qqmlecmascript::urlPropertyWithEncoding()
void tst_qqmlecmascript::urlListPropertyWithEncoding()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("urlListProperty.qml"));
QObject *object = component.create();
@@ -6796,6 +6992,7 @@ void tst_qqmlecmascript::urlListPropertyWithEncoding()
void tst_qqmlecmascript::dynamicString()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("dynamicString.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6805,6 +7002,7 @@ void tst_qqmlecmascript::dynamicString()
void tst_qqmlecmascript::deleteLaterObjectMethodCall()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deleteLaterObjectMethodCall.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6812,6 +7010,7 @@ void tst_qqmlecmascript::deleteLaterObjectMethodCall()
void tst_qqmlecmascript::automaticSemicolon()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("automaticSemicolon.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6819,6 +7018,7 @@ void tst_qqmlecmascript::automaticSemicolon()
void tst_qqmlecmascript::compatibilitySemicolon()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("compatibilitySemicolon.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6826,6 +7026,7 @@ void tst_qqmlecmascript::compatibilitySemicolon()
void tst_qqmlecmascript::incrDecrSemicolon1()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon1.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6833,6 +7034,7 @@ void tst_qqmlecmascript::incrDecrSemicolon1()
void tst_qqmlecmascript::incrDecrSemicolon2()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon2.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6840,6 +7042,7 @@ void tst_qqmlecmascript::incrDecrSemicolon2()
void tst_qqmlecmascript::incrDecrSemicolon_error1()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("incrDecrSemicolon_error1.qml"));
QObject *object = component.create();
QVERIFY(!object);
@@ -6847,6 +7050,7 @@ void tst_qqmlecmascript::incrDecrSemicolon_error1()
void tst_qqmlecmascript::unaryExpression()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("unaryExpression.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6855,6 +7059,7 @@ void tst_qqmlecmascript::unaryExpression()
// Makes sure that a binding isn't double re-evaluated when it depends on the same variable twice
void tst_qqmlecmascript::doubleEvaluate()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("doubleEvaluate.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6871,6 +7076,7 @@ void tst_qqmlecmascript::doubleEvaluate()
void tst_qqmlecmascript::nonNotifyable()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nonNotifyable.qml"));
QQmlTestMessageHandler messageHandler;
@@ -6881,7 +7087,7 @@ void tst_qqmlecmascript::nonNotifyable()
QString expected1 = QLatin1String("QQmlExpression: Expression ") +
component.url().toString() +
- QLatin1String(":5:24 depends on non-NOTIFYable properties:");
+ QLatin1String(":5:5 depends on non-NOTIFYable properties:");
QString expected2 = QLatin1String(" ") +
QLatin1String(object->metaObject()->className()) +
QLatin1String("::value");
@@ -6895,6 +7101,7 @@ void tst_qqmlecmascript::nonNotifyable()
void tst_qqmlecmascript::nonNotifyableConstant()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nonNotifyableConstant.qml"));
QQmlTestMessageHandler messageHandler;
@@ -6907,6 +7114,7 @@ void tst_qqmlecmascript::nonNotifyableConstant()
void tst_qqmlecmascript::forInLoop()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("forInLoop.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6927,6 +7135,7 @@ void tst_qqmlecmascript::forInLoop()
// An object the binding depends on is deleted while the binding is still running
void tst_qqmlecmascript::deleteWhileBindingRunning()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("deleteWhileBindingRunning.qml"));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -6937,6 +7146,7 @@ void tst_qqmlecmascript::qtbug_22679()
{
MyQmlObject object;
object.setStringProperty(QLatin1String("Please work correctly"));
+ QQmlEngine engine;
engine.rootContext()->setContextProperty("contextProp", &object);
QQmlComponent component(&engine, testFileUrl("qtbug_22679.qml"));
@@ -6966,6 +7176,7 @@ void tst_qqmlecmascript::qtbug_22843()
fileName += QLatin1String(".library");
fileName += QLatin1String(".qml");
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(fileName));
QString url = component.url().toString();
@@ -6978,6 +7189,7 @@ void tst_qqmlecmascript::qtbug_22843()
void tst_qqmlecmascript::switchStatement()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("switchStatement.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -7050,7 +7262,7 @@ void tst_qqmlecmascript::switchStatement()
{
QQmlComponent component(&engine, testFileUrl("switchStatement.4.qml"));
- QString warning = component.url().toString() + ":4:12: Unable to assign [undefined] to int";
+ QString warning = component.url().toString() + ":4:5: Unable to assign [undefined] to int";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -7124,6 +7336,7 @@ void tst_qqmlecmascript::switchStatement()
void tst_qqmlecmascript::withStatement()
{
+ QQmlEngine engine;
{
QUrl url = testFileUrl("withStatement.1.qml");
QQmlComponent component(&engine, url);
@@ -7136,6 +7349,7 @@ void tst_qqmlecmascript::withStatement()
void tst_qqmlecmascript::tryStatement()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("tryStatement.1.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
@@ -7157,7 +7371,7 @@ void tst_qqmlecmascript::tryStatement()
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(object != nullptr);
- QCOMPARE(object->value(), 1);
+ QVERIFY(object->qjsvalue().isUndefined());
}
{
@@ -7165,7 +7379,7 @@ void tst_qqmlecmascript::tryStatement()
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(object != nullptr);
- QCOMPARE(object->value(), 1);
+ QVERIFY(object->qjsvalue().isUndefined());
}
}
@@ -7211,6 +7425,7 @@ void tst_qqmlecmascript::invokableWithQObjectDerived()
void tst_qqmlecmascript::realTypePrecision()
{
// Properties and signal parameters of type real should have double precision.
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("realTypePrecision.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
@@ -7261,8 +7476,8 @@ void tst_qqmlecmascript::bindingBoundFunctions()
void tst_qqmlecmascript::deleteRootObjectInCreation()
{
- {
QQmlEngine engine;
+ {
QQmlComponent c(&engine, testFileUrl("deleteRootObjectInCreation.qml"));
QObject *obj = c.create();
QVERIFY(obj != nullptr);
@@ -7401,7 +7616,7 @@ void tst_qqmlecmascript::onDestructionViaGC()
QVERIFY2(!weakReferenceMutator.isNull(), qPrintable(component.errorString()));
weakReferenceMutator->init(v4, weakRef.data(), &mutatorResult);
- v4->memoryManager->allocObject<QV4::WeakReferenceSentinel>(weakRef.data(), &sentinelResult);
+ v4->memoryManager->allocate<QV4::WeakReferenceSentinel>(weakRef.data(), &sentinelResult);
}
gc(engine);
@@ -7475,6 +7690,7 @@ void tst_qqmlecmascript::signalEmitted()
// QTBUG-25647
void tst_qqmlecmascript::threadSignal()
{
+ QQmlEngine engine;
{
QQmlComponent c(&engine, testFileUrl("threadSignal.qml"));
QScopedPointer<QObject> object(c.create());
@@ -7493,6 +7709,7 @@ void tst_qqmlecmascript::threadSignal()
// ensure that the qqmldata::destroyed() handler doesn't cause problems
void tst_qqmlecmascript::qqmldataDestroyed()
{
+ QQmlEngine engine;
// gc cleans up a qobject, later the qqmldata destroyed handler will run.
{
QQmlComponent c(&engine, testFileUrl("qqmldataDestroyed.qml"));
@@ -7526,6 +7743,7 @@ void tst_qqmlecmascript::qqmldataDestroyed()
void tst_qqmlecmascript::secondAlias()
{
+ QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("secondAlias.qml"));
QObject *object = c.create();
QVERIFY(object != nullptr);
@@ -7536,6 +7754,7 @@ void tst_qqmlecmascript::secondAlias()
// An alias to a var property works
void tst_qqmlecmascript::varAlias()
{
+ QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("varAlias.qml"));
QObject *object = c.create();
QVERIFY(object != nullptr);
@@ -7546,6 +7765,7 @@ void tst_qqmlecmascript::varAlias()
// Used to trigger an assert in the lazy meta object creation stage
void tst_qqmlecmascript::overrideDataAssert()
{
+ QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("overrideDataAssert.qml"));
QObject *object = c.create();
QVERIFY(object != nullptr);
@@ -7571,6 +7791,7 @@ void tst_qqmlecmascript::fallbackBindings()
{
QFETCH(QString, source);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(source));
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
@@ -7580,6 +7801,7 @@ void tst_qqmlecmascript::fallbackBindings()
void tst_qqmlecmascript::propertyOverride()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("propertyOverride.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
@@ -7615,6 +7837,7 @@ void tst_qqmlecmascript::sequenceSort()
QFETCH(QString, function);
QFETCH(bool, useComparer);
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("sequenceSort.qml"));
QObject *object = component.create();
@@ -7631,6 +7854,7 @@ void tst_qqmlecmascript::sequenceSort()
void tst_qqmlecmascript::dateParse()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("date.qml"));
QObject *object = component.create();
@@ -7651,6 +7875,7 @@ void tst_qqmlecmascript::dateParse()
void tst_qqmlecmascript::utcDate()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("utcdate.qml"));
QObject *object = component.create();
@@ -7666,6 +7891,7 @@ void tst_qqmlecmascript::utcDate()
void tst_qqmlecmascript::negativeYear()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("negativeyear.qml"));
QObject *object = component.create();
@@ -7687,6 +7913,7 @@ void tst_qqmlecmascript::negativeYear()
void tst_qqmlecmascript::concatenatedStringPropertyAccess()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("concatenatedStringPropertyAccess.qml"));
QObject *object = component.create();
QVERIFY(object);
@@ -7732,6 +7959,7 @@ void tst_qqmlecmascript::updateCall()
// documented it can be called from within QML. Make sure
// we don't crash when calling it.
QString file("updateCall.qml");
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(file));
QObject *object = component.create();
QVERIFY(object != nullptr);
@@ -7739,6 +7967,7 @@ void tst_qqmlecmascript::updateCall()
void tst_qqmlecmascript::numberParsing()
{
+ QQmlEngine engine;
for (int i = 1; i < 8; ++i) {
QString file("numberParsing.%1.qml");
file = file.arg(i);
@@ -7756,6 +7985,7 @@ void tst_qqmlecmascript::numberParsing()
void tst_qqmlecmascript::stringParsing()
{
+ QQmlEngine engine;
for (int i = 1; i < 7; ++i) {
QString file("stringParsing_error.%1.qml");
file = file.arg(i);
@@ -7779,6 +8009,7 @@ void tst_qqmlecmascript::push_and_shift()
void tst_qqmlecmascript::qtbug_32801()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_32801.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -7791,6 +8022,7 @@ void tst_qqmlecmascript::qtbug_32801()
void tst_qqmlecmascript::thisObject()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("thisObject.qml"));
QObject *object = component.create();
QVERIFY(object);
@@ -7800,6 +8032,7 @@ void tst_qqmlecmascript::thisObject()
void tst_qqmlecmascript::qtbug_33754()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_33754.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -7808,6 +8041,7 @@ void tst_qqmlecmascript::qtbug_33754()
void tst_qqmlecmascript::qtbug_34493()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_34493.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -7823,6 +8057,7 @@ void tst_qqmlecmascript::qtbug_34493()
// as its type*, it's parent type* and as QObject*
void tst_qqmlecmascript::singletonFromQMLToCpp()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFile("singletonTest.qml"));
QScopedPointer<QObject> obj(component.create());
if (component.errors().size())
@@ -7840,6 +8075,7 @@ void tst_qqmlecmascript::singletonFromQMLToCpp()
// and correctly compares to itself
void tst_qqmlecmascript::singletonFromQMLAndBackAndCompare()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFile("singletonTest2.qml"));
QScopedPointer<QObject> o(component.create());
if (component.errors().size())
@@ -7864,9 +8100,10 @@ void tst_qqmlecmascript::singletonFromQMLAndBackAndCompare()
void tst_qqmlecmascript::setPropertyOnInvalid()
{
+ QQmlEngine engine;
{
QQmlComponent component(&engine, testFileUrl("setPropertyOnNull.qml"));
- QString warning = component.url().toString() + ":4: TypeError: Type error";
+ QString warning = component.url().toString() + ":4: TypeError: Value is null and could not be converted to an object";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QObject *object = component.create();
QVERIFY(object);
@@ -7875,7 +8112,7 @@ void tst_qqmlecmascript::setPropertyOnInvalid()
{
QQmlComponent component(&engine, testFileUrl("setPropertyOnUndefined.qml"));
- QString warning = component.url().toString() + ":4: TypeError: Type error";
+ QString warning = component.url().toString() + ":4: TypeError: Value is undefined and could not be converted to an object";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QObject *object = component.create();
QVERIFY(object);
@@ -7885,6 +8122,7 @@ void tst_qqmlecmascript::setPropertyOnInvalid()
void tst_qqmlecmascript::miscTypeTest()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("misctypetest.qml"));
QObject *object = component.create();
@@ -7913,6 +8151,7 @@ void tst_qqmlecmascript::stackLimits()
void tst_qqmlecmascript::idsAsLValues()
{
+ QQmlEngine engine;
QString err = QString(QLatin1String("%1:5 left-hand side of assignment operator is not an lvalue\n")).arg(testFileUrl("idAsLValue.qml").toString());
QQmlComponent component(&engine, testFileUrl("idAsLValue.qml"));
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
@@ -7923,6 +8162,7 @@ void tst_qqmlecmascript::idsAsLValues()
void tst_qqmlecmascript::qtbug_34792()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug34792.qml"));
QObject *object = component.create();
@@ -7934,6 +8174,7 @@ void tst_qqmlecmascript::qtbug_34792()
void tst_qqmlecmascript::noCaptureWhenWritingProperty()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("noCaptureWhenWritingProperty.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
@@ -7942,6 +8183,7 @@ void tst_qqmlecmascript::noCaptureWhenWritingProperty()
void tst_qqmlecmascript::singletonWithEnum()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("singletontype/singletonWithEnum.qml"));
QScopedPointer<QObject> obj(component.create());
if (obj.isNull())
@@ -7963,48 +8205,53 @@ void tst_qqmlecmascript::singletonWithEnum()
void tst_qqmlecmascript::lazyBindingEvaluation()
{
- QQmlComponent component(&engine, testFileUrl("lazyBindingEvaluation.qml"));
- QScopedPointer<QObject> obj(component.create());
- if (obj.isNull())
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("lazyBindingEvaluation.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
qDebug() << component.errors().first().toString();
- QVERIFY(!obj.isNull());
- QVariant prop = obj->property("arrayLength");
- QCOMPARE(prop.type(), QVariant::Int);
- QCOMPARE(prop.toInt(), 2);
+ QVERIFY(!obj.isNull());
+ QVariant prop = obj->property("arrayLength");
+ QCOMPARE(prop.type(), QVariant::Int);
+ QCOMPARE(prop.toInt(), 2);
}
void tst_qqmlecmascript::varPropertyAccessOnObjectWithInvalidContext()
{
- QQmlComponent component(&engine, testFileUrl("varPropertyAccessOnObjectWithInvalidContext.qml"));
- QScopedPointer<QObject> obj(component.create());
- if (obj.isNull())
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("varPropertyAccessOnObjectWithInvalidContext.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
qDebug() << component.errors().first().toString();
- QVERIFY(!obj.isNull());
- QVERIFY(obj->property("success").toBool());
+ QVERIFY(!obj.isNull());
+ QVERIFY(obj->property("success").toBool());
}
void tst_qqmlecmascript::importedScriptsAccessOnObjectWithInvalidContext()
{
- QQmlComponent component(&engine, testFileUrl("importedScriptsAccessOnObjectWithInvalidContext.qml"));
- QScopedPointer<QObject> obj(component.create());
- if (obj.isNull())
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("importedScriptsAccessOnObjectWithInvalidContext.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
qDebug() << component.errors().first().toString();
- QVERIFY(!obj.isNull());
- QTRY_VERIFY(obj->property("success").toBool());
+ QVERIFY(!obj.isNull());
+ QTRY_VERIFY(obj->property("success").toBool());
}
void tst_qqmlecmascript::importedScriptsWithoutQmlMode()
{
- QQmlComponent component(&engine, testFileUrl("importScriptsWithoutQmlMode.qml"));
- QScopedPointer<QObject> obj(component.create());
- if (obj.isNull())
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("importScriptsWithoutQmlMode.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
qDebug() << component.errors().first().toString();
- QVERIFY(!obj.isNull());
- QTRY_VERIFY(obj->property("success").toBool());
+ QVERIFY(!obj.isNull());
+ QTRY_VERIFY(obj->property("success").toBool());
}
void tst_qqmlecmascript::contextObjectOnLazyBindings()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("contextObjectOnLazyBindings.qml"));
QScopedPointer<QObject> obj(component.create());
if (obj.isNull())
@@ -8017,6 +8264,7 @@ void tst_qqmlecmascript::contextObjectOnLazyBindings()
void tst_qqmlecmascript::garbageCollectionDuringCreation()
{
+ QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import Qt.test 1.0\n"
"QObjectContainerWithGCOnAppend {\n"
@@ -8044,6 +8292,7 @@ void tst_qqmlecmascript::garbageCollectionDuringCreation()
void tst_qqmlecmascript::qtbug_39520()
{
+ QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\n"
"Item {\n"
@@ -8165,6 +8414,7 @@ void tst_qqmlecmascript::switchExpression()
void tst_qqmlecmascript::qtbug_46022()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_46022.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -8175,6 +8425,7 @@ void tst_qqmlecmascript::qtbug_46022()
void tst_qqmlecmascript::qtbug_52340()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_52340.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
@@ -8186,6 +8437,7 @@ void tst_qqmlecmascript::qtbug_52340()
void tst_qqmlecmascript::qtbug_54589()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_54589.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -8197,11 +8449,12 @@ void tst_qqmlecmascript::qtbug_54687()
{
QJSEngine e;
// it's simple: this shouldn't crash.
- engine.evaluate("12\n----12");
+ e.evaluate("12\n----12");
}
void tst_qqmlecmascript::stringify_qtbug_50592()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stringify_qtbug_50592.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -8389,6 +8642,7 @@ void tst_qqmlecmascript::freeze_empty_object()
void tst_qqmlecmascript::singleBlockLoops()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_59012.qml"));
QScopedPointer<QObject> obj(component.create());
@@ -8400,6 +8654,7 @@ void tst_qqmlecmascript::singleBlockLoops()
// This fix ensures it looks up the right thing.
void tst_qqmlecmascript::qtbug_60547()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug60547/main.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
@@ -8408,6 +8663,7 @@ void tst_qqmlecmascript::qtbug_60547()
void tst_qqmlecmascript::anotherNaN()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nans.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
@@ -8513,6 +8769,35 @@ void tst_qqmlecmascript::jumpStrictNotEqualUndefined()
QCOMPARE(v.toInt(), 2);
}
+void tst_qqmlecmascript::removeBindingsWithNoDependencies()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("removeBindingsWithNoDependencies.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVariant rect = object->property("placement");
+ QCOMPARE(rect.toRectF(), QRectF(0, 0, 100, 100));
+ const QMetaObject *metaObject = object->metaObject();
+
+ {
+ const QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("placement"));
+ QVERIFY(prop.isValid());
+ QVERIFY(!QQmlPropertyPrivate::binding(object.data(), QQmlPropertyIndex(prop.propertyIndex())));
+ }
+
+ {
+ const QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("partialPlacement"));
+ QVERIFY(prop.isValid());
+ QQmlAbstractBinding *vtProxyBinding = QQmlPropertyPrivate::binding(object.data(), QQmlPropertyIndex(prop.propertyIndex()));
+ QVERIFY(vtProxyBinding);
+ QVERIFY(vtProxyBinding->isValueTypeProxy());
+
+ QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding*>(vtProxyBinding);
+ QVERIFY(!proxy->subBindings());
+ }
+
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 95098648fa..f58ae38264 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -79,6 +79,7 @@ private slots:
void componentFromEval();
void qrcUrls();
void cppSignalAndEval();
+ void singletonInstance();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -543,7 +544,7 @@ void tst_qqmlengine::outputWarningsToStandardError()
delete o;
QCOMPARE(messageHandler.messages().count(), 1);
- QCOMPARE(messageHandler.messages().at(0), QLatin1String("<Unknown File>:1:48: Unable to assign [undefined] to int"));
+ QCOMPARE(messageHandler.messages().at(0), QLatin1String("<Unknown File>:1:32: Unable to assign [undefined] to int"));
messageHandler.clear();
engine.setOutputWarningsToStandardError(false);
@@ -905,23 +906,19 @@ void tst_qqmlengine::qrcUrls()
QQmlEnginePrivate *pEngine = QQmlEnginePrivate::get(&engine);
{
- QQmlRefPointer<QQmlTypeData> oneQml(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.qml")),
- QQmlRefPointer<QQmlTypeData>::Adopt);
- QVERIFY(oneQml != nullptr);
- QQmlRefPointer<QQmlTypeData> twoQml(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.qml")),
- QQmlRefPointer<QQmlTypeData>::Adopt);
- QVERIFY(twoQml != nullptr);
- QCOMPARE(oneQml, twoQml);
+ QQmlRefPointer<QQmlTypeData> oneQml(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.qml")));
+ QVERIFY(oneQml.data() != nullptr);
+ QQmlRefPointer<QQmlTypeData> twoQml(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.qml")));
+ QVERIFY(twoQml.data() != nullptr);
+ QCOMPARE(oneQml.data(), twoQml.data());
}
{
- QQmlRefPointer<QQmlTypeData> oneJS(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.js")),
- QQmlRefPointer<QQmlTypeData>::Adopt);
- QVERIFY(oneJS != nullptr);
- QQmlRefPointer<QQmlTypeData> twoJS(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.js")),
- QQmlRefPointer<QQmlTypeData>::Adopt);
- QVERIFY(twoJS != nullptr);
- QCOMPARE(oneJS, twoJS);
+ QQmlRefPointer<QQmlTypeData> oneJS(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.js")));
+ QVERIFY(oneJS.data() != nullptr);
+ QQmlRefPointer<QQmlTypeData> twoJS(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.js")));
+ QVERIFY(twoJS.data() != nullptr);
+ QCOMPARE(oneJS.data(), twoJS.data());
}
}
@@ -956,6 +953,96 @@ void tst_qqmlengine::cppSignalAndEval()
QCOMPARE(object->property("r"), 1.1234);
}
+class CppSingleton : public QObject {
+ Q_OBJECT
+public:
+ CppSingleton() {}
+
+ static QObject *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
+ {
+ Q_UNUSED(qmlEngine);
+ Q_UNUSED(jsEngine);
+ return new CppSingleton();
+ }
+};
+
+class JsSingleton : public QObject {
+ Q_OBJECT
+public:
+ JsSingleton() {}
+
+ static QJSValue create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
+ {
+ Q_UNUSED(qmlEngine);
+ QJSValue value = jsEngine->newQObject(new JsSingleton());
+ return value;
+ }
+};
+
+class SomeQObjectClass : public QObject {
+ Q_OBJECT
+public:
+ SomeQObjectClass() : QObject(nullptr){}
+};
+
+void tst_qqmlengine::singletonInstance()
+{
+ QQmlEngine engine;
+
+ int cppSingletonTypeId = qmlRegisterSingletonType<CppSingleton>("Test", 1, 0, "CppSingleton", &CppSingleton::create);
+ int jsValueSingletonTypeId = qmlRegisterSingletonType("Test", 1, 0, "JsSingleton", &JsSingleton::create);
+
+ {
+ // Cpp QObject singleton type
+ QJSValue value = engine.singletonInstance<QJSValue>(cppSingletonTypeId);
+ QVERIFY(!value.isUndefined());
+ QVERIFY(value.isQObject());
+ QObject *instance = value.toQObject();
+ QVERIFY(instance);
+ QCOMPARE(instance->metaObject()->className(), "CppSingleton");
+ }
+
+ {
+ // QJSValue QObject singleton type
+ QJSValue value = engine.singletonInstance<QJSValue>(jsValueSingletonTypeId);
+ QVERIFY(!value.isUndefined());
+ QVERIFY(value.isQObject());
+ QObject *instance = value.toQObject();
+ QVERIFY(instance);
+ QCOMPARE(instance->metaObject()->className(), "JsSingleton");
+ }
+
+ {
+ // Invalid types
+ QJSValue value;
+ value = engine.singletonInstance<QJSValue>(-4711);
+ QVERIFY(value.isUndefined());
+ value = engine.singletonInstance<QJSValue>(1701);
+ QVERIFY(value.isUndefined());
+ }
+
+ {
+ // Valid, but non-singleton type
+ int typeId = qmlRegisterType<CppSingleton>("Test", 1, 0, "NotASingleton");
+ QJSValue value = engine.singletonInstance<QJSValue>(typeId);
+ QVERIFY(value.isUndefined());
+ }
+
+ {
+ // Cpp QObject singleton type
+ CppSingleton *instance = engine.singletonInstance<CppSingleton*>(cppSingletonTypeId);
+ QVERIFY(instance);
+ QCOMPARE(instance->metaObject()->className(), "CppSingleton");
+ QCOMPARE(instance, engine.singletonInstance<QJSValue>(cppSingletonTypeId).toQObject());
+ }
+
+ {
+ // Wrong destination type
+ SomeQObjectClass * instance = engine.singletonInstance<SomeQObjectClass*>(cppSingletonTypeId);
+ QVERIFY(!instance);
+ }
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/dynamicMeta.5.errors.txt b/tests/auto/qml/qqmllanguage/data/dynamicMeta.5.errors.txt
index 015d55b03b..30b5193cd5 100644
--- a/tests/auto/qml/qqmllanguage/data/dynamicMeta.5.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/dynamicMeta.5.errors.txt
@@ -1 +1 @@
-3:1:UnknownType is not a type
+4:5:UnknownType is not a type
diff --git a/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt b/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt
index 3813680562..4f3f758b7e 100644
--- a/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt
+++ b/tests/auto/qml/qqmllanguage/data/incorrectCase.errors.insensitive.txt
@@ -1,2 +1,2 @@
-3:1:Type IncorrectCaseType unavailable
+3:1:IncorrectCaseType is not a type
-1:-1:File name case mismatch
diff --git a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
index db7d9c0f60..cefd62f9d4 100644
--- a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
@@ -1 +1 @@
-4:18:Unexpected object assignment
+4:18:Unexpected object assignment for property "x"
diff --git a/tests/auto/qml/qqmllanguage/data/property.4.errors.txt b/tests/auto/qml/qqmllanguage/data/property.4.errors.txt
index b447186849..2807384ec4 100644
--- a/tests/auto/qml/qqmllanguage/data/property.4.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/property.4.errors.txt
@@ -1 +1 @@
-5:1:Syntax error
+5:1:Expected token `:'
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest18.qml b/tests/auto/qml/qqmllanguage/data/singletonTest18.qml
new file mode 100644
index 0000000000..7616c23531
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/singletonTest18.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import "singleton"
+import Test 1.0
+
+Item {
+ property var qmlSingleton: SingletonType
+ property var jsSingleton: MyQJSValueQObjectSingleton
+ property var cppSingleton: MyTypeObjectSingleton
+}
diff --git a/tests/auto/qml/qqmllanguage/data/wrongType.16.errors.txt b/tests/auto/qml/qqmllanguage/data/wrongType.16.errors.txt
index 77cf210918..cedae349d2 100644
--- a/tests/auto/qml/qqmllanguage/data/wrongType.16.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/wrongType.16.errors.txt
@@ -1 +1 @@
-4:24:Cannot assign object to property
+4:24:Cannot assign object of type "QtObject" to property of type "MyQmlObject*" as the former is neither the same as the latter nor a sub-class of it.
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 0eb4f26878..7e247b1906 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -35,6 +35,14 @@ static QObject *myTypeObjectSingleton(QQmlEngine *engine, QJSEngine *scriptEngin
return new MyTypeObject();
}
+static QJSValue myQJSValueQObjectSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(engine)
+
+ QJSValue value = scriptEngine->newQObject(new MyTypeObject());
+ return value;
+}
+
void registerTypes()
{
qmlRegisterInterface<MyInterface>("MyInterface");
@@ -101,6 +109,7 @@ void registerTypes()
qmlRegisterType<MyCompositeBaseType>("Test", 1, 0, "MyCompositeBaseType");
qmlRegisterSingletonType<MyTypeObjectSingleton>("Test", 1, 0, "MyTypeObjectSingleton", myTypeObjectSingleton);
+ qmlRegisterSingletonType("Test", 1, 0, "MyQJSValueQObjectSingleton", myQJSValueQObjectSingleton);
qmlRegisterType<MyArrayBufferTestClass>("Test", 1, 0, "MyArrayBufferTestClass");
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 8913528d79..f3569c2efe 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -246,6 +246,8 @@ private slots:
void compositeSingletonRegistered();
void compositeSingletonCircular();
+ void singletonsHaveContextAndEngine();
+
void customParserBindingScopes();
void customParserEvaluateEnum();
void customParserProperties();
@@ -288,6 +290,8 @@ private slots:
void valueTypeGroupPropertiesInBehavior();
+ void retrieveQmlTypeId();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -2193,7 +2197,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode()
QUrl url = testFileUrl("scriptString7.qml");
{
QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine);
- QQmlTypeData *td = eng->typeLoader.getType(url);
+ QQmlRefPointer<QQmlTypeData> td = eng->typeLoader.getType(url);
Q_ASSERT(td);
const QV4::CompiledData::Unit *readOnlyQmlUnit = td->compilationUnit()->data;
@@ -3923,11 +3927,13 @@ void tst_qqmllanguage::getSingletonInstance(QObject* o, const char* propertyName
return;
QVariant variant = o->property(propertyName);
- QVERIFY(variant.userType() == qMetaTypeId<QObject *>());
+ QVERIFY(variant.isValid());
QObject *singleton = nullptr;
- if (variant.canConvert<QObject*>())
+ if (variant.userType() == qMetaTypeId<QObject *>())
singleton = variant.value<QObject*>();
+ else if (variant.userType() == qMetaTypeId<QJSValue>())
+ singleton = variant.value<QJSValue>().toQObject();
QVERIFY(singleton != nullptr);
*result = singleton;
@@ -4232,6 +4238,24 @@ void tst_qqmllanguage::compositeSingletonCircular()
QCOMPARE(o->property("value").toInt(), 2);
}
+void tst_qqmllanguage::singletonsHaveContextAndEngine()
+{
+ QObject *qmlSingleton = nullptr;
+ getSingletonInstance(engine, "singletonTest18.qml", "qmlSingleton", &qmlSingleton);
+ QVERIFY(qmlContext(qmlSingleton));
+ QCOMPARE(qmlEngine(qmlSingleton), &engine);
+
+ QObject *jsSingleton = nullptr;
+ getSingletonInstance(engine, "singletonTest18.qml", "jsSingleton", &jsSingleton);
+ QVERIFY(qmlContext(jsSingleton));
+ QCOMPARE(qmlEngine(jsSingleton), &engine);
+
+ QObject *cppSingleton = nullptr;
+ getSingletonInstance(engine, "singletonTest18.qml", "cppSingleton", &cppSingleton);
+ QVERIFY(qmlContext(cppSingleton));
+ QCOMPARE(qmlEngine(cppSingleton), &engine);
+}
+
void tst_qqmllanguage::customParserBindingScopes()
{
QQmlComponent component(&engine, testFile("customParserBindingScopes.qml"));
@@ -4934,6 +4958,26 @@ void tst_qqmllanguage::valueTypeGroupPropertiesInBehavior()
QCOMPARE(animation->property("easing").value<QEasingCurve>().type(), QEasingCurve::InOutQuad);
}
+void tst_qqmllanguage::retrieveQmlTypeId()
+{
+ // Register in reverse order to provoke wrong minor version matching.
+ int id2 = qmlRegisterType<QObject>("Test", 2, 3, "SomeTestType");
+ int id1 = qmlRegisterType<QObject>("Test", 2, 1, "SomeTestType");
+ QCOMPARE(qmlTypeId("Test", 2, 1, "SomeTestType"), id1);
+ QCOMPARE(qmlTypeId("Test", 2, 2, "SomeTestType"), id1);
+ QCOMPARE(qmlTypeId("Test", 2, 3, "SomeTestType"), id2);
+
+ // Error cases
+ QCOMPARE(qmlTypeId("Test", 2, 0, "SomeTestType"), -1);
+ QCOMPARE(qmlTypeId("Test", 2, 3, "DoesNotExist"), -1);
+ QCOMPARE(qmlTypeId("DoesNotExist", 2, 3, "SomeTestType"), -1);
+
+ // Must also work for other types (defined in testtpes.cpp)
+ QVERIFY(qmlTypeId("Test", 1, 0, "MyExtendedUncreateableBaseClass") >= 0);
+ QVERIFY(qmlTypeId("Test", 1, 0, "MyUncreateableBaseClass") >= 0);
+ QVERIFY(qmlTypeId("Test", 1, 0, "MyTypeObjectSingleton") >= 0);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qml/qqmllistmodel/data/dynamicroles.qml b/tests/auto/qml/qqmllistmodel/data/dynamicroles.qml
new file mode 100644
index 0000000000..7d3650c3b9
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodel/data/dynamicroles.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ ListModel {
+ id: listModel
+ objectName: "listModel"
+ dynamicRoles: true
+
+ // have to add elements dynamically when dynamicRoles = true
+ function appendNewElement() {
+ listModel.append({"name": "test", "obj": null})
+ }
+
+ function setElementAgain() {
+ var element = listModel.get(0)
+ listModel.set(0, element)
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmllistmodel/data/qtbug38907.qml b/tests/auto/qml/qqmllistmodel/data/qtbug38907.qml
new file mode 100644
index 0000000000..0abf221f60
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodel/data/qtbug38907.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.0
+import QtTest 1.0
+
+Item {
+
+ Item {
+ id : testItem
+ property string name : "testObject"
+ property var object : this
+ function testMethod() {
+ return -1;
+ }
+ }
+
+ ListModel {
+ id : listModel
+ dynamicRoles : true
+ }
+
+ function exec() {
+ listModel.append(testItem);
+ listModel.append({ item : testItem });
+ return true;
+ }
+}
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 9fdc54f067..771f3e5c4e 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -106,6 +106,7 @@ private slots:
void get_nested_data();
void crash_model_with_multiple_roles();
void crash_model_with_unknown_roles();
+ void crash_model_with_dynamic_roles();
void set_model_cache();
void property_changes();
void property_changes_data();
@@ -126,6 +127,7 @@ private slots:
void stringifyModelEntry();
void qobjectTrackerForDynamicModelObjects();
void crash_append_empty_array();
+ void dynamic_roles_crash_QTBUG_38907();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -984,6 +986,97 @@ void tst_qqmllistmodel::crash_model_with_unknown_roles()
model->index(0, 0, QModelIndex()).data(Qt::UserRole);
}
+//QTBUG-35639
+void tst_qqmllistmodel::crash_model_with_dynamic_roles()
+{
+ {
+ // setting a dynamic role to a QObject value, then triggering dtor
+ QQmlEngine eng;
+ QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
+ QObject *rootItem = component.create();
+ qWarning() << component.errorString();
+ QVERIFY(component.errorString().isEmpty());
+ QVERIFY(rootItem != 0);
+ QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
+ QVERIFY(model != 0);
+
+ QMetaObject::invokeMethod(model, "appendNewElement");
+
+ QObject *testObj = new QObject;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
+ delete testObj;
+
+ // delete the root item, which will cause the model dtor to run
+ // previously, this would crash as it attempted to delete testObj.
+ delete rootItem;
+ }
+
+ {
+ // setting a dynamic role to a QObject value, then triggering
+ // DynamicRoleModelNode::updateValues() to trigger unsafe qobject_cast
+ QQmlEngine eng;
+ QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
+ QObject *rootItem = component.create();
+ qWarning() << component.errorString();
+ QVERIFY(component.errorString().isEmpty());
+ QVERIFY(rootItem != 0);
+ QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
+ QVERIFY(model != 0);
+
+ QMetaObject::invokeMethod(model, "appendNewElement");
+
+ QObject *testObj = new QObject;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
+ delete testObj;
+
+ QMetaObject::invokeMethod(model, "setElementAgain");
+
+ delete rootItem;
+ }
+
+ {
+ // setting a dynamic role to a QObject value, then triggering
+ // DynamicRoleModelNodeMetaObject::propertyWrite()
+
+ /*
+ XXX TODO: I couldn't reproduce this one simply - I think it
+ requires a WorkerScript sync() call, and that's non-trivial.
+ I thought I could do it simply via:
+
+ QQmlEngine eng;
+ QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
+ QObject *rootItem = component.create();
+ qWarning() << component.errorString();
+ QVERIFY(component.errorString().isEmpty());
+ QVERIFY(rootItem != 0);
+ QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
+ QVERIFY(model != 0);
+
+ QMetaObject::invokeMethod(model, "appendNewElement");
+
+ QObject *testObj = new QObject;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
+ delete testObj;
+ QObject *testObj2 = new QObject;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj2));
+
+ But it turns out that that doesn't work (the setValue() call within
+ setProperty() doesn't seem to trigger the right codepath, for some
+ reason), and you can't trigger it manually via:
+
+ QObject *testObj2 = new QObject;
+ void *a[] = { testObj2, 0 };
+ QMetaObject::metacall(dynamicNodeModel, QMetaObject::WriteProperty, 0, a);
+
+ because the dynamicNodeModel for that index cannot be retrieved
+ using the public API.
+
+ But, anyway, I think the above two test cases are sufficient to
+ show that QObject* values should be guarded internally.
+ */
+ }
+}
+
//QTBUG-15190
void tst_qqmllistmodel::set_model_cache()
{
@@ -1556,6 +1649,24 @@ void tst_qqmllistmodel::crash_append_empty_array()
QCOMPARE(spy.count(), 0);
}
+void tst_qqmllistmodel::dynamic_roles_crash_QTBUG_38907()
+{
+ QQmlEngine eng;
+ QQmlComponent component(&eng, testFileUrl("qtbug38907.qml"));
+ QVERIFY(!component.isError());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
+ QVERIFY(item != 0);
+
+ QVariant retVal;
+
+ QMetaObject::invokeMethod(item.data(),
+ "exec",
+ Qt::DirectConnection,
+ Q_RETURN_ARG(QVariant, retVal));
+
+ QVERIFY(retVal.toBool());
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
index 7fd4d69b5e..44ce1d6987 100644
--- a/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
+++ b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
@@ -53,7 +53,7 @@ void tst_qqmlopenmetaobject::createProperties()
QQmlEngine engine;
CustomObject object;
const QQmlRefPointer<QQmlOpenMetaObjectType> mot = new QQmlOpenMetaObjectType(object.metaObject(), &engine);
- QQmlOpenMetaObject *const mo = new QQmlOpenMetaObject(&object, mot);
+ QQmlOpenMetaObject *const mo = new QQmlOpenMetaObject(&object, mot.data());
mo->setCached(true);
mot->createProperty("customProperty");
QVERIFY(true);
diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
index ba2b836a6d..ce9d0ac894 100644
--- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
+++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
@@ -50,6 +50,9 @@ private slots:
void qmlParser();
#endif
void invalidEscapeSequence();
+ void stringLiteral();
+ void noSubstitutionTemplateLiteral();
+ void templateLiteral();
private:
QStringList excludedDirs;
@@ -78,6 +81,13 @@ public:
const quint32 parentBegin = parent->firstSourceLocation().begin();
const quint32 parentEnd = parent->lastSourceLocation().end();
+ if (node->firstSourceLocation().begin() < parentBegin)
+ qDebug() << "first source loc failed: node:" << node->kind << "at" << node->firstSourceLocation().startLine << "/" << node->firstSourceLocation().startColumn
+ << "parent" << parent->kind << "at" << parent->firstSourceLocation().startLine << "/" << parent->firstSourceLocation().startColumn;
+ if (node->lastSourceLocation().end() > parentEnd)
+ qDebug() << "first source loc failed: node:" << node->kind << "at" << node->lastSourceLocation().startLine << "/" << node->lastSourceLocation().startColumn
+ << "parent" << parent->kind << "at" << parent->lastSourceLocation().startLine << "/" << parent->lastSourceLocation().startColumn;
+
QVERIFY(node->firstSourceLocation().begin() >= parentBegin);
QVERIFY(node->lastSourceLocation().end() <= parentEnd);
}
@@ -183,13 +193,12 @@ void tst_qqmlparser::qmlParser()
Lexer lexer(&engine);
lexer.setCode(code, 1, qmlMode);
Parser parser(&engine);
- if (qmlMode)
- parser.parse();
- else
- parser.parseProgram();
+ bool ok = qmlMode ? parser.parse() : parser.parseProgram();
- check::Check chk;
- chk(parser.rootNode());
+ if (ok) {
+ check::Check chk;
+ chk(parser.rootNode());
+ }
}
#endif
@@ -204,6 +213,67 @@ void tst_qqmlparser::invalidEscapeSequence()
parser.parse();
}
+void tst_qqmlparser::stringLiteral()
+{
+ using namespace QQmlJS;
+
+ Engine engine;
+ Lexer lexer(&engine);
+ QLatin1String code("'hello string'");
+ lexer.setCode(code , 1);
+ Parser parser(&engine);
+ QVERIFY(parser.parseExpression());
+ AST::ExpressionNode *expression = parser.expression();
+ QVERIFY(expression);
+ auto *literal = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expression);
+ QVERIFY(literal);
+ QCOMPARE(literal->value, "hello string");
+ QCOMPARE(literal->firstSourceLocation().begin(), 0);
+ QCOMPARE(literal->lastSourceLocation().end(), code.size());
+}
+
+void tst_qqmlparser::noSubstitutionTemplateLiteral()
+{
+ using namespace QQmlJS;
+
+ Engine engine;
+ Lexer lexer(&engine);
+ QLatin1String code("`hello template`");
+ lexer.setCode(code, 1);
+ Parser parser(&engine);
+ QVERIFY(parser.parseExpression());
+ AST::ExpressionNode *expression = parser.expression();
+ QVERIFY(expression);
+
+ auto *literal = QQmlJS::AST::cast<QQmlJS::AST::TemplateLiteral *>(expression);
+ QVERIFY(literal);
+
+ QCOMPARE(literal->value, "hello template");
+ QCOMPARE(literal->firstSourceLocation().begin(), 0);
+ QCOMPARE(literal->lastSourceLocation().end(), code.size());
+}
+
+void tst_qqmlparser::templateLiteral()
+{
+ using namespace QQmlJS;
+
+ Engine engine;
+ Lexer lexer(&engine);
+ QLatin1String code("`one plus one equals ${1+1}!`");
+ lexer.setCode(code, 1);
+ Parser parser(&engine);
+ QVERIFY(parser.parseExpression());
+ AST::ExpressionNode *expression = parser.expression();
+ QVERIFY(expression);
+
+ auto *templateLiteral = QQmlJS::AST::cast<QQmlJS::AST::TemplateLiteral *>(expression);
+ QVERIFY(templateLiteral);
+
+ QCOMPARE(templateLiteral->firstSourceLocation().begin(), 0);
+ auto *e = templateLiteral->expression;
+ QVERIFY(e);
+}
+
QTEST_MAIN(tst_qqmlparser)
#include "tst_qqmlparser.moc"
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index ef2136bc64..ba7c85df15 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -2007,15 +2007,15 @@ void tst_qqmlproperty::warnOnInvalidBinding()
QString expectedWarning;
// V4 error message for property-to-property binding
- expectedWarning = testUrl.toString() + QString::fromLatin1(":6:36: Unable to assign QQuickText to QQuickRectangle");
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":6:5: Unable to assign QQuickText to QQuickRectangle");
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
// V8 error message for function-to-property binding
- expectedWarning = testUrl.toString() + QString::fromLatin1(":7:36: Unable to assign QQuickText to QQuickRectangle");
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":7:5: Unable to assign QQuickText to QQuickRectangle");
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
// V8 error message for invalid binding to anchor
- expectedWarning = testUrl.toString() + QString::fromLatin1(":14:33: Unable to assign QQuickItem_QML_8 to QQuickAnchorLine");
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":14:9: Unable to assign QQuickItem_QML_8 to QQuickAnchorLine");
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
QQmlComponent component(&engine, testUrl);
@@ -2064,14 +2064,15 @@ void tst_qqmlproperty::floatToStringPrecision_data()
QTest::addColumn<QString>("propertyName");
QTest::addColumn<double>("number");
QTest::addColumn<QString>("qtString");
+ QTest::addColumn<QString>("alternateQtString");
QTest::addColumn<QString>("jsString");
- QTest::newRow("3.4") << "a" << 3.4 << "3.4" << "3.4";
- QTest::newRow("0.035003945") << "b" << 0.035003945 << "0.035003945" << "0.035003945";
- QTest::newRow("0.0000012345") << "c" << 0.0000012345 << "1.2345e-06" << "0.0000012345";
- QTest::newRow("0.00000012345") << "d" << 0.00000012345 << "1.2345e-07" << "1.2345e-7";
- QTest::newRow("1e20") << "e" << 1e20 << "1e+20" << "100000000000000000000";
- QTest::newRow("1e21") << "f" << 1e21 << "1e+21" << "1e+21";
+ QTest::newRow("3.4") << "a" << 3.4 << "3.4" << "3.4" << "3.4";
+ QTest::newRow("0.035003945") << "b" << 0.035003945 << "0.035003945" << "0.0035003945" << "0.035003945";
+ QTest::newRow("0.0000012345") << "c" << 0.0000012345 << "1.2345e-6" << "1.2345e-06" << "0.0000012345";
+ QTest::newRow("0.00000012345") << "d" << 0.00000012345 << "1.2345e-7" << "1.2345e-07" << "1.2345e-7";
+ QTest::newRow("1e20") << "e" << 1e20 << "1e+20" << "1e+20" << "100000000000000000000";
+ QTest::newRow("1e21") << "f" << 1e21 << "1e+21" << "1e+21" << "1e+21";
}
void tst_qqmlproperty::floatToStringPrecision()
@@ -2083,15 +2084,24 @@ void tst_qqmlproperty::floatToStringPrecision()
QFETCH(QString, propertyName);
QFETCH(double, number);
QFETCH(QString, qtString);
+ QFETCH(QString, alternateQtString);
QFETCH(QString, jsString);
QByteArray name = propertyName.toLatin1();
QCOMPARE(obj->property(name).toDouble(), number);
- QCOMPARE(obj->property(name).toString(), qtString);
+ if (obj->property(name).toString() != qtString) {
+ QCOMPARE(obj->property(name).toString(), alternateQtString);
+ } else {
+ QCOMPARE(obj->property(name).toString(), qtString);
+ }
QByteArray name1 = (propertyName + QLatin1Char('1')).toLatin1();
QCOMPARE(obj->property(name1).toDouble(), number);
- QCOMPARE(obj->property(name1).toString(), qtString);
+ if (obj->property(name1).toString() != qtString) {
+ QCOMPARE(obj->property(name1).toString(), alternateQtString);
+ } else {
+ QCOMPARE(obj->property(name1).toString(), qtString);
+ }
QByteArray name2 = (propertyName + QLatin1Char('2')).toLatin1();
QCOMPARE(obj->property(name2).toDouble(), number);
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index b9e56b39a2..29f70c4e46 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -95,7 +95,7 @@ Q_SIGNALS:
void signalB();
};
-QQmlPropertyData *cacheProperty(QQmlPropertyCache *cache, const char *name)
+QQmlPropertyData *cacheProperty(const QQmlRefPointer<QQmlPropertyCache> &cache, const char *name)
{
return cache->property(QLatin1String(name), nullptr, nullptr);
}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index b96eecafe8..2d8115e867 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -505,8 +505,14 @@ void tst_qqmlqt::font()
QObject *object = component.create();
QVERIFY(object != nullptr);
- QCOMPARE(qvariant_cast<QFont>(object->property("test1")), QFont("Arial", 22));
- QCOMPARE(qvariant_cast<QFont>(object->property("test2")), QFont("Arial", 20, QFont::DemiBold, true));
+ QFont f;
+ f.setFamily("Arial");
+ f.setPointSize(22);
+ QCOMPARE(qvariant_cast<QFont>(object->property("test1")), f);
+ f.setPointSize(20);
+ f.setWeight(QFont::DemiBold);
+ f.setItalic(true);
+ QCOMPARE(qvariant_cast<QFont>(object->property("test2")), f);
QCOMPARE(qvariant_cast<QFont>(object->property("test3")), QFont());
QCOMPARE(qvariant_cast<QFont>(object->property("test4")), QFont());
diff --git a/tests/auto/qml/qqmltranslation/data/translationChange.qml b/tests/auto/qml/qqmltranslation/data/translationChange.qml
index c48a482138..ae3231935c 100644
--- a/tests/auto/qml/qqmltranslation/data/translationChange.qml
+++ b/tests/auto/qml/qqmltranslation/data/translationChange.qml
@@ -3,6 +3,13 @@ import QtQuick 2.0
TranslationChangeBase {
id: root
+ ListModel {
+ id: listModel
+ ListElement {
+ text: qsTr("translate me")
+ }
+ }
+
baseProperty: "do not translate"
property string text1: qsTr("translate me")
function weDoTranslations() {
@@ -10,6 +17,7 @@ TranslationChangeBase {
}
property string text2: weDoTranslations()
property string text3
+ property string fromListModel: listModel.get(0).text
states: [
State {
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index 1c67ba5541..5042a236d4 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -76,7 +76,7 @@ void tst_qqmltranslation::translation()
if (verifyCompiledData) {
QQmlContext *context = qmlContext(object);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
- QQmlTypeData *typeData = engine->typeLoader.getType(context->baseUrl());
+ QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl());
QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit();
QVERIFY(compilationUnit);
@@ -136,7 +136,7 @@ void tst_qqmltranslation::idTranslation()
{
QQmlContext *context = qmlContext(object);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
- QQmlTypeData *typeData = engine->typeLoader.getType(context->baseUrl());
+ QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl());
QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit();
QVERIFY(compilationUnit);
@@ -195,6 +195,7 @@ void tst_qqmltranslation::translationChange()
QCOMPARE(object->property("text1").toString(), QString::fromUtf8("translate me"));
QCOMPARE(object->property("text2").toString(), QString::fromUtf8("translate me"));
QCOMPARE(object->property("text3").toString(), QString::fromUtf8("translate me"));
+ QCOMPARE(object->property("fromListModel").toString(), QString::fromUtf8("translate me"));
DummyTranslator translator;
QCoreApplication::installTranslator(&translator);
@@ -206,6 +207,7 @@ void tst_qqmltranslation::translationChange()
QCOMPARE(object->property("text1").toString(), QString::fromUtf8("xxx"));
QCOMPARE(object->property("text2").toString(), QString::fromUtf8("xxx"));
QCOMPARE(object->property("text3").toString(), QString::fromUtf8("xxx"));
+ QCOMPARE(object->property("fromListModel").toString(), QString::fromUtf8("xxx"));
QCoreApplication::removeTranslator(&translator);
}
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index d336d033a3..cf3bc8b050 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -87,7 +87,7 @@ void tst_QQMLTypeLoader::trimCache()
QUrl url = testFileUrl("trim_cache.qml");
url.setQuery(QString::number(i));
- QQmlTypeData *data = loader.getType(url);
+ QQmlTypeData *data = loader.getType(url).take();
// Run an event loop to receive the callback that release()es.
QTRY_COMPARE(data->count(), 2);
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index a456facd2f..1ee4510e30 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -1020,7 +1020,7 @@ void tst_qqmlvaluetypes::bindingAssignment()
// function assignment should fail without crashing
{
- QString warning1 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":6:13: Invalid use of Qt.binding() in a binding declaration.");
+ QString warning1 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":6:5: Invalid use of Qt.binding() in a binding declaration.");
QString warning2 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":10: Cannot assign JavaScript function to value-type property");
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
@@ -1125,7 +1125,7 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.3.qml"));
- QString warning = component.url().toString() + ":6:11: Unable to assign [undefined] to QRect";
+ QString warning = component.url().toString() + ":6:5: Unable to assign [undefined] to QRect";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != nullptr);
diff --git a/tests/auto/qml/qv4identifiertable/qv4identifiertable.pro b/tests/auto/qml/qv4identifiertable/qv4identifiertable.pro
new file mode 100644
index 0000000000..64dc822367
--- /dev/null
+++ b/tests/auto/qml/qv4identifiertable/qv4identifiertable.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qv4identifiertable
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qv4identifiertable.cpp
+
+QT += qml qml-private testlib
+
diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
new file mode 100644
index 0000000000..b2908ac5bb
--- /dev/null
+++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 basysKom GmbH.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QQmlEngine>
+#include <private/qv4identifiertable_p.h>
+
+class tst_qv4identifiertable : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void sweepFirstEntryInBucket();
+ void sweepCenterEntryInBucket();
+ void sweepLastEntryInBucket();
+ void sweepFirstEntryInSameBucketWithDifferingHash();
+ void dontSweepAcrossBucketBoundaries();
+ void sweepAcrossBucketBoundariesIfFirstBucketFull();
+};
+
+void tst_qv4identifiertable::sweepFirstEntryInBucket()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // All strings go into the same bucket
+ entry1->stringHash = 0;
+ entry2->stringHash = 0;
+ entry3->stringHash = 0;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+
+ QCOMPARE(table.size, 3);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+ entry3->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry2);
+ QCOMPARE(table.entriesByHash[1], entry3);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+void tst_qv4identifiertable::sweepCenterEntryInBucket()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // All strings go into the same bucket
+ entry1->stringHash = 0;
+ entry2->stringHash = 0;
+ entry3->stringHash = 0;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+
+ QCOMPARE(table.size, 3);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+
+ entry1->setMarkBit();
+ // second entry not marked
+ entry3->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry3);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+void tst_qv4identifiertable::sweepLastEntryInBucket()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // All strings go into the same bucket
+ entry1->stringHash = 0;
+ entry2->stringHash = 0;
+ entry3->stringHash = 0;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+
+ QCOMPARE(table.size, 3);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+
+ entry1->setMarkBit();
+ entry2->setMarkBit();
+ // third entry not marked
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+void tst_qv4identifiertable::sweepFirstEntryInSameBucketWithDifferingHash()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+
+ // First and second entry have differing hash but end up in the
+ // same bucket after modulo alloc.
+ entry1->stringHash = 0;
+ entry2->stringHash = 5;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+
+ QCOMPARE(table.size, 2);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry2);
+ QCOMPARE(table.entriesByHash[1], nullptr);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+}
+
+void tst_qv4identifiertable::dontSweepAcrossBucketBoundaries()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // Different buckets for both entries.
+ entry1->stringHash = 0;
+ entry2->stringHash = 1;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+
+ QCOMPARE(table.size, 2);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], nullptr);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+}
+
+void tst_qv4identifiertable::sweepAcrossBucketBoundariesIfFirstBucketFull()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/3);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+ auto entry4 = engine.newString(QStringLiteral("four"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+ entry4->createHashValue();
+
+ // First, third and fourth entry have the same bucket (after modulo) and
+ // would typically end up in order [entry1, entry3, entry4, entry2]. However
+ // since null termination isn't guaranteed, an insertion order of
+ // entry1, entry2, entry3 and entry4 results in a
+ // table [entry1, entry2, entry3, entry4].
+ entry1->stringHash = 0;
+ entry2->stringHash = 1;
+ entry3->stringHash = 11;
+ entry4->stringHash = 11;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+ table.asPropertyKey(entry4);
+
+ QCOMPARE(table.size, 4);
+ QCOMPARE(table.alloc, 11);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], entry4);
+ QCOMPARE(table.entriesByHash[4], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+ entry3->setMarkBit();
+ entry4->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry3);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry4);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+QTEST_MAIN(tst_qv4identifiertable)
+
+#include "tst_qv4identifiertable.moc"
diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
index d4ba363d00..07f8e9f1d1 100644
--- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp
+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
#include <QQmlEngine>
+#include <QLoggingCategory>
#include <private/qv4mm_p.h>
class tst_qv4mm : public QObject
@@ -36,23 +37,15 @@ class tst_qv4mm : public QObject
private slots:
void gcStats();
- void tweaks();
};
void tst_qv4mm::gcStats()
{
- qputenv(QV4_MM_STATS, "1");
+ QLoggingCategory::setFilterRules("qt.qml.gc.*=true");
QQmlEngine engine;
engine.collectGarbage();
}
-void tst_qv4mm::tweaks()
-{
- qputenv(QV4_MM_MAXBLOCK_SHIFT, "5");
- qputenv(QV4_MM_MAX_CHUNK_SIZE, "65536");
- QQmlEngine engine;
-}
-
QTEST_MAIN(tst_qv4mm)
#include "tst_qv4mm.moc"
diff --git a/tests/auto/qmltest/rectangle/tst_rectangle.qml b/tests/auto/qmltest/rectangle/tst_rectangle.qml
index 9af55b6a79..cf57da0d73 100644
--- a/tests/auto/qmltest/rectangle/tst_rectangle.qml
+++ b/tests/auto/qmltest/rectangle/tst_rectangle.qml
@@ -48,7 +48,7 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.12
import QtTest 1.1
Item {
@@ -83,6 +83,17 @@ Item {
}
Rectangle {
+ id: horizontalGradient
+ width: 300
+ height: 100
+ gradient: Gradient {
+ orientation: Gradient.Horizontal
+ GradientStop { position: 0.0; color: "red" }
+ GradientStop { position: 1.0; color: "green" }
+ }
+ }
+
+ Rectangle {
id: rectangleborder
width: 300
height: 150
@@ -132,8 +143,18 @@ Item {
compare(gstops[0].color.toString(), "#ff0000")
compare(gstops[1].color.toString(), "#ffff00")
compare(gstops[2].color.toString(), "#008000")
+ compare(grad.orientation, Gradient.Vertical)
+ }
+
+ function test_horizontalGradient() {
+ var grad = horizontalGradient.gradient;
+ var gstops = grad.stops;
+ compare(gstops[0].color.toString(), "#ff0000")
+ compare(gstops[1].color.toString(), "#008000")
+ compare(grad.orientation, Gradient.Horizontal)
}
+
function test_borders() {
compare(rectangleborder.border.width, 1)
compare(rectangleborder.border.color.toString(), "#808080")
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index eee8dfcf26..ea8830fefa 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -74,7 +74,6 @@ tst_examples::tst_examples()
{
// Add files to exclude here
excludedFiles << "snippets/qml/listmodel/listmodel.qml"; //Just a ListModel, no root QQuickItem
- excludedFiles << "examples/quick/demos/photosurface/photosurface.qml"; // root item is Window rather than Item
// Add directories you want excluded here
excludedDirs << "shared"; //Not an example
@@ -91,9 +90,6 @@ tst_examples::tst_examples()
excludedFiles << "examples/quick/shapes/content/interactive.qml"; // relies on resources
#ifdef QT_NO_XMLPATTERNS
- excludedDirs << "demos/twitter";
- excludedDirs << "demos/flickr";
- excludedDirs << "demos/photoviewer";
excludedFiles << "snippets/qml/xmlrole.qml";
excludedFiles << "particles/itemparticle/particleview.qml";
excludedFiles << "views/visualdatamodel/slideshow.qml";
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
new file mode 100644
index 0000000000..485c6ce914
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import Qt.labs.handlers 1.0
+
+Item {
+ id: root
+ property int value: 50
+ property int maximumValue: 99
+ property alias label: label.text
+ property alias tapEnabled: tap.enabled
+ property alias pressed: tap.pressed
+ signal tapped
+
+ DragHandler {
+ id: dragHandler
+ objectName: root.objectName + " DragHandler"
+ target: knob
+ xAxis.enabled: false
+ yAxis.minimum: slot.y
+ yAxis.maximum: slot.height + slot.y - knob.height
+ }
+
+ Rectangle {
+ id: slot
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 10
+ anchors.topMargin: 30
+ anchors.bottomMargin: 30
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 10
+ color: "black"
+ radius: width / 2
+ smooth: true
+ }
+
+ Rectangle {
+ id: glow
+ anchors.fill: knob
+ anchors.margins: -5
+ anchors.leftMargin: -2
+ anchors.horizontalCenterOffset: 1
+ radius: 5
+ color: "#4400FFFF"
+ opacity: tap.pressed || tapFlash.running ? 1 : 0
+ FlashAnimation on visible {
+ id: tapFlash
+ }
+ }
+ Rectangle {
+ id: knob
+ objectName: "Slider Knob"
+ width: parent.width - 2
+ height: 20
+ radius: 5
+ color: "darkgray"
+ border.color: "black"
+ property bool programmatic: false
+ property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum)
+ onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier
+ transformOrigin: Item.Center
+ function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier }
+ TapHandler {
+ id: tap
+ objectName: root.objectName + " TapHandler"
+ gesturePolicy: TapHandler.DragThreshold
+ onTapped: {
+ tapFlash.start()
+ root.tapped
+ }
+ }
+ }
+
+ Text {
+ color: "red"
+ anchors.top: slot.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: root.value
+ }
+
+ Text {
+ id: label
+ font.pointSize: 9
+ color: "red"
+ anchors.bottom: slot.top
+ anchors.bottomMargin: 5
+ anchors.horizontalCenter: parent.horizontalCenter
+ verticalAlignment: Text.AlignBottom
+ }
+
+ Component.onCompleted: {
+ knob.programmatic = true
+ knob.setValue(root.value)
+ knob.programmatic = false
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
index f6acd53615..7f6535651c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -80,14 +80,14 @@ Item {
function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier }
DragHandler {
id: dragHandler
- objectName: label.text + " DragHandler"
+ objectName: root.objectName + " DragHandler"
xAxis.enabled: false
yAxis.minimum: slot.y
yAxis.maximum: slot.height + slot.y - knob.height
}
TapHandler {
id: tap
- objectName: label.text + " TapHandler"
+ objectName: root.objectName + " TapHandler"
gesturePolicy: TapHandler.DragThreshold
onTapped: {
tapFlash.start()
@@ -97,20 +97,20 @@ Item {
}
Text {
- font.pointSize: 16
color: "red"
- anchors.bottom: parent.bottom
+ anchors.top: slot.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: root.value
}
Text {
id: label
- font.pointSize: 12
+ font.pointSize: 9
color: "red"
- anchors.top: parent.top
- anchors.topMargin: 5
+ anchors.bottom: slot.top
+ anchors.bottomMargin: 5
anchors.horizontalCenter: parent.horizontalCenter
+ verticalAlignment: Text.AlignBottom
}
Component.onCompleted: {
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
index 7d7f53dd15..8adec58621 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
@@ -46,10 +46,15 @@ Rectangle {
Row {
spacing: 6
- Slider {
- label: "DragHandler"
- objectName: "Slider"
- value: 49; width: 100; height: 400
+ KnobDragSlider {
+ label: "Slider with\nDH on knob"
+ objectName: "knobSlider"
+ value: 49; width: 120; height: 400
+ }
+ GrooveDragSlider {
+ label: "Slider with\nDH on root"
+ objectName: "grooveSlider"
+ value: 49; width: 120; height: 400
}
Column {
spacing: 6
@@ -80,6 +85,7 @@ Rectangle {
objectName: "drag"
DragHandler {
id: drag1
+ objectName: "drag1"
}
Text {
anchors.centerIn: parent
@@ -96,6 +102,7 @@ Rectangle {
border.width: 3
TapHandler {
id: tap1
+ objectName: "tap1"
gesturePolicy: TapHandler.DragThreshold
}
Text {
@@ -113,9 +120,11 @@ Rectangle {
objectName: "dragAndTap"
DragHandler {
id: drag2
+ objectName: "drag2"
}
TapHandler {
id: tap2
+ objectName: "tap2"
gesturePolicy: TapHandler.DragThreshold
}
Text {
@@ -133,10 +142,12 @@ Rectangle {
objectName: "tapAndDrag"
TapHandler {
id: tap3
+ objectName: "tap3"
gesturePolicy: TapHandler.DragThreshold
}
DragHandler {
id: drag3
+ objectName: "drag3"
}
Text {
anchors.centerIn: parent
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
index f3513881cd..6aa2eaa3cb 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
@@ -69,6 +69,7 @@ private slots:
void mouseDragFlickableBehindButton();
void touchDragSlider();
void touchDragFlickableBehindSlider();
+ void mouseDragSlider_data();
void mouseDragSlider();
void mouseDragFlickableBehindSlider();
void touchDragFlickableBehindItemWithHandlers_data();
@@ -293,7 +294,7 @@ void tst_FlickableInterop::touchDragSlider()
createView(windowPtr, "flickableWithHandlers.qml");
QQuickView * window = windowPtr.data();
- QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider");
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
QVERIFY(slider);
QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
QVERIFY(drag);
@@ -339,6 +340,26 @@ void tst_FlickableInterop::touchDragSlider()
QCOMPARE(translationChangedSpy.count(), 1);
}
+void tst_FlickableInterop::mouseDragSlider_data()
+{
+ QTest::addColumn<QString>("nameOfSliderToDrag");
+ QTest::addColumn<QPoint>("pressPositionRelativeToKnob");
+ QTest::addColumn<QPoint>("dragDirection"); // a unit vector
+ QTest::addColumn<bool>("expectedTapHandlerPressed");
+ QTest::addColumn<bool>("expectedDragHandlerActive");
+ QTest::addColumn<bool>("expectedFlickableMoving");
+
+ QTest::newRow("drag down on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(0, 1) << true << true << false;
+ QTest::newRow("drag sideways on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true;
+ QTest::newRow("drag down on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(0, 1) << false << false << true;
+ QTest::newRow("drag sideways on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true;
+
+ QTest::newRow("drag down on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(0, 1) << true << true << false;
+ QTest::newRow("drag sideways on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true;
+ QTest::newRow("drag down on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(0, 1) << false << true << false;
+ QTest::newRow("drag sideways on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true;
+}
+
void tst_FlickableInterop::mouseDragSlider()
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
@@ -346,7 +367,14 @@ void tst_FlickableInterop::mouseDragSlider()
createView(windowPtr, "flickableWithHandlers.qml");
QQuickView * window = windowPtr.data();
- QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider");
+ QFETCH(QString, nameOfSliderToDrag);
+ QFETCH(QPoint, pressPositionRelativeToKnob);
+ QFETCH(QPoint, dragDirection); // a unit vector
+ QFETCH(bool, expectedTapHandlerPressed);
+ QFETCH(bool, expectedDragHandlerActive);
+ QFETCH(bool, expectedFlickableMoving);
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>(nameOfSliderToDrag);
QVERIFY(slider);
QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
QVERIFY(drag);
@@ -357,33 +385,40 @@ void tst_FlickableInterop::mouseDragSlider()
QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
- // Drag the slider in the allowed (vertical) direction
+ // Drag the slider
tappedSpy.clear();
- QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() + pressPositionRelativeToKnob;
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(slider->property("pressed").toBool());
- p1 += QPoint(0, dragThreshold);
+ QTRY_COMPARE(slider->property("pressed").toBool(), expectedTapHandlerPressed);
+ p1 += QPoint(dragThreshold * dragDirection.x(), dragThreshold * dragDirection.y());
QTest::mouseMove(window, p1);
- QVERIFY(slider->property("pressed").toBool());
+ QCOMPARE(drag->active(), false);
+ QCOMPARE(slider->property("pressed").toBool(), expectedTapHandlerPressed);
QCOMPARE(slider->property("value").toInt(), 49);
- p1 += QPoint(0, 1);
+ p1 += dragDirection; // one more pixel
QTest::mouseMove(window, p1);
- p1 += QPoint(0, 10);
+ QCOMPARE(drag->active(), expectedDragHandlerActive);
+ // drag farther, to make sure the knob gets adjusted significantly
+ p1 += QPoint(10 * dragDirection.x(), 10 * dragDirection.y());
QTest::mouseMove(window, p1);
- QVERIFY(slider->property("value").toInt() < 49);
- QVERIFY(!flickable->isMoving());
- QVERIFY(!slider->property("pressed").toBool());
+ if (expectedDragHandlerActive && dragDirection.y() > 0)
+ QVERIFY(slider->property("value").toInt() < 49);
+ // by now, Flickable will have stolen the grab, if it decided that it wanted to during filtering of the last event
+ QCOMPARE(flickable->isMoving(), expectedFlickableMoving);
+ QCOMPARE(slider->property("pressed").toBool(), false);
- // Now that the DragHandler is active, the Flickable will not steal the grab
+ // If the DragHandler is active, the Flickable will not steal the grab
// even if we move a large distance horizontally
- p1 += QPoint(dragThreshold * 2, 0);
- QTest::mouseMove(window, p1);
- QVERIFY(!flickable->isMoving());
+ if (expectedDragHandlerActive) {
+ p1 += QPoint(dragThreshold * 2, 0);
+ QTest::mouseMove(window, p1);
+ QCOMPARE(flickable->isMoving(), false);
+ }
// Release, and do not expect the tapped signal
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(tappedSpy.count(), 0);
- QCOMPARE(translationChangedSpy.count(), 1);
+ QCOMPARE(translationChangedSpy.count(), expectedDragHandlerActive ? 1 : 0);
}
void tst_FlickableInterop::touchDragFlickableBehindSlider()
@@ -393,7 +428,7 @@ void tst_FlickableInterop::touchDragFlickableBehindSlider()
createView(windowPtr, "flickableWithHandlers.qml");
QQuickView * window = windowPtr.data();
- QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider");
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
QVERIFY(slider);
QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
QVERIFY(drag);
@@ -439,7 +474,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindSlider()
createView(windowPtr, "flickableWithHandlers.qml");
QQuickView * window = windowPtr.data();
- QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider");
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
QVERIFY(slider);
QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
QVERIFY(drag);
@@ -568,7 +603,7 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
createView(windowPtr, "flickableWithHandlers.qml");
QQuickView * window = windowPtr.data();
- QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider");
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
QVERIFY(slider);
QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
QVERIFY(drag);
@@ -576,6 +611,7 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
QVERIFY(knob);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
// The knob is initially centered over the slider's "groove"
qreal initialXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).x() - slider->mapToScene
@@ -584,57 +620,36 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
// Drag the slider in the allowed (vertical) direction with one finger
QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ touchSeq.press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
p1 += QPoint(0, dragThreshold);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ touchSeq.move(1, p1, window).commit();
QQuickTouchUtils::flush(window);
p1 += QPoint(0, dragThreshold);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ touchSeq.move(1, p1, window).commit();
QQuickTouchUtils::flush(window);
p1 += QPoint(0, dragThreshold);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ touchSeq.move(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(slider->property("value").toInt() < 49);
QVERIFY(!flickable->isMoving());
// Drag the Flickable with a second finger
QPoint p2(300,300);
- QTest::touchEvent(window, touchDevice).stationary(1).press(2, p2, window);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
+ touchSeq.stationary(1).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
- QQuickTouchUtils::flush(window);
- p1 += QPoint(-10, -10);
- p2 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
- QQuickTouchUtils::flush(window);
- QTRY_VERIFY(flickable->isMoving());
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ touchSeq.move(1, p1, window).stationary(2).commit();
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ touchSeq.stationary(1).move(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ qCDebug(lcPointerTests) << "step" << i << ": fingers @" << p1 << p2 << "is Flickable moving yet?" << flickable->isMoving();
+ }
+ QVERIFY(flickable->isMoving());
qreal knobSliderXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).toPoint().x() -
slider->mapToScene(slider->clipRect().center()).toPoint().x()) - initialXOffset;
if (knobSliderXOffset > 1)
@@ -643,7 +658,7 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
QVERIFY(qAbs(knobSliderXOffset) <= 1);
// Release
- QTest::touchEvent(window, touchDevice).release(1, p1, window).release(2, p2, window);
+ touchSeq.release(1, p1, window).release(2, p2, window).commit();
}
QTEST_MAIN(tst_FlickableInterop)
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
index 4b096f9c3a..0561a9e4f1 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -210,9 +210,9 @@ void tst_MptaInterop::touchesThenPinch()
if (!pinchStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == pinch)
pinchStoleGrab = i;
}
- qCDebug(lcPointerTests) << "pinch started after" << pinchStoleGrab << "moves; ended with scale" << pinch->scale() << "rot" << pinch->rotation();
+ qCDebug(lcPointerTests) << "pinch started after" << pinchStoleGrab << "moves; ended with scale" << pinch->activeScale() << "rot" << pinch->rotation();
QTRY_VERIFY(pinch->rotation() > 4);
- QVERIFY(pinch->scale() > 1);
+ QVERIFY(pinch->activeScale() > 1);
// Press one more point (pinkie finger)
QPoint p4 = mpta->mapToScene(QPointF(300, 200)).toPoint();
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 53bb10b7b8..0271924c9b 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -256,8 +256,9 @@ void tst_DragHandler::touchDragMulti()
QPointF ball2Center = ball2->clipRect().center();
QPointF scenePressPos2 = ball2->mapToScene(ball2Center);
QPoint p2 = scenePressPos2.toPoint();
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
- QTest::touchEvent(window, touchDevice).press(1, p1, window).press(2, p2, window);
+ touchSeq.press(1, p1, window).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(!dragHandler1->active());
QCOMPARE(dragHandler1->point().position(), ball1Center);
@@ -271,12 +272,12 @@ void tst_DragHandler::touchDragMulti()
QCOMPARE(dragHandler2->point().scenePressPosition(), scenePressPos2);
p1 += QPoint(dragThreshold, 0);
p2 += QPoint(0, dragThreshold);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).move(2, p2, window);
+ touchSeq.move(1, p1, window).move(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(!dragHandler1->active());
p1 += QPoint(1, 0);
p2 += QPoint(0, 1);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).move(2, p2, window);
+ touchSeq.move(1, p1, window).move(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(dragHandler1->active());
QVERIFY(dragHandler2->active());
@@ -292,7 +293,7 @@ void tst_DragHandler::touchDragMulti()
QCOMPARE(translationChangedSpy2.count(), 0);
QCOMPARE(dragHandler2->translation().x(), 0.0);
QCOMPARE(dragHandler2->point().sceneGrabPosition(), sceneGrabPos2);
- QTest::touchEvent(window, touchDevice).move(1, p1, window).move(2, p2, window);
+ touchSeq.move(1, p1, window).move(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(dragHandler1->active());
QVERIFY(dragHandler2->active());
@@ -310,14 +311,14 @@ void tst_DragHandler::touchDragMulti()
QCOMPARE(dragHandler2->point().sceneGrabPosition(), sceneGrabPos2);
QCOMPARE(dragHandler2->translation().x(), 0.0);
QCOMPARE(dragHandler2->translation().y(), dragThreshold + 20.0);
- QTest::touchEvent(window, touchDevice).release(1, p1, window).stationary(2);
+ touchSeq.release(1, p1, window).stationary(2).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!dragHandler1->active());
QVERIFY(dragHandler2->active());
QCOMPARE(dragHandler1->point().pressedButtons(), Qt::NoButton);
QCOMPARE(ball1->mapToScene(ball1Center).toPoint(), p1);
QCOMPARE(translationChangedSpy1.count(), 1);
- QTest::touchEvent(window, touchDevice).release(2, p2, window);
+ touchSeq.release(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!dragHandler2->active());
QCOMPARE(ball2->mapToScene(ball2Center).toPoint(), p2);
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index cf18b5eca1..f9970df9f0 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -526,23 +526,24 @@ void tst_TapHandler::buttonsMultiTouch()
QQuickItem *buttonReleaseWithinBounds = window->rootObject()->findChild<QQuickItem*>("ReleaseWithinBounds");
QVERIFY(buttonReleaseWithinBounds);
QSignalSpy releaseWithinBoundsTappedSpy(buttonReleaseWithinBounds, SIGNAL(tapped()));
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
// can press multiple buttons at the same time
QPoint p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ touchSeq.press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
QPoint p2 = buttonWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).stationary(1).press(2, p2, window);
+ touchSeq.stationary(1).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
QPoint p3 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).stationary(1).stationary(2).press(3, p3, window);
+ touchSeq.stationary(1).stationary(2).press(3, p3, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
// can release top button and press again: others stay pressed the whole time
- QTest::touchEvent(window, touchDevice).stationary(2).stationary(3).release(1, p1, window);
+ touchSeq.stationary(2).stationary(3).release(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
QCOMPARE(dragThresholdTappedSpy.count(), 1);
@@ -550,14 +551,14 @@ void tst_TapHandler::buttonsMultiTouch()
QCOMPARE(withinBoundsTappedSpy.count(), 0);
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
- QTest::touchEvent(window, touchDevice).stationary(2).stationary(3).press(1, p1, window);
+ touchSeq.stationary(2).stationary(3).press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
QVERIFY(buttonWithinBounds->property("pressed").toBool());
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
// can release middle button and press again: others stay pressed the whole time
- QTest::touchEvent(window, touchDevice).stationary(1).stationary(3).release(2, p2, window);
+ touchSeq.stationary(1).stationary(3).release(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
QCOMPARE(withinBoundsTappedSpy.count(), 1);
@@ -565,21 +566,21 @@ void tst_TapHandler::buttonsMultiTouch()
QCOMPARE(dragThresholdTappedSpy.count(), 1);
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
- QTest::touchEvent(window, touchDevice).stationary(1).stationary(3).press(2, p2, window);
+ touchSeq.stationary(1).stationary(3).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(buttonDragThreshold->property("pressed").toBool());
QVERIFY(buttonWithinBounds->property("pressed").toBool());
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
// can release bottom button and press again: others stay pressed the whole time
- QTest::touchEvent(window, touchDevice).stationary(1).stationary(2).release(3, p3, window);
+ touchSeq.stationary(1).stationary(2).release(3, p3, window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
QVERIFY(buttonWithinBounds->property("pressed").toBool());
QCOMPARE(withinBoundsTappedSpy.count(), 1);
QVERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
QCOMPARE(dragThresholdTappedSpy.count(), 1);
- QTest::touchEvent(window, touchDevice).stationary(1).stationary(2).press(3, p3, window);
+ touchSeq.stationary(1).stationary(2).press(3, p3, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
QVERIFY(buttonWithinBounds->property("pressed").toBool());
@@ -599,8 +600,8 @@ void tst_TapHandler::componentUserBehavioralOverride()
QQuickTapHandler *userTapHandler = button->findChild<QQuickTapHandler*>("override");
QVERIFY(userTapHandler);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QQuickEventPoint *)));
- QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QQuickEventPoint *)));
+ QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QQuickEventPoint::GrabState, QQuickEventPoint *)));
+ QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QQuickEventPoint::GrabState, QQuickEventPoint *)));
QSignalSpy innerPressedChangedSpy(innerTapHandler, SIGNAL(pressedChanged()));
QSignalSpy userPressedChangedSpy(userTapHandler, SIGNAL(pressedChanged()));
diff --git a/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml b/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
new file mode 100644
index 0000000000..551329a457
--- /dev/null
+++ b/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+AnimatedSprite {
+ loops: AnimatedSprite.Infinite
+ source: "squarefacesprite.png"
+ frameCount: 6
+ frameDuration: 240
+ width: 160
+ height: 160
+}
diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
index d24ebd9878..4ca31fd957 100644
--- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
+++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
@@ -53,6 +53,7 @@ private slots:
void test_largeAnimation();
void test_reparenting();
void test_changeSourceToSmallerImgKeepingBigFrameSize();
+ void test_infiniteLoops();
void test_implicitSize();
};
@@ -79,8 +80,13 @@ void tst_qquickanimatedsprite::test_properties()
QVERIFY(sprite->interpolate());
QCOMPARE(sprite->loops(), 30);
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
sprite->setRunning(false);
QVERIFY(!sprite->running());
+ // The finished() signal shouldn't be emitted when running is manually set to false.
+ QCOMPARE(finishedSpy.count(), 0);
sprite->setInterpolate(false);
QVERIFY(!sprite->interpolate());
}
@@ -100,10 +106,15 @@ void tst_qquickanimatedsprite::test_runningChangedSignal()
QVERIFY(!sprite->running());
QSignalSpy runningChangedSpy(sprite, SIGNAL(runningChanged(bool)));
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
sprite->setRunning(true);
QTRY_COMPARE(runningChangedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
QTRY_VERIFY(!sprite->running());
QTRY_COMPARE(runningChangedSpy.count(), 2);
+ QCOMPARE(finishedSpy.count(), 1);
}
template <typename T>
@@ -357,6 +368,28 @@ void tst_qquickanimatedsprite::test_implicitSize()
QCOMPARE(frameImplicitHeightChangedSpy.count(), 1);
}
+void tst_qquickanimatedsprite::test_infiniteLoops()
+{
+ QQuickView window;
+ window.setSource(testFileUrl("infiniteLoops.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject());
+
+ QQuickAnimatedSprite* sprite = qobject_cast<QQuickAnimatedSprite*>(window.rootObject());
+ QVERIFY(sprite);
+
+ QTRY_VERIFY(sprite->running());
+
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ // The finished() signal shouldn't be emitted for infinite animations.
+ const int previousFrame = sprite->currentFrame();
+ QTRY_VERIFY(sprite->currentFrame() != previousFrame);
+ QCOMPARE(finishedSpy.count(), 0);
+}
+
QTEST_MAIN(tst_qquickanimatedsprite)
#include "tst_qquickanimatedsprite.moc"
diff --git a/tests/auto/quick/qquickanimations/data/finished.qml b/tests/auto/quick/qquickanimations/data/finished.qml
new file mode 100644
index 0000000000..a18b321501
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/finished.qml
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 400
+ height: 400
+
+ property bool finishedUsableInQml: false
+
+ property alias simpleTopLevelAnimation: simpleTopLevelAnimation
+ property real foo: 0
+
+ property alias transitionRect: transitionRect
+ property alias transition: transition
+ property alias animationWithinTransition: animationWithinTransition
+
+ property real bar: 0
+ property alias animationWithinBehavior: animationWithinBehavior
+ property alias behavior: behavior
+
+ NumberAnimation {
+ id: simpleTopLevelAnimation
+ target: root
+ property: "foo"
+ from: 0
+ to: 1
+ duration: 10
+
+ onFinished: finishedUsableInQml = true
+ }
+
+ Rectangle {
+ id: transitionRect
+ color: "green"
+ width: 50
+ height: 50
+ anchors.centerIn: parent
+
+ states: State {
+ name: "go"
+ }
+ transitions: Transition {
+ id: transition
+ to: "go"
+ SequentialAnimation {
+ NumberAnimation {
+ id: animationWithinTransition
+ duration: 10
+ property: "foo"
+ from: 1
+ to: 2
+ }
+ }
+ }
+ }
+
+ Behavior on bar {
+ id: behavior
+ NumberAnimation {
+ id: animationWithinBehavior
+ duration: 10
+ property: "bar"
+ from: 0
+ to: 1
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index de86bb16db..3cfe03a376 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -105,6 +105,7 @@ private slots:
void pathSvgAnimation();
void pathLineUnspecifiedXYBug();
void unsetAnimatorProxyJobWindow();
+ void finished();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -1612,6 +1613,79 @@ void tst_qquickanimations::unsetAnimatorProxyJobWindow()
QCOMPARE(proxy.job().data(), job);
}
+void tst_qquickanimations::finished()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("finished.qml"));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+
+ // Test that finished() is emitted for a simple top-level animation.
+ // (Each test is in its own block so that we can reuse the nice signal names :))
+ {
+ QQuickAbstractAnimation *simpleTopLevelAnimation
+ = root->property("simpleTopLevelAnimation").value<QQuickAbstractAnimation*>();
+ QVERIFY(simpleTopLevelAnimation);
+
+ QSignalSpy stoppedSpy(simpleTopLevelAnimation, SIGNAL(stopped()));
+ QVERIFY(stoppedSpy.isValid());
+
+ QSignalSpy finishedSpy(simpleTopLevelAnimation, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ QVERIFY(simpleTopLevelAnimation->setProperty("running", QVariant(true)));
+ QTRY_COMPARE(stoppedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 1);
+
+ // Test that the signal is properly revisioned and hence accessible from QML.
+ QCOMPARE(root->property("finishedUsableInQml").toBool(), true);
+ }
+
+ // Test that finished() is not emitted for animations within a Transition.
+ {
+ QObject *transition = root->property("transition").value<QObject*>();
+ QVERIFY(transition);
+
+ QSignalSpy runningChangedSpy(transition, SIGNAL(runningChanged()));
+ QVERIFY(runningChangedSpy.isValid());
+
+ QQuickAbstractAnimation *animationWithinTransition
+ = root->property("animationWithinTransition").value<QQuickAbstractAnimation*>();
+ QVERIFY(animationWithinTransition);
+
+ QSignalSpy stoppedSpy(animationWithinTransition, SIGNAL(stopped()));
+ QVERIFY(stoppedSpy.isValid());
+
+ QSignalSpy finishedSpy(animationWithinTransition, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ QObject *transitionRect = root->property("transitionRect").value<QObject*>();
+ QVERIFY(transitionRect);
+ QVERIFY(transitionRect->setProperty("state", QVariant(QLatin1String("go"))));
+ QTRY_COMPARE(runningChangedSpy.count(), 1);
+ QCOMPARE(stoppedSpy.count(), 0);
+ QCOMPARE(finishedSpy.count(), 0);
+ }
+
+ // Test that finished() is not emitted for animations within a Behavior.
+ {
+ QQuickAbstractAnimation *animationWithinBehavior
+ = root->property("animationWithinBehavior").value<QQuickAbstractAnimation*>();
+ QVERIFY(animationWithinBehavior);
+
+ QSignalSpy stoppedSpy(animationWithinBehavior, SIGNAL(stopped()));
+ QVERIFY(stoppedSpy.isValid());
+
+ QSignalSpy finishedSpy(animationWithinBehavior, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ QVERIFY(root->setProperty("bar", QVariant(1.0)));
+ QTRY_COMPARE(root->property("bar").toReal(), 1.0);
+ QCOMPARE(stoppedSpy.count(), 0);
+ QCOMPARE(finishedSpy.count(), 0);
+ }
+}
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
index 750f37638d..dc960a24d0 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
@@ -834,5 +834,96 @@ CanvasTestCase {
ctx.lineCap = 'square';
compare(ctx.lineCap, 'square');
+ }
+
+ function test_lineDash(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+ ctx.reset();
+ ctx.strokeStyle = "#fff";
+ ctx.lineWidth = 2;
+ var pattern = [2, 3, 5, 1, 6, 3]
+ ctx.setLineDash(pattern)
+
+ compare(ctx.getLineDash(), pattern);
+
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(40, 0);
+ ctx.stroke();
+
+ comparePixel(ctx, 0,0, 255,255,255,255);
+ comparePixel(ctx, 1,0, 255,255,255,255);
+ comparePixel(ctx, 2,0, 255,255,255,255);
+ comparePixel(ctx, 3,0, 255,255,255,255);
+ comparePixel(ctx, 4,0, 0,0,0,0);
+ comparePixel(ctx, 5,0, 0,0,0,0);
+ comparePixel(ctx, 6,0, 0,0,0,0);
+ comparePixel(ctx, 7,0, 0,0,0,0);
+ comparePixel(ctx, 8,0, 0,0,0,0);
+ comparePixel(ctx, 9,0, 0,0,0,0);
+ comparePixel(ctx, 10,0, 255,255,255,255);
+ comparePixel(ctx, 11,0, 255,255,255,255);
+ comparePixel(ctx, 12,0, 255,255,255,255);
+ comparePixel(ctx, 13,0, 255,255,255,255);
+ comparePixel(ctx, 14,0, 255,255,255,255);
+ comparePixel(ctx, 15,0, 255,255,255,255);
+ comparePixel(ctx, 16,0, 255,255,255,255);
+ comparePixel(ctx, 17,0, 255,255,255,255);
+ comparePixel(ctx, 18,0, 255,255,255,255);
+ comparePixel(ctx, 19,0, 255,255,255,255);
+ comparePixel(ctx, 20,0, 0,0,0,0);
+ comparePixel(ctx, 21,0, 0,0,0,0);
+ comparePixel(ctx, 22,0, 255,255,255,255);
+ comparePixel(ctx, 23,0, 255,255,255,255);
+ comparePixel(ctx, 24,0, 255,255,255,255);
+ comparePixel(ctx, 25,0, 255,255,255,255);
+ comparePixel(ctx, 26,0, 255,255,255,255);
+ comparePixel(ctx, 27,0, 255,255,255,255);
+ comparePixel(ctx, 28,0, 255,255,255,255);
+ comparePixel(ctx, 29,0, 255,255,255,255);
+ comparePixel(ctx, 30,0, 255,255,255,255);
+ comparePixel(ctx, 31,0, 255,255,255,255);
+ comparePixel(ctx, 32,0, 255,255,255,255);
+ comparePixel(ctx, 33,0, 255,255,255,255);
+ comparePixel(ctx, 34,0, 0,0,0,0);
+ comparePixel(ctx, 35,0, 0,0,0,0);
+ comparePixel(ctx, 36,0, 0,0,0,0);
+ comparePixel(ctx, 37,0, 0,0,0,0);
+ comparePixel(ctx, 38,0, 0,0,0,0);
+ comparePixel(ctx, 39,0, 0,0,0,0);
+ }
+
+ function test_lineDashOffset(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+ ctx.reset();
+ ctx.strokeStyle = "#fff";
+ ctx.lineWidth = 2;
+ var pattern = [2,2]
+ ctx.setLineDash(pattern)
+ ctx.lineDashOffset = 1
+ compare(ctx.getLineDash(), pattern);
+
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(40, 0);
+ ctx.stroke();
+
+
+ comparePixel(ctx, 0,0, 255,255,255,255);
+ comparePixel(ctx, 1,0, 255,255,255,255);
+ comparePixel(ctx, 2,0, 0,0,0,0);
+ comparePixel(ctx, 3,0, 0,0,0,0);
+ comparePixel(ctx, 4,0, 0,0,0,0);
+ comparePixel(ctx, 5,0, 0,0,0,0);
+ comparePixel(ctx, 6,0, 255,255,255,255);
+ comparePixel(ctx, 7,0, 255,255,255,255);
+ comparePixel(ctx, 8,0, 255,255,255,255);
+ comparePixel(ctx, 9,0, 255,255,255,255);
+ comparePixel(ctx, 10,0, 0,0,0,0);
+ comparePixel(ctx, 11,0, 0,0,0,0);
+ comparePixel(ctx, 12,0, 0,0,0,0);
+ comparePixel(ctx, 13,0, 0,0,0,0);
}
}
diff --git a/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml b/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
index 68f456af99..63d65b435c 100644
--- a/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
+++ b/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
@@ -4,6 +4,8 @@ Item {
width: 100
height: 62
- x: Math.max(0, 200)
+ // Add a dummy dependency to parent.x to ensure that the
+ // binding stays for the test.
+ x: parent.x + Math.max(0, 200) - parent.x
}
diff --git a/tests/auto/quick/qquickdesignersupport/data/test.qml b/tests/auto/quick/qquickdesignersupport/data/test.qml
index 1d43cb3b7e..6c89f15257 100644
--- a/tests/auto/quick/qquickdesignersupport/data/test.qml
+++ b/tests/auto/quick/qquickdesignersupport/data/test.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.11
Rectangle {
objectName: "rootItem"
@@ -13,7 +13,7 @@ Rectangle {
Rectangle {
objectName: "rectangleItem"
- gradient: Gradient {
+ containmentMask: Item {
}
}
diff --git a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
index 96a11e16e9..3e0765552a 100644
--- a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
+++ b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
@@ -209,15 +209,15 @@ void tst_qquickdesignersupport::objectProperties()
//Read gradient property as QObject
- int propertyIndex = rectangleItem->metaObject()->indexOfProperty("gradient");
+ int propertyIndex = rectangleItem->metaObject()->indexOfProperty("containmentMask");
QVERIFY(propertyIndex > 0);
QMetaProperty metaProperty = rectangleItem->metaObject()->property(propertyIndex);
QVERIFY(metaProperty.isValid());
QVERIFY(QQuickDesignerSupportProperties::isPropertyQObject(metaProperty));
- QObject*gradient = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
- QVERIFY(gradient);
+ QObject *containmentItem = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
+ QVERIFY(containmentItem);
//The width property is not a QObject
@@ -450,7 +450,7 @@ void tst_qquickdesignersupport::testNotifyPropertyChangeCallBack()
QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(notifyPropertyChangeCallBackPointer);
- rectangle->setProperty("gradient", QVariant::fromValue<QQuickGradient *>(gradient));
+ rectangle->setProperty("gradient", QVariant::fromValue<QJSValue>(view->engine()->newQObject(gradient)));
QVERIFY(s_object);
QCOMPARE(s_object, rootItem);
diff --git a/tests/auto/quick/qquickflickable/BLACKLIST b/tests/auto/quick/qquickflickable/BLACKLIST
index 826c024732..870bb2e1e9 100644
--- a/tests/auto/quick/qquickflickable/BLACKLIST
+++ b/tests/auto/quick/qquickflickable/BLACKLIST
@@ -20,3 +20,4 @@ osx-10.10
osx-10.10
[nestedSliderUsingTouch:keepNeither]
ubuntu-16.04
+ubuntu-18.04
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 248f8447e0..ba266824e6 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -203,6 +203,8 @@ private slots:
void overshoot();
void overshoot_data();
void overshoot_reentrant();
+ void synchronousDrag_data();
+ void synchronousDrag();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
@@ -2458,6 +2460,70 @@ void tst_qquickflickable::overshoot_reentrant()
QCOMPARE(flickable->verticalOvershoot(), 25.0);
}
+void tst_qquickflickable::synchronousDrag_data()
+{
+ QTest::addColumn<bool>("synchronousDrag");
+
+ QTest::newRow("default") << false;
+ QTest::newRow("synch") << true;
+}
+
+void tst_qquickflickable::synchronousDrag()
+{
+ QFETCH(bool, synchronousDrag);
+
+ QScopedPointer<QQuickView> scopedWindow(new QQuickView);
+ QQuickView *window = scopedWindow.data();
+ window->setSource(testFileUrl("longList.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window);
+ QQuickViewTestUtil::moveMouseAway(window);
+ window->show();
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable != nullptr);
+ QCOMPARE(flickable->synchronousDrag(), false);
+ flickable->setSynchronousDrag(synchronousDrag);
+
+ QPoint p1(100, 100);
+ QPoint p2(95, 95);
+ QPoint p3(70, 70);
+ QPoint p4(50, 50);
+ QPoint p5(30, 30);
+ QCOMPARE(flickable->contentY(), 0.0f);
+
+ // Drag via mouse
+ moveAndPress(window, p1);
+ QTest::mouseMove(window, p2);
+ QTest::mouseMove(window, p3);
+ QTest::mouseMove(window, p4);
+ QCOMPARE(flickable->contentY(), synchronousDrag ? 50.0f : 0.0f);
+ QTest::mouseMove(window, p5);
+ if (!synchronousDrag)
+ QVERIFY(flickable->contentY() < 50.0f);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p5);
+
+ // Reset to initial condition
+ flickable->setContentY(0);
+
+ // Drag via touch
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).move(0, p2, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).move(0, p3, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).move(0, p4, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(flickable->contentY(), synchronousDrag ? 50.0f : 0.0f);
+ QTest::touchEvent(window, touchDevice).move(0, p5, window);
+ QQuickTouchUtils::flush(window);
+ if (!synchronousDrag)
+ QVERIFY(flickable->contentY() < 50.0f);
+ QTest::touchEvent(window, touchDevice).release(0, p5, window);
+}
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index 805baebc7a..6aff66d61e 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -193,7 +193,7 @@ void tst_QQuickFramebufferObject::testThatStuffWorks()
view.show();
view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QImage result = view.grabWindow();
@@ -233,7 +233,7 @@ void tst_QQuickFramebufferObject::testInvalidate()
view.show();
view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QCOMPARE(frameInfo.fboSize, QSize(200, 200));
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 915b9b43ea..7deed8c5a8 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -4387,24 +4387,34 @@ void tst_QQuickGridView::snapOneRow_data()
QTest::addColumn<qreal>("snapAlignment");
QTest::addColumn<qreal>("endExtent");
QTest::addColumn<qreal>("startExtent");
+ QTest::addColumn<qreal>("flickSlowdown");
QTest::newRow("vertical, left to right") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 240.0 << 0.0;
+ << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 240.0 << 0.0 << 1.0;
QTest::newRow("horizontal, left to right") << QQuickGridView::FlowTopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 240.0 << 0.0;
+ << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 240.0 << 0.0 << 1.0;
QTest::newRow("horizontal, right to left") << QQuickGridView::FlowTopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 << -240.0;
+ << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 << -240.0 << 1.0;
QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 340.0 << -20.0;
+ << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 340.0 << -20.0 << 1.0;
QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::FlowTopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 340.0 << -20.0;
+ << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 340.0 << -20.0 << 1.0;
QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::FlowTopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 - 100.0 << -220.0;
+ << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 - 100.0 << -220.0 << 1.0;
+
+ // Using e.g. 120 rather than 95 always went to the next row.
+ // Ensure this further movement has the same behavior
+ QTest::newRow("vertical, left to right, no more blindspot") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 160) << QPoint(20, 95) << 100.0 << 240.0 << 0.0 << 4.0;
+
+ // StrictlyEnforceRange should not override valid SnapOneItem decisions
+ QTest::newRow("vertical, left to right, no more blindspot, enforce range") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 160) << QPoint(20, 95) << 100.0 << 340.0 << -20.0 << 4.0;
}
void tst_QQuickGridView::snapOneRow()
@@ -4417,6 +4427,9 @@ void tst_QQuickGridView::snapOneRow()
QFETCH(qreal, snapAlignment);
QFETCH(qreal, endExtent);
QFETCH(qreal, startExtent);
+ QFETCH(qreal, flickSlowdown);
+
+ qreal flickDuration = 180 * flickSlowdown;
QQuickView *window = getView();
QQuickViewTestUtil::moveMouseAway(window);
@@ -4439,7 +4452,7 @@ void tst_QQuickGridView::snapOneRow()
QSignalSpy currentIndexSpy(gridview, SIGNAL(currentIndexChanged()));
// confirm that a flick hits next row boundary
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
if (flow == QQuickGridView::FlowLeftToRight)
QCOMPARE(gridview->contentY(), snapAlignment);
@@ -4453,7 +4466,7 @@ void tst_QQuickGridView::snapOneRow()
// flick to end
do {
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
} while (flow == QQuickGridView::FlowLeftToRight
? !gridview->isAtYEnd()
@@ -4471,7 +4484,7 @@ void tst_QQuickGridView::snapOneRow()
// flick to start
do {
- flick(window, flickEnd, flickStart, 180);
+ flick(window, flickEnd, flickStart, flickDuration);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
} while (flow == QQuickGridView::FlowLeftToRight
? !gridview->isAtYBeginning()
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index d8464ebc74..4b75a7e008 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -65,6 +65,7 @@ private slots:
void threadTest();
void asyncTextureTest();
+ void instantAsyncTextureTest();
private:
QString newImageFileName() const;
@@ -550,6 +551,70 @@ void tst_qquickimageprovider::asyncTextureTest()
}
}
+class InstantAsyncImageResponse : public QQuickImageResponse
+{
+ public:
+ InstantAsyncImageResponse(const QString &id, const QSize &requestedSize)
+ {
+ QImage image(50, 50, QImage::Format_RGB32);
+ image.fill(QColor(id).rgb());
+ if (requestedSize.isValid())
+ image = image.scaled(requestedSize);
+ m_texture = QQuickTextureFactory::textureFactoryForImage(image);
+ emit finished();
+ }
+
+ QQuickTextureFactory *textureFactory() const
+ {
+ return m_texture;
+ }
+
+ QQuickTextureFactory *m_texture;
+};
+
+class InstancAsyncProvider : public QQuickAsyncImageProvider
+{
+ public:
+ InstancAsyncProvider()
+ {
+ }
+
+ ~InstancAsyncProvider() {}
+
+ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize)
+ {
+ return new InstantAsyncImageResponse(id, requestedSize);
+ }
+};
+
+void tst_qquickimageprovider::instantAsyncTextureTest()
+{
+ QQmlEngine engine;
+
+ InstancAsyncProvider *provider = new InstancAsyncProvider;
+
+ engine.addImageProvider("test_instantasync", provider);
+ QVERIFY(engine.imageProvider("test_instantasync") != nullptr);
+
+ QString componentStr = "import QtQuick 2.0\nItem { \n"
+ "Image { source: \"image://test_instantasync/blue\"; }\n"
+ "Image { source: \"image://test_instantasync/red\"; }\n"
+ "Image { source: \"image://test_instantasync/green\"; }\n"
+ "Image { source: \"image://test_instantasync/yellow\"; }\n"
+ " }";
+ QQmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> obj(component.create());
+
+ QVERIFY(!obj.isNull());
+ const QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
+ QCOMPARE(images.count(), 4);
+
+ for (QQuickImage *img: images) {
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ }
+}
+
QTEST_MAIN(tst_qquickimageprovider)
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index c1daddb561..64a186eade 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -118,6 +118,7 @@ private slots:
void noCurrentIndex();
void keyNavigation();
void keyNavigation_data();
+ void checkCountForMultiColumnModels();
void enforceRange();
void enforceRange_withoutHighlight();
void spacing();
@@ -1855,6 +1856,38 @@ void tst_QQuickListView::swapWithFirstItem()
delete testObject;
}
+void tst_QQuickListView::checkCountForMultiColumnModels()
+{
+ // Check that a list view will only load items for the first
+ // column, even if the model reports that it got several columns.
+ // We test this since QQmlDelegateModel has been changed to
+ // also understand multi-column models, but this should not affect ListView.
+ QScopedPointer<QQuickView> window(createView());
+
+ const int rowCount = 10;
+ const int columnCount = 10;
+
+ QaimModel model;
+ model.columns = columnCount;
+ for (int i = 0; i < rowCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
+
+ window->setSource(testFileUrl("listviewtest.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != nullptr);
+
+ QCOMPARE(listview->count(), rowCount);
+}
+
void tst_QQuickListView::enforceRange()
{
QScopedPointer<QQuickView> window(createView());
@@ -5481,38 +5514,50 @@ void tst_QQuickListView::snapOneItem_data()
QTest::addColumn<qreal>("snapAlignment");
QTest::addColumn<qreal>("endExtent");
QTest::addColumn<qreal>("startExtent");
+ QTest::addColumn<qreal>("flickSlowdown");
QTest::newRow("vertical, top to bottom")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 560.0 << 0.0;
+ << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 560.0 << 0.0 << 1.0;
QTest::newRow("vertical, bottom to top")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -560.0 - 240.0 << -240.0;
+ << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -560.0 - 240.0 << -240.0 << 1.0;
QTest::newRow("horizontal, left to right")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
- << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 560.0 << 0.0;
+ << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 560.0 << 0.0 << 1.0;
QTest::newRow("horizontal, right to left")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -560.0 - 240.0 << -240.0;
+ << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -560.0 - 240.0 << -240.0 << 1.0;
QTest::newRow("vertical, top to bottom, enforce range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 580.0 << -20.0;
+ << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 580.0 << -20.0 << 1.0;
QTest::newRow("vertical, bottom to top, enforce range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -580.0 - 240.0 << -220.0;
+ << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -580.0 - 240.0 << -220.0 << 1.0;
QTest::newRow("horizontal, left to right, enforce range")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 580.0 << -20.0;
+ << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 580.0 << -20.0 << 1.0;
QTest::newRow("horizontal, right to left, enforce range")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -580.0 - 240.0 << -220.0;
+ << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -580.0 - 240.0 << -220.0 << 1.0;
+
+ // Using e.g. 120 rather than 95 always went to the next item.
+ // Ensure this further movement has the same behavior
+ QTest::newRow("vertical, top to bottom, no more blindspot")
+ << QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 200) << QPoint(20, 95) << 180.0 << 560.0 << 0.0 << 6.0;
+
+ // StrictlyEnforceRange should not override valid SnapOneItem decisions
+ QTest::newRow("vertical, top to bottom, no more blindspot, enforce range")
+ << QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 200) << QPoint(20, 95) << 180.0 << 580.0 << -20.0 << 6.0;
}
void tst_QQuickListView::snapOneItem()
@@ -5526,6 +5571,9 @@ void tst_QQuickListView::snapOneItem()
QFETCH(qreal, snapAlignment);
QFETCH(qreal, endExtent);
QFETCH(qreal, startExtent);
+ QFETCH(qreal, flickSlowdown);
+
+ qreal flickDuration = 180 * flickSlowdown;
QQuickView *window = getView();
QQuickViewTestUtil::moveMouseAway(window);
@@ -5550,7 +5598,7 @@ void tst_QQuickListView::snapOneItem()
QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
// confirm that a flick hits the next item boundary
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
if (orientation == QQuickListView::Vertical)
QCOMPARE(listview->contentY(), snapAlignment);
@@ -5564,7 +5612,7 @@ void tst_QQuickListView::snapOneItem()
// flick to end
do {
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
} while (orientation == QQuickListView::Vertical
? verticalLayoutDirection == QQuickItemView::TopToBottom ? !listview->isAtYEnd() : !listview->isAtYBeginning()
@@ -5582,7 +5630,7 @@ void tst_QQuickListView::snapOneItem()
// flick to start
do {
- flick(window, flickEnd, flickStart, 180);
+ flick(window, flickEnd, flickStart, flickDuration);
QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
} while (orientation == QQuickListView::Vertical
? verticalLayoutDirection == QQuickItemView::TopToBottom ? !listview->isAtYBeginning() : !listview->isAtYEnd()
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 5c3729a8cd..fbdd87905b 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -739,7 +739,7 @@ void tst_QQuickLoader::initialPropertyValuesError_data()
<< (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": No such file or directory"));
QTest::newRow("invalid source url") << testFileUrl("initialPropertyValues.error.3.qml")
- << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
+ << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Expected token `:'"));
QTest::newRow("invalid initial property values object with invalid property access") << testFileUrl("initialPropertyValues.error.4.qml")
<< (QStringList() << QString(testFileUrl("initialPropertyValues.error.4.qml").toString() + ":7:5: QML Loader: setSource: value is not an object")
@@ -885,7 +885,7 @@ void tst_QQuickLoader::asynchronous_data()
<< (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": No such file or directory"));
QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml")
- << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
+ << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Expected token `:'"));
}
void tst_QQuickLoader::asynchronous()
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
index cab6e2f7bf..cdb3e7733b 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -1,4 +1,6 @@
[nonOverlapping]
ubuntu-16.04
+ubuntu-18.04
[nested]
ubuntu-16.04
+ubuntu-18.04
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index e6c03d052c..7d297d3fa2 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -367,6 +367,10 @@ void tst_QQuickPathView::insertModel_data()
void tst_QQuickPathView::insertModel()
{
+#ifdef Q_OS_MACOS
+ QSKIP("this test currently crashes on MacOS. See QTBUG-68048");
+#endif
+
QFETCH(int, mode);
QFETCH(int, idx);
QFETCH(int, count);
@@ -773,6 +777,10 @@ void tst_QQuickPathView::path()
void tst_QQuickPathView::dataModel()
{
+#ifdef Q_OS_MACOS
+ QSKIP("this test currently crashes on MacOS. See QTBUG-68047");
+#endif
+
QScopedPointer<QQuickView> window(createView());
window->show();
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index 0395b08f10..ec31acf035 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -40,6 +40,8 @@
using namespace QQuickViewTestUtil;
using namespace QQuickVisualTestUtil;
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
class tst_qquickpositioners : public QQmlDataTest
{
Q_OBJECT
@@ -3772,6 +3774,10 @@ void tst_qquickpositioners::test_mirroring()
QList<QString> objectNames;
objectNames << "one" << "two" << "three" << "four" << "five";
+#ifdef Q_OS_MACOS
+ qputenv("QSG_RENDER_LOOP","basic"); // QTBUG-69040
+#endif
+
foreach (const QString qmlFile, qmlFiles) {
QScopedPointer<QQuickView> windowA(createView(testFile(qmlFile)));
QQuickItem *rootA = qobject_cast<QQuickItem*>(windowA->rootObject());
@@ -4007,15 +4013,19 @@ void tst_qquickpositioners::test_attachedproperties_dynamic()
QQuickView *tst_qquickpositioners::createView(const QString &filename, bool wait)
{
QQuickView *window = new QQuickView(nullptr);
- qDebug() << "1";
+ qCDebug(lcTests) << "created window";
window->setSource(QUrl::fromLocalFile(filename));
- qDebug() << "2";
+ qCDebug(lcTests) << "loaded content from" << filename;
window->show();
- qDebug() << "3";
+ qCDebug(lcTests) << "window shown";
+ bool exposed = true;
if (wait)
- QTest::qWaitForWindowExposed(window); //It may not relayout until the next frame, so it needs to be drawn
- qDebug() << "4";
+ exposed = QTest::qWaitForWindowExposed(window); //It may not relayout until the next frame, so it needs to be drawn
+ if (exposed)
+ qCDebug(lcTests) << "window exposed";
+ else
+ qCWarning(lcTests) << "window NOT exposed";
return window;
}
diff --git a/tests/auto/quick/qquickrectangle/data/gradient-preset.qml b/tests/auto/quick/qquickrectangle/data/gradient-preset.qml
new file mode 100644
index 0000000000..b740bdd610
--- /dev/null
+++ b/tests/auto/quick/qquickrectangle/data/gradient-preset.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ Rectangle {
+ objectName: "enum"
+ gradient: Gradient.NightFade
+ }
+ Rectangle {
+ objectName: "string"
+ gradient: "NightFade"
+ }
+ Rectangle {
+ objectName: "invalid"
+ gradient: -1
+ }
+}
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index 2aaad867bf..f6ca999cf5 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -49,6 +49,7 @@ private slots:
void gradient_border();
void gradient_separate();
void gradient_multiple();
+ void gradient_preset();
void antialiasing();
private:
@@ -84,7 +85,7 @@ void tst_qquickrectangle::gradient()
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(component.create());
QVERIFY(rect);
- QQuickGradient *grad = rect->gradient();
+ QQuickGradient *grad = qobject_cast<QQuickGradient *>(rect->gradient().toQObject());
QVERIFY(grad);
QQmlListProperty<QQuickGradientStop> stops = grad->stops();
@@ -103,7 +104,7 @@ void tst_qquickrectangle::gradient()
QMetaObject::invokeMethod(rect, "resetGradient");
- grad = rect->gradient();
+ grad = qobject_cast<QQuickGradient *>(rect->gradient().toQObject());
QVERIFY(!grad);
delete rect;
@@ -174,6 +175,29 @@ void tst_qquickrectangle::gradient_multiple()
QVERIFY(secondIsDirty);
}
+void tst_qquickrectangle::gradient_preset()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("gradient-preset.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QQuickRectangle *enumRect = view.rootObject()->findChild<QQuickRectangle *>("enum");
+ QVERIFY(enumRect);
+ QVERIFY(enumRect->gradient().isNumber());
+ QCOMPARE(enumRect->gradient().toUInt(), QGradient::NightFade);
+
+ QQuickRectangle *stringRect = view.rootObject()->findChild<QQuickRectangle *>("string");
+ QVERIFY(stringRect);
+ QVERIFY(stringRect->gradient().isString());
+ QCOMPARE(stringRect->gradient().toString(), QLatin1String("NightFade"));
+
+ QQuickRectangle *invalidRect = view.rootObject()->findChild<QQuickRectangle *>("invalid");
+ QVERIFY(invalidRect);
+ QVERIFY(invalidRect->gradient().isUndefined());
+}
+
void tst_qquickrectangle::antialiasing()
{
QQmlComponent component(&engine);
diff --git a/tests/auto/quick/qquickrepeater/data/ownership.qml b/tests/auto/quick/qquickrepeater/data/ownership.qml
new file mode 100644
index 0000000000..e13df3ab3a
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/ownership.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.0
+
+Repeater {
+}
diff --git a/tests/auto/quick/qquickrepeater/data/package.qml b/tests/auto/quick/qquickrepeater/data/package.qml
new file mode 100644
index 0000000000..1f9eb0d970
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/package.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.0
+import QtQml.Models 2.2
+import QtQuick.Window 2.0
+
+Window {
+ width: 300
+ height: 300
+ visible: true
+ DelegateModel {
+ id: mdl
+
+ model: 1
+ delegate: Package {
+ Item {
+ id: first
+ Package.name: "first"
+ objectName: "firstItem"
+ }
+ Item{
+ id: second
+ Package.name: "second"
+ objectName: "secondItem"
+ }
+ }
+ }
+
+ Repeater {
+ id: repeater1
+ model: mdl.parts.first
+ }
+ Repeater {
+ id: repeater2
+ model: mdl.parts.second
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 0499e2f9a6..0860956224 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -37,6 +37,7 @@
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmllistmodel_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtGui/qstandarditemmodel.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -76,6 +77,8 @@ private slots:
void stackingOrder();
void objectModel();
void QTBUG54859_asynchronousMove();
+ void package();
+ void ownership();
};
class TestObject : public QObject
@@ -1014,6 +1017,91 @@ void tst_QQuickRepeater::QTBUG54859_asynchronousMove()
QTRY_COMPARE(item->property("finished"), QVariant(true));
}
+void tst_QQuickRepeater::package()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("package.qml"));
+
+ QScopedPointer<QObject>o(component.create()); // don't crash!
+ QVERIFY(o != nullptr);
+
+ {
+ QQuickRepeater *repeater1 = qobject_cast<QQuickRepeater*>(qmlContext(o.data())->contextProperty("repeater1").value<QObject*>());
+ QVERIFY(repeater1);
+ QCOMPARE(repeater1->count(), 1);
+ QCOMPARE(repeater1->itemAt(0)->objectName(), "firstItem");
+ }
+
+ {
+ QQuickRepeater *repeater2 = qobject_cast<QQuickRepeater*>(qmlContext(o.data())->contextProperty("repeater2").value<QObject*>());
+ QVERIFY(repeater2);
+ QCOMPARE(repeater2->count(), 1);
+ QCOMPARE(repeater2->itemAt(0)->objectName(), "secondItem");
+ }
+}
+
+void tst_QQuickRepeater::ownership()
+{
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("ownership.qml"));
+
+ QScopedPointer<QAbstractItemModel> aim(new QStandardItemModel);
+ QPointer<QAbstractItemModel> modelGuard(aim.data());
+ QQmlEngine::setObjectOwnership(aim.data(), QQmlEngine::JavaScriptOwnership);
+ {
+ QJSValue wrapper = engine.newQObject(aim.data());
+ }
+
+ QScopedPointer<QObject> repeater(component.create());
+ QVERIFY(!repeater.isNull());
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(aim.data()));
+
+ repeater->setProperty("model", QVariant::fromValue<QObject*>(aim.data()));
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(aim.data()));
+
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ QVERIFY(modelGuard);
+
+ QScopedPointer<QQmlComponent> delegate(new QQmlComponent(&engine));
+ delegate->setData(QByteArrayLiteral("import QtQuick 2.0\nItem{}"), dataDirectoryUrl().resolved(QUrl("inline.qml")));
+ QPointer<QQmlComponent> delegateGuard(delegate.data());
+ QQmlEngine::setObjectOwnership(delegate.data(), QQmlEngine::JavaScriptOwnership);
+ {
+ QJSValue wrapper = engine.newQObject(delegate.data());
+ }
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(delegate.data()));
+
+ repeater->setProperty("delegate", QVariant::fromValue<QObject*>(delegate.data()));
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(delegate.data()));
+
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ QVERIFY(delegateGuard);
+
+ repeater->setProperty("model", QVariant());
+ repeater->setProperty("delegate", QVariant());
+
+ QVERIFY(delegateGuard);
+ QVERIFY(modelGuard);
+
+ delegate.take();
+ aim.take();
+
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ QVERIFY(!delegateGuard);
+ QVERIFY(!modelGuard);
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquickshape/qquickshape.pro b/tests/auto/quick/qquickshape/qquickshape.pro
index 29c3502b86..a0e5c002e0 100644
--- a/tests/auto/quick/qquickshape/qquickshape.pro
+++ b/tests/auto/quick/qquickshape/qquickshape.pro
@@ -9,27 +9,5 @@ include (../shared/util.pri)
TESTDATA = data/*
-HEADERS += \
- ../../../../src/imports/shapes/qquickshape_p.h \
- ../../../../src/imports/shapes/qquickshape_p_p.h \
- ../../../../src/imports/shapes/qquickshapegenericrenderer_p.h \
- ../../../../src/imports/shapes/qquickshapesoftwarerenderer_p.h
-
-SOURCES += \
- ../../../../src/imports/shapes/qquickshape.cpp \
- ../../../../src/imports/shapes/qquickshapegenericrenderer.cpp \
- ../../../../src/imports/shapes/qquickshapesoftwarerenderer.cpp
-
-qtConfig(opengl) {
- HEADERS += \
- ../../../../src/imports/shapes/qquicknvprfunctions_p.h \
- ../../../../src/imports/shapes/qquicknvprfunctions_p_p.h \
- ../../../../src/imports/shapes/qquickshapenvprrenderer_p.h
-
- SOURCES += \
- ../../../../src/imports/shapes/qquicknvprfunctions.cpp \
- ../../../../src/imports/shapes/qquickshapenvprrenderer.cpp
-}
-
-QT += core-private gui-private qml-private quick-private testlib
+QT += core-private gui-private qml-private quick-private testlib quickshapes-private
qtHaveModule(widgets): QT += widgets
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index 2a349d2013..72f987ce4a 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -33,7 +33,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
-#include "../../../../src/imports/shapes/qquickshape_p.h"
+#include <QtQuickShapes/private/qquickshape_p.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
diff --git a/tests/auto/quick/qquicktableview/data/countingtableview.qml b/tests/auto/quick/qquicktableview/data/countingtableview.qml
new file mode 100644
index 0000000000..d8315be54f
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/countingtableview.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.tableview 1.0
+
+Item {
+ id: root
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property int currentDelegateCount: 0
+ property int maxDelegateCount: 0
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ cacheBuffer: 0
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ TableView.cellWidth: 100
+ TableView.cellHeight: 50
+ color: "lightgray"
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ Component.onCompleted: {
+ currentDelegateCount++;
+ maxDelegateCount = Math.max(maxDelegateCount, currentDelegateCount);
+ }
+ Component.onDestruction: {
+ currentDelegateCount--;
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/plaintableview.qml b/tests/auto/quick/qquicktableview/data/plaintableview.qml
new file mode 100644
index 0000000000..7668f0ca01
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/plaintableview.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.tableview 1.0
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property real delegateWidth: 100
+ property real delegateHeight: 50
+ property Component delegate: tableViewDelegate
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ cacheBuffer: 0
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ TableView.cellWidth: delegateWidth
+ TableView.cellHeight: delegateHeight
+ color: "lightgray"
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml b/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
new file mode 100644
index 0000000000..65e4d0861c
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.tableview 1.0
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ cacheBuffer: 0
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ color: "lightgray"
+ border.width: 1
+ implicitWidth: 90
+ implicitHeight: 60
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/qquicktableview.pro b/tests/auto/quick/qquicktableview/qquicktableview.pro
new file mode 100644
index 0000000000..f4d0265dd3
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/qquicktableview.pro
@@ -0,0 +1,14 @@
+CONFIG += testcase
+TARGET = tst_qquicktableview
+macos:CONFIG -= app_bundle
+
+HEADERS += testmodel.h
+SOURCES += tst_qquicktableview.cpp
+
+include (../../shared/util.pri)
+include (../shared/util.pri)
+
+TESTDATA = data/*
+
+QT += core-private gui-private qml-private quick-private testlib
+
diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h
new file mode 100644
index 0000000000..06384f7a5e
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/testmodel.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtCore>
+#include <QtGui/QStandardItemModel>
+
+class TestModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+ Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged)
+
+public:
+ TestModel(QObject *parent = nullptr)
+ : QAbstractTableModel(parent)
+ {}
+
+ TestModel(int rows, int columns, QObject *parent = nullptr)
+ : QAbstractTableModel(parent)
+ , m_rows(rows)
+ , m_columns(columns)
+ {}
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override { return m_rows; }
+ void setRowCount(int count) { beginResetModel(); m_rows = count; emit rowCountChanged(); endResetModel(); }
+
+ int columnCount(const QModelIndex & = QModelIndex()) const override { return m_columns; }
+ void setColumnCount(int count) { beginResetModel(); m_columns = count; emit columnCountChanged(); endResetModel(); }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+
+ int cell = index.row() + (index.column() * m_columns);
+ if (selectedCells.contains(cell))
+ return QStringLiteral("selected");
+ return QString("%1").arg(index.row());
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return { {Qt::DisplayRole, "display"} };
+ }
+
+ Q_INVOKABLE void selectCell(int row, int column)
+ {
+ int cell = row + (column * m_columns);
+ selectedCells.insert(cell);
+ auto index = createIndex(row, column, nullptr);
+ emit dataChanged(index, index);
+ }
+
+signals:
+ void rowCountChanged();
+ void columnCountChanged();
+
+private:
+ int m_rows = 0;
+ int m_columns = 0;
+ QSet<int> selectedCells;
+};
+
+#define TestModelAsVariant(...) QVariant::fromValue(QSharedPointer<TestModel>(new TestModel(__VA_ARGS__)))
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
new file mode 100644
index 0000000000..8caced4396
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -0,0 +1,791 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquicktableview_p.h>
+#include <QtQuick/private/qquicktableview_p_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlexpression.h>
+#include <QtQml/qqmlincubator.h>
+#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtQml/private/qqmllistmodel_p.h>
+#include <QtQml/private/qqmldelegatemodel_p.h>
+
+#include "testmodel.h"
+
+#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
+#include "../shared/visualtestutil.h"
+
+using namespace QQuickViewTestUtil;
+using namespace QQuickVisualTestUtil;
+
+static const char* kTableViewPropName = "tableView";
+static const char* kDelegateObjectName = "tableViewDelegate";
+
+Q_DECLARE_METATYPE(QMarginsF);
+
+#define LOAD_TABLEVIEW(fileName) \
+ QScopedPointer<QQuickView> view(createView()); \
+ view->setSource(testFileUrl(fileName)); \
+ view->show(); \
+ QVERIFY(QTest::qWaitForWindowActive(view.data())); \
+ auto tableView = view->rootObject()->property(kTableViewPropName).value<QQuickTableView *>(); \
+ QVERIFY(tableView); \
+ auto tableViewPrivate = QQuickTableViewPrivate::get(tableView); \
+ Q_UNUSED(tableViewPrivate)
+
+#define WAIT_UNTIL_POLISHED \
+ QVERIFY(tableViewPrivate->polishScheduled); \
+ QTRY_VERIFY(!tableViewPrivate->polishScheduled)
+
+class tst_QQuickTableView : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_QQuickTableView();
+
+ QQuickTableViewAttached *getAttachedObject(const QObject *object) const;
+ QPoint getContextRowAndColumn(const QQuickItem *item) const;
+
+private slots:
+ void initTestCase() override;
+
+ void setAndGetModel_data();
+ void setAndGetModel();
+ void emptyModel_data();
+ void emptyModel();
+ void checkZeroSizedDelegate();
+ void checkImplicitSizeDelegate();
+ void noDelegate();
+ void countDelegateItems_data();
+ void countDelegateItems();
+ void checkLayoutOfEqualSizedDelegateItems_data();
+ void checkLayoutOfEqualSizedDelegateItems();
+ void checkTableMargins_data();
+ void checkTableMargins();
+ void fillTableViewButNothingMore_data();
+ void fillTableViewButNothingMore();
+ void checkInitialAttachedProperties_data();
+ void checkInitialAttachedProperties();
+ void flick_data();
+ void flick();
+ void flickOvershoot_data();
+ void flickOvershoot();
+ void checkRowColumnCount();
+};
+
+tst_QQuickTableView::tst_QQuickTableView()
+{
+}
+
+void tst_QQuickTableView::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qmlRegisterType<TestModel>("TestModel", 0, 1, "TestModel");
+}
+
+QQuickTableViewAttached *tst_QQuickTableView::getAttachedObject(const QObject *object) const
+{
+ QObject *attachedObject = qmlAttachedPropertiesObject<QQuickTableView>(object);
+ return static_cast<QQuickTableViewAttached *>(attachedObject);
+}
+
+QPoint tst_QQuickTableView::getContextRowAndColumn(const QQuickItem *item) const
+{
+ const auto context = qmlContext(item);
+ const int row = context->contextProperty("row").toInt();
+ const int column = context->contextProperty("column").toInt();
+ return QPoint(column, row);
+}
+
+void tst_QQuickTableView::setAndGetModel_data()
+{
+ QTest::addColumn<QVariant>("model");
+
+ QTest::newRow("QAIM 1x1") << TestModelAsVariant(1, 1);
+ QTest::newRow("Number model 1") << QVariant::fromValue(1);
+ QTest::newRow("QStringList 1") << QVariant::fromValue(QStringList() << "one");
+}
+
+void tst_QQuickTableView::setAndGetModel()
+{
+ // Test that we can set and get different kind of models
+ QFETCH(QVariant, model);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ QCOMPARE(model, tableView->model());
+}
+
+void tst_QQuickTableView::emptyModel_data()
+{
+ QTest::addColumn<QVariant>("model");
+
+ QTest::newRow("QAIM") << TestModelAsVariant(0, 0);
+ QTest::newRow("Number model") << QVariant::fromValue(0);
+ QTest::newRow("QStringList") << QVariant::fromValue(QStringList());
+}
+
+void tst_QQuickTableView::emptyModel()
+{
+ // Check that if we assign an empty model to
+ // TableView, no delegate items will be created.
+ QFETCH(QVariant, model);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableViewPrivate->loadedItems.count(), 0);
+}
+
+void tst_QQuickTableView::checkZeroSizedDelegate()
+{
+ // Check that if we assign a delegate with empty width and height, we
+ // fall back to use kDefaultColumnWidth and kDefaultRowHeight as
+ // column/row sizes.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ view->rootObject()->setProperty("delegateWidth", 0);
+ view->rootObject()->setProperty("delegateHeight", 0);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(!items.isEmpty());
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ auto item = fxItem->item;
+ QCOMPARE(item->width(), kDefaultColumnWidth);
+ QCOMPARE(item->height(), kDefaultRowHeight);
+ }
+}
+
+void tst_QQuickTableView::checkImplicitSizeDelegate()
+{
+ // Check that we can set the size of delegate items using
+ // implicit width/height, instead of forcing the user to
+ // create an attached object by using TableView.cellWidth/Height.
+ LOAD_TABLEVIEW("tableviewimplicitsize.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(!items.isEmpty());
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ auto item = fxItem->item;
+ QCOMPARE(item->width(), 90);
+ QCOMPARE(item->height(), 60);
+ }
+}
+
+void tst_QQuickTableView::noDelegate()
+{
+ // Check that you can skip setting a delegate without
+ // it causing any problems (like crashing or asserting).
+ // And then set a delegate, and do a quick check that the
+ // view gets populated as expected.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rows = 5;
+ const int columns = 5;
+ auto model = TestModelAsVariant(columns, rows);
+ tableView->setModel(model);
+
+ // Start with no delegate, and check
+ // that we end up with no items in the table.
+ tableView->setDelegate(nullptr);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(items.isEmpty());
+
+ // Set a delegate, and check that we end
+ // up with the expected number of items.
+ auto delegate = view->rootObject()->property("delegate").value<QQmlComponent *>();
+ QVERIFY(delegate);
+ tableView->setDelegate(delegate);
+
+ WAIT_UNTIL_POLISHED;
+
+ items = tableViewPrivate->loadedItems;
+ QCOMPARE(items.count(), rows * columns);
+
+ // And then unset the delegate again, and check
+ // that we end up with no items.
+ tableView->setDelegate(nullptr);
+
+ WAIT_UNTIL_POLISHED;
+
+ items = tableViewPrivate->loadedItems;
+ QVERIFY(items.isEmpty());
+}
+
+void tst_QQuickTableView::countDelegateItems_data()
+{
+ QTest::addColumn<QVariant>("model");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("QAIM 1x1") << TestModelAsVariant(1, 1) << 1;
+ QTest::newRow("QAIM 2x1") << TestModelAsVariant(2, 1) << 2;
+ QTest::newRow("QAIM 1x2") << TestModelAsVariant(1, 2) << 2;
+ QTest::newRow("QAIM 2x2") << TestModelAsVariant(2, 2) << 4;
+ QTest::newRow("QAIM 4x4") << TestModelAsVariant(4, 4) << 16;
+
+ QTest::newRow("Number model 1") << QVariant::fromValue(1) << 1;
+ QTest::newRow("Number model 4") << QVariant::fromValue(4) << 4;
+
+ QTest::newRow("QStringList 1") << QVariant::fromValue(QStringList() << "one") << 1;
+ QTest::newRow("QStringList 4") << QVariant::fromValue(QStringList() << "one" << "two" << "three" << "four") << 4;
+}
+
+void tst_QQuickTableView::countDelegateItems()
+{
+ // Assign different models of various sizes, and check that the number of
+ // delegate items in the view matches the size of the model. Note that for
+ // this test to be valid, all items must be within the visible area of the view.
+ QFETCH(QVariant, model);
+ QFETCH(int, count);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+
+ // Check that tableview internals contain the expected number of items
+ auto const items = tableViewPrivate->loadedItems;
+ QCOMPARE(items.count(), count);
+
+ // Check that this also matches the items found in the view
+ auto foundItems = findItems<QQuickItem>(tableView, kDelegateObjectName);
+ QCOMPARE(foundItems.count(), count);
+}
+
+void tst_QQuickTableView::checkLayoutOfEqualSizedDelegateItems_data()
+{
+ QTest::addColumn<QVariant>("model");
+ QTest::addColumn<QSize>("tableSize");
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+
+ // Check spacing together with different table setups
+ QTest::newRow("QAIM 1x1 1,1") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 5x5 0,0") << TestModelAsVariant(5, 5) << QSize(5, 5) << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 5x5 1,0") << TestModelAsVariant(5, 5) << QSize(5, 5) << QSizeF(1, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 5x5 0,1") << TestModelAsVariant(5, 5) << QSize(5, 5) << QSizeF(0, 1) << QMarginsF(0, 0, 0, 0);
+
+ // Check spacing together with margins
+ QTest::newRow("QAIM 1x1 1,1 5555") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(5, 5, 5, 5);
+ QTest::newRow("QAIM 4x4 0,0 3333") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(0, 0) << QMarginsF(3, 3, 3, 3);
+ QTest::newRow("QAIM 4x4 2,2 1234") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(2, 2) << QMarginsF(1, 2, 3, 4);
+
+ // Check "list" models
+ QTest::newRow("NumberModel 1x4, 0000") << QVariant::fromValue(4) << QSize(1, 4) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QStringList 1x4, 0,0 1111") << QVariant::fromValue(QStringList() << "one" << "two" << "three" << "four")
+ << QSize(1, 4) << QSizeF(0, 0) << QMarginsF(1, 1, 1, 1);
+}
+
+void tst_QQuickTableView::checkLayoutOfEqualSizedDelegateItems()
+{
+ // Check that the geometry of the delegate items are correct
+ QFETCH(QVariant, model);
+ QFETCH(QSize, tableSize);
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const qreal expectedItemWidth = 100;
+ const qreal expectedItemHeight = 50;
+ const int expectedItemCount = tableSize.width() * tableSize.height();
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+
+ WAIT_UNTIL_POLISHED;
+
+ auto const items = tableViewPrivate->loadedItems;
+ QVERIFY(!items.isEmpty());
+
+ for (int i = 0; i < expectedItemCount; ++i) {
+ const QQuickItem *item = items[i]->item;
+ QVERIFY(item);
+ QCOMPARE(item->parentItem(), tableView->contentItem());
+
+ const QPoint cell = getContextRowAndColumn(item);
+ qreal expectedX = margins.left() + (cell.x() * (expectedItemWidth + spacing.width()));
+ qreal expectedY = margins.top() + (cell.y() * (expectedItemHeight + spacing.height()));
+ QCOMPARE(item->x(), expectedX);
+ QCOMPARE(item->y(), expectedY);
+ QCOMPARE(item->width(), expectedItemWidth);
+ QCOMPARE(item->height(), expectedItemHeight);
+ }
+}
+
+void tst_QQuickTableView::checkTableMargins_data()
+{
+ QTest::addColumn<QVariant>("model");
+ QTest::addColumn<QSize>("tableSize");
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+
+ QTest::newRow("QAIM 1x1 1,1 0000") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 4x4 1,1 0000") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 1x1 1,1 5555") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(5, 5, 5, 5);
+ QTest::newRow("QAIM 4x4 0,0 3333") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(0, 0) << QMarginsF(3, 3, 3, 3);
+ QTest::newRow("QAIM 4x4 2,2 1234") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(2, 2) << QMarginsF(1, 2, 3, 4);
+ QTest::newRow("QAIM 1x1 0,0 3210") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(0, 0) << QMarginsF(3, 2, 1, 0);
+}
+
+void tst_QQuickTableView::checkTableMargins()
+{
+ // Check that the space between the content view and
+ // the items matches the margins we set on the tableview.
+ QFETCH(QVariant, model);
+ QFETCH(QSize, tableSize);
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.size(), tableSize);
+
+ auto const topLeftFxItem = tableViewPrivate->loadedTableItem(QPoint(0, 0));
+ auto const bottomRightFxItem = tableViewPrivate->loadedTableItem(tableViewPrivate->loadedTable.bottomRight());
+ auto const topLeftItem = topLeftFxItem->item;
+ auto const bottomRightItem = bottomRightFxItem->item;
+
+ qreal leftSpace = topLeftItem->x();
+ qreal topSpace = topLeftItem->y();
+ qreal rightSpace = tableView->contentWidth() - (bottomRightItem->x() + bottomRightItem->width());
+ qreal bottomSpace = tableView->contentHeight() - (bottomRightItem->y() + bottomRightItem->height());
+ QCOMPARE(leftSpace, margins.left());
+ QCOMPARE(topSpace, margins.top());
+ QCOMPARE(rightSpace, margins.right());
+ QCOMPARE(bottomSpace, margins.bottom());
+}
+
+void tst_QQuickTableView::fillTableViewButNothingMore_data()
+{
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+
+ QTest::newRow("0 0,0 0") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("0 10,10 0") << QSizeF(10, 10) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("100 10,10 0") << QSizeF(10, 10) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("0 0,0 100") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("0 10,10 100") << QSizeF(10, 10) << QMarginsF(100, 100, 100, 100);
+ QTest::newRow("100 10,10 100") << QSizeF(10, 10) << QMarginsF(100, 100, 100, 100);
+}
+
+void tst_QQuickTableView::fillTableViewButNothingMore()
+{
+ // Check that we end up filling the whole visible part of
+ // the tableview with cells, but nothing more.
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rows = 100;
+ const int columns = 100;
+ auto model = TestModelAsVariant(rows, columns);
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+ tableView->setCacheBuffer(0);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto const topLeftFxItem = tableViewPrivate->loadedTableItem(QPoint(0, 0));
+ auto const topLeftItem = topLeftFxItem->item;
+
+ // Check that the top-left item are at the corner of the view
+ QCOMPARE(topLeftItem->x(), margins.left());
+ QCOMPARE(topLeftItem->y(), margins.top());
+
+ auto const bottomRightFxItem = tableViewPrivate->loadedTableItem(tableViewPrivate->loadedTable.bottomRight());
+ auto const bottomRightItem = bottomRightFxItem->item;
+ const QPoint bottomRightCell = getContextRowAndColumn(bottomRightItem.data());
+
+ // Check that the right-most item is overlapping the right edge of the view
+ QVERIFY(bottomRightItem->x() < tableView->width());
+ QVERIFY(bottomRightItem->x() + bottomRightItem->width() >= tableView->width() - spacing.width());
+
+ // Check that the actual number of columns matches what we expect
+ qreal cellWidth = bottomRightItem->width() + spacing.width();
+ qreal availableWidth = tableView->width() - margins.left();
+ int expectedColumns = qCeil(availableWidth / cellWidth);
+ int actualColumns = bottomRightCell.x() + 1;
+ QCOMPARE(actualColumns, expectedColumns);
+
+ // Check that the bottom-most item is overlapping the bottom edge of the view
+ QVERIFY(bottomRightItem->y() < tableView->height());
+ QVERIFY(bottomRightItem->y() + bottomRightItem->height() >= tableView->height() - spacing.height());
+
+ // Check that the actual number of rows matches what we expect
+ qreal cellHeight = bottomRightItem->height() + spacing.height();
+ qreal availableHeight = tableView->height() - margins.top();
+ int expectedRows = qCeil(availableHeight / cellHeight);
+ int actualRows = bottomRightCell.y() + 1;
+ QCOMPARE(actualRows, expectedRows);
+}
+
+void tst_QQuickTableView::checkInitialAttachedProperties_data()
+{
+ QTest::addColumn<QVariant>("model");
+
+ QTest::newRow("QAIM") << TestModelAsVariant(4, 4);
+ QTest::newRow("Number model") << QVariant::fromValue(4);
+ QTest::newRow("QStringList") << QVariant::fromValue(QStringList() << "0" << "1" << "2" << "3");
+}
+
+void tst_QQuickTableView::checkInitialAttachedProperties()
+{
+ // Check that the context and attached properties inside
+ // the delegate items are what we expect at start-up.
+ QFETCH(QVariant, model);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ const int index = fxItem->index;
+ const auto item = fxItem->item;
+ const auto context = qmlContext(item.data());
+ const QPoint cell = tableViewPrivate->cellAtModelIndex(index);
+ const int contextIndex = context->contextProperty("index").toInt();
+ const QPoint contextCell = getContextRowAndColumn(item.data());
+ const QString contextModelData = context->contextProperty("modelData").toString();
+ const QQmlDelegateModelAttached *delegateModelAttached =
+ static_cast<QQmlDelegateModelAttached *>(
+ qmlAttachedPropertiesObject<QQmlDelegateModel>(item));
+ const int contextItemsIndex = delegateModelAttached->property("itemsIndex").toInt();
+
+ QCOMPARE(contextCell.y(), cell.y());
+ QCOMPARE(contextCell.x(), cell.x());
+ QCOMPARE(contextIndex, index);
+ QCOMPARE(contextModelData, QStringLiteral("%1").arg(cell.y()));
+ QCOMPARE(contextItemsIndex, index);
+ }
+}
+
+void tst_QQuickTableView::flick_data()
+{
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+
+ QTest::newRow("s:0 m:0") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("s:5 m:0") << QSizeF(5, 5) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("s:0 m:20") << QSizeF(0, 0) << QMarginsF(20, 20, 20, 20);
+ QTest::newRow("s:5 m:20") << QSizeF(5, 5) << QMarginsF(20, 20, 20, 20);
+}
+
+void tst_QQuickTableView::flick()
+{
+ // Check that if we end up with the correct start and end column/row as we flick around
+ // with different table configurations.
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const int visualColumnCount = 4;
+ const int visualRowCount = 4;
+ const qreal cellWidth = delegateWidth + spacing.width();
+ const qreal cellHeight = delegateHeight + spacing.height();
+ auto model = TestModelAsVariant(100, 100);
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+ tableView->setCacheBuffer(0);
+ tableView->setWidth(margins.left() + (visualColumnCount * cellWidth) - spacing.width());
+ tableView->setHeight(margins.top() + (visualRowCount * cellHeight) - spacing.height());
+
+ WAIT_UNTIL_POLISHED;
+
+ // Check the "simple" case if the cells never lands egde-to-edge with the viewport. For
+ // that case we only accept that visible row/columns are loaded.
+ qreal flickValues[] = {0.5, 1.5, 4.5, 20.5, 10.5, 3.5, 1.5, 0.5};
+
+ for (qreal cellsToFlick : flickValues) {
+ // Flick to the beginning of the cell
+ tableView->setContentX(cellsToFlick * cellWidth);
+ tableView->setContentY(cellsToFlick * cellHeight);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const QRect loadedTable = tableViewPrivate->loadedTable;
+
+ const int expectedTableLeft = cellsToFlick - int((margins.left() + spacing.width()) / cellWidth);
+ const int expectedTableTop = cellsToFlick - int((margins.top() + spacing.height()) / cellHeight);
+
+ QCOMPARE(loadedTable.left(), expectedTableLeft);
+ QCOMPARE(loadedTable.right(), expectedTableLeft + visualColumnCount);
+ QCOMPARE(loadedTable.top(), expectedTableTop);
+ QCOMPARE(loadedTable.bottom(), expectedTableTop + visualRowCount);
+ }
+}
+
+void tst_QQuickTableView::flickOvershoot_data()
+{
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+
+ QTest::newRow("s:0 m:0") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("s:5 m:0") << QSizeF(5, 5) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("s:0 m:20") << QSizeF(0, 0) << QMarginsF(20, 20, 20, 20);
+ QTest::newRow("s:5 m:20") << QSizeF(5, 5) << QMarginsF(20, 20, 20, 20);
+}
+
+void tst_QQuickTableView::flickOvershoot()
+{
+ // Flick the table completely out and then in again, and see
+ // that we still contains the expected rows/columns
+ // Note that TableView always keeps top-left item loaded, even
+ // when everything is flicked out of view.
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rowCount = 5;
+ const int columnCount = 5;
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const qreal cellWidth = delegateWidth + spacing.width();
+ const qreal cellHeight = delegateHeight + spacing.height();
+ const qreal tableWidth = margins.left() + margins.right() + (cellWidth * columnCount) - spacing.width();
+ const qreal tableHeight = margins.top() + margins.bottom() + (cellHeight * rowCount) - spacing.height();
+ const int outsideMargin = 10;
+ auto model = TestModelAsVariant(rowCount, columnCount);
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+ tableView->setCacheBuffer(0);
+ tableView->setWidth(tableWidth - margins.right() - cellWidth / 2);
+ tableView->setHeight(tableHeight - margins.bottom() - cellHeight / 2);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick table out of view left
+ tableView->setContentX(-tableView->width() - outsideMargin);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+
+ // Flick table out of view right
+ tableView->setContentX(tableWidth + outsideMargin);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+
+ // Flick table out of view on top
+ tableView->setContentX(0);
+ tableView->setContentY(-tableView->height() - outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), 0);
+
+ // Flick table out of view at the bottom
+ tableView->setContentX(0);
+ tableView->setContentY(tableHeight + outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+
+ // Flick table out of view left and top at the same time
+ tableView->setContentX(-tableView->width() - outsideMargin);
+ tableView->setContentY(-tableView->height() - outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), 0);
+
+ // Flick table back to origo
+ tableView->setContentX(0);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+
+ // Flick table out of view right and bottom at the same time
+ tableView->setContentX(tableWidth + outsideMargin);
+ tableView->setContentY(tableHeight + outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+
+ // Flick table back to origo
+ tableView->setContentX(0);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedTable.left(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.right(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->loadedTable.top(), 0);
+ QCOMPARE(tableViewPrivate->loadedTable.bottom(), rowCount - 1);
+}
+
+void tst_QQuickTableView::checkRowColumnCount()
+{
+ // If we flick several columns (rows) at the same time, check that we don't
+ // end up with loading more delegate items into memory than necessary. We
+ // should free up columns as we go before loading new ones.
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const char *maxDelegateCountProp = "maxDelegateCount";
+ auto model = TestModelAsVariant(100, 100);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const int tableViewCount = tableViewPrivate->loadedItems.count();
+ const int qmlCountAfterInit = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(tableViewCount, qmlCountAfterInit);
+
+ // Flick a long distance right
+ tableView->setContentX(tableView->width() * 2);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const int qmlCountAfterRightFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterRightFlick, qmlCountAfterInit);
+
+ // Flick a long distance down
+ tableView->setContentX(tableView->height() * 2);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const int qmlCountAfterDownFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterDownFlick, qmlCountAfterInit);
+
+ // Flick a long distance left
+ tableView->setContentX(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const int qmlCountAfterLeftFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterLeftFlick, qmlCountAfterInit);
+
+ // Flick a long distance up
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const int qmlCountAfterUpFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterUpFlick, qmlCountAfterInit);
+}
+
+QTEST_MAIN(tst_QQuickTableView)
+
+#include "tst_qquicktableview.moc"
diff --git a/tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml b/tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml
new file mode 100644
index 0000000000..fb8626a75a
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+
+Item
+{
+ id : _rootItem
+ width : 200
+ height : 1000
+ ColumnLayout
+ {
+ id : _textContainer
+ anchors.centerIn: parent
+ Layout.maximumWidth: (_rootItem.width - 40) // to have some space left / right
+ Text
+ {
+ id : text
+ objectName: "text"
+ font.italic: true
+ textFormat: Text.RichText
+ horizontalAlignment : Text.AlignHCenter
+ verticalAlignment : Text.AlignVCenter
+ wrapMode: Text.Wrap
+ Layout.maximumWidth: (_rootItem.width - 60)
+ Component.onCompleted: text.text = "This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 89d2590c03..48069ab8c5 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -105,6 +105,7 @@ private slots:
void implicitSize_data();
void implicitSize();
+ void implicitSizeChangeRewrap();
void dependentImplicitSizes();
void contentSize();
void implicitSizeBinding_data();
@@ -999,11 +1000,14 @@ static inline QByteArray msgNotLessThan(int n1, int n2)
void tst_qquicktext::hAlignImplicitWidth()
{
+#ifdef Q_OS_MACOS
+ QSKIP("this test currently crashes on MacOS. See QTBUG-68047");
+#endif
QQuickView view(testFileUrl("hAlignImplicitWidth.qml"));
view.setFlags(view.flags() | Qt::WindowStaysOnTopHint); // Prevent being obscured by other windows.
view.show();
view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
QVERIFY(text != nullptr);
@@ -4369,6 +4373,23 @@ void tst_qquicktext::fontInfo()
QVERIFY(copy->font().pixelSize() < 1000);
}
+void tst_qquicktext::implicitSizeChangeRewrap()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("implicitSizeChangeRewrap.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *root = window->rootObject();
+
+ QQuickText *text = root->findChild<QQuickText *>("text");
+ QVERIFY(text != nullptr);
+
+ QVERIFY(text->contentWidth() < window->width());
+}
+
QTEST_MAIN(tst_qquicktext)
#include "tst_qquicktext.moc"
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 65c9c9e8ad..ed2d535fda 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -1990,9 +1990,6 @@ void tst_qquicktextinput::validators()
QCOMPARE(intInput->hasAcceptableInput(), false);
QCOMPARE(intInput->property("acceptable").toBool(), false);
QCOMPARE(intSpy.count(), 0);
- QTest::keyPress(&window, Qt::Key_2);
- QTest::keyRelease(&window, Qt::Key_2, Qt::NoModifier);
- QTRY_COMPARE(intInput->text(), QLatin1String("1"));
QCOMPARE(intInput->hasAcceptableInput(), false);
QCOMPARE(intInput->property("acceptable").toBool(), false);
QCOMPARE(intSpy.count(), 0);
@@ -5989,7 +5986,7 @@ void tst_qquicktextinput::QTBUG_19956_regexp()
{
QUrl url = testFileUrl("qtbug-19956regexp.qml");
- QString warning = url.toString() + ":11:17: Unable to assign [undefined] to QRegExp";
+ QString warning = url.toString() + ":11:9: Unable to assign [undefined] to QRegExp";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QQuickView window(url);
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 44cd1dd656..381da76fa3 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -631,9 +631,10 @@ void tst_qquickwindow::touchEvent_basic()
topItem->setSize(QSizeF(150, 150));
QPointF pos(10, 10);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
// press single point
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(),window).commit();
QQuickTouchUtils::flush(window);
QTRY_COMPARE(topItem->lastEvent.touchPoints.count(), 1);
@@ -643,11 +644,11 @@ void tst_qquickwindow::touchEvent_basic()
// would put the decorated window at that position rather than the window itself.
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
topItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, topItem->mapToScene(pos).toPoint(), window).commit();
// press multiple points
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window)
- .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(), window)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
@@ -656,35 +657,35 @@ void tst_qquickwindow::touchEvent_basic()
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
topItem->reset();
bottomItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window).release(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, topItem->mapToScene(pos).toPoint(), window).release(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
// touch point on top item moves to bottom item, but top item should still receive the event
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.move(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
topItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
// touch point on bottom item moves to top item, but bottom item should still receive the event
- QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).move(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.move(0, topItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
bottomItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
// a single stationary press on an item shouldn't cause an event
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).stationary(0)
- .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.stationary(0)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
@@ -696,13 +697,13 @@ void tst_qquickwindow::touchEvent_basic()
// cleanup: what is pressed must be released
// Otherwise you will get an assertion failure:
// ASSERT: "itemForTouchPointId.isEmpty()" in file items/qquickwindow.cpp
- QTest::touchEvent(window, touchDevice).release(0, pos.toPoint(), window).release(1, pos.toPoint(), window);
+ touchSeq.release(0, pos.toPoint(), window).release(1, pos.toPoint(), window).commit();
QQuickTouchUtils::flush(window);
// move touch point from top item to bottom, and release
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(),window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(),window);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(),window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, Qt::TouchPointReleased,
@@ -710,13 +711,13 @@ void tst_qquickwindow::touchEvent_basic()
topItem->reset();
// release while another point is pressed
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
- .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(),window)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.move(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window)
- .stationary(1);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(), window)
+ .stationary(1).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
diff --git a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
index 757cb8f513..bcff0c46fb 100644
--- a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
+++ b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
@@ -354,7 +354,7 @@ void tst_qquickxmllistmodel::xml()
QSignalSpy spy(model, SIGNAL(statusChanged(QQuickXmlListModel::Status)));
QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
+ QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
QQuickXmlListModel::Loading);
QTRY_COMPARE(spy.count(), 1); spy.clear();
@@ -410,6 +410,13 @@ void tst_qquickxmllistmodel::headers()
QTRY_COMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
QQuickXmlListModel::Ready);
+ // It doesn't do a network request for a local file
+ QCOMPARE(factory.lastSentHeaders.count(), 0);
+
+ model->setProperty("source", QUrl("http://localhost/filethatdoesnotexist.xml"));
+ QTRY_COMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
+ QQuickXmlListModel::Error);
+
QVariantMap expectedHeaders;
expectedHeaders["Accept"] = "application/xml,*/*";
@@ -433,7 +440,7 @@ void tst_qquickxmllistmodel::source()
QSignalSpy spy(model, SIGNAL(statusChanged(QQuickXmlListModel::Status)));
QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
+ QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
QQuickXmlListModel::Loading);
QTRY_COMPARE(spy.count(), 1); spy.clear();
@@ -447,7 +454,7 @@ void tst_qquickxmllistmodel::source()
if (model->property("source").toString().isEmpty())
QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
QQuickXmlListModel::Null);
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
+ QCOMPARE(model->property("progress").toDouble(), qreal(source.isLocalFile() ? 1.0 : 0.0));
QTRY_COMPARE(spy.count(), 1); spy.clear();
QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
QQuickXmlListModel::Loading);
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index a54a707f4a..a4b6076a34 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -66,6 +66,7 @@ QUICKTESTS += \
qquickitem2 \
qquickitemlayer \
qquicklistview \
+ qquicktableview \
qquickloader \
qquickmousearea \
qquickmultipointtoucharea \
@@ -93,7 +94,7 @@ QUICKTESTS += \
SUBDIRS += $$PUBLICTESTS
# Following tests are too slow on qemu + software backend
-boot2qt: QUICKTESTS -= qquickgridview qquicklistview qquickpositioners
+boot2qt: QUICKTESTS -= qquickgridview qquicklistview qquicktableview qquickpositioners
!qtConfig(accessibility):QUICKTESTS -= qquickaccessible
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index dc813b9d59..3bfa23173e 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -153,6 +153,12 @@ int QQuickViewTestUtil::QaimModel::rowCount(const QModelIndex &parent) const
return list.count();
}
+int QQuickViewTestUtil::QaimModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return columns;
+}
+
QHash<int,QByteArray> QQuickViewTestUtil::QaimModel::roleNames() const
{
QHash<int,QByteArray> roles = QAbstractListModel::roleNames();
@@ -174,7 +180,7 @@ QVariant QQuickViewTestUtil::QaimModel::data(const QModelIndex &index, int role)
int QQuickViewTestUtil::QaimModel::count() const
{
- return rowCount();
+ return rowCount() * columnCount();
}
QString QQuickViewTestUtil::QaimModel::name(int index) const
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index b11d5e4859..04e1771ef8 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -76,6 +76,7 @@ namespace QQuickViewTestUtil
QaimModel(QObject *parent=0);
int rowCount(const QModelIndex &parent=QModelIndex()) const;
+ int columnCount(const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
QHash<int,QByteArray> roleNames() const;
@@ -104,6 +105,8 @@ namespace QQuickViewTestUtil
using QAbstractListModel::dataChanged;
+ int columns = 1;
+
private:
QList<QPair<QString,QString> > list;
};
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index a69cd5bc34..2fc56c2ad8 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -824,6 +824,7 @@ void tst_TouchMouse::buttonOnTouch()
EventItem *eventItem4 = window->rootObject()->findChild<EventItem*>("eventItem4");
QVERIFY(eventItem4);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window.data(), device, false);
// Test the common case of a mouse area on top of pinch
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
@@ -835,9 +836,9 @@ void tst_TouchMouse::buttonOnTouch()
// Normal touch click
QPoint p1 = QPoint(10, 110);
- QTest::touchEvent(window.data(), device).press(0, p1, window.data());
+ touchSeq.press(0, p1, window.data()).commit();
QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).release(0, p1, window.data());
+ touchSeq.release(0, p1, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(eventItem1->eventList.size(), 5);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
@@ -860,9 +861,9 @@ void tst_TouchMouse::buttonOnTouch()
QPoint p2 = QPoint(60, 10);
// Start the events after each other
- QTest::touchEvent(window.data(), device).press(0, p1, window.data());
+ touchSeq.press(0, p1, window.data()).commit();
QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).stationary(0).press(1, p2, window.data());
+ touchSeq.stationary(0).press(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(button1->scale(), 1.0);
@@ -870,24 +871,24 @@ void tst_TouchMouse::buttonOnTouch()
// This event seems to be discarded, let's ignore it for now until someone digs into pincharea
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QCOMPARE(button1->scale(), 1.5);
qDebug() << "Button scale: " << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QCOMPARE(button1->scale(), 2.0);
qDebug() << "Button scale: " << button1->scale();
- QTest::touchEvent(window.data(), device).release(0, p1, window.data()).release(1, p2, window.data());
+ touchSeq.release(0, p1, window.data()).release(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QVERIFY(eventItem1->eventList.isEmpty());
// QCOMPARE(button1->scale(), 2.0);
@@ -901,7 +902,7 @@ void tst_TouchMouse::buttonOnTouch()
button1->setScale(1.0);
p1 = QPoint(40, 110);
p2 = QPoint(60, 110);
- QTest::touchEvent(window.data(), device).press(0, p1, window.data()).press(1, p2, window.data());
+ touchSeq.press(0, p1, window.data()).press(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(button1->scale(), 1.0);
QCOMPARE(eventItem1->eventList.count(), 2);
@@ -911,24 +912,24 @@ void tst_TouchMouse::buttonOnTouch()
// This event seems to be discarded, let's ignore it for now until someone digs into pincharea
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
//QCOMPARE(button1->scale(), 1.5);
qDebug() << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
qDebug() << button1->scale();
//QCOMPARE(button1->scale(), 2.0);
- QTest::touchEvent(window.data(), device).release(0, p1, window.data()).release(1, p2, window.data());
+ touchSeq.release(0, p1, window.data()).release(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QCOMPARE(eventItem1->eventList.size(), 99);
qDebug() << button1->scale();
@@ -1334,6 +1335,7 @@ void tst_TouchMouse::touchPointDeliveryOrder()
QPoint pLeftMiddle = QPoint(200, 100);
QPoint pRightMiddle = QPoint(350, 100);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window.data(), device, false);
QVector<QQuickItem*> events;
EventItem *background = window->rootObject()->findChild<EventItem*>("background");
@@ -1349,7 +1351,7 @@ void tst_TouchMouse::touchPointDeliveryOrder()
connect(middle, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
connect(right, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
- QTest::touchEvent(window.data(), device).press(0, pLeft, window.data());
+ touchSeq.press(0, pLeft, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// Touch on left, then background
@@ -1359,7 +1361,7 @@ void tst_TouchMouse::touchPointDeliveryOrder()
events.clear();
// New press events are deliverd first, the stationary point was not accepted, thus it doesn't get delivered
- QTest::touchEvent(window.data(), device).stationary(0).press(1, pRightMiddle, window.data());
+ touchSeq.stationary(0).press(1, pRightMiddle, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 3);
QCOMPARE(events.at(0), middle);
@@ -1367,49 +1369,49 @@ void tst_TouchMouse::touchPointDeliveryOrder()
QCOMPARE(events.at(2), background);
events.clear();
- QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRightMiddle, window.data());
+ touchSeq.release(0, pLeft, window.data()).release(1, pRightMiddle, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 0); // no accepted events
// Two presses, the first point should come first
- QTest::touchEvent(window.data(), device).press(0, pLeft, window.data()).press(1, pRight, window.data());
+ touchSeq.press(0, pLeft, window.data()).press(1, pRight, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 3);
QCOMPARE(events.at(0), left);
QCOMPARE(events.at(1), right);
QCOMPARE(events.at(2), background);
- QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRight, window.data());
+ touchSeq.release(0, pLeft, window.data()).release(1, pRight, window.data()).commit();
events.clear();
// Again, pressing right first
- QTest::touchEvent(window.data(), device).press(0, pRight, window.data()).press(1, pLeft, window.data());
+ touchSeq.press(0, pRight, window.data()).press(1, pLeft, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 3);
QCOMPARE(events.at(0), right);
QCOMPARE(events.at(1), left);
QCOMPARE(events.at(2), background);
- QTest::touchEvent(window.data(), device).release(0, pRight, window.data()).release(1, pLeft, window.data());
+ touchSeq.release(0, pRight, window.data()).release(1, pLeft, window.data()).commit();
events.clear();
// Two presses, both hitting the middle item on top, then branching left and right, then bottom
// Each target should be offered the events exactly once, middle first, left must come before right (id 0)
- QTest::touchEvent(window.data(), device).press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data());
+ touchSeq.press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data()).commit();
QCOMPARE(events.size(), 4);
QCOMPARE(events.at(0), middle);
QCOMPARE(events.at(1), left);
QCOMPARE(events.at(2), right);
QCOMPARE(events.at(3), background);
- QTest::touchEvent(window.data(), device).release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data());
+ touchSeq.release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data()).commit();
events.clear();
- QTest::touchEvent(window.data(), device).press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data());
+ touchSeq.press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data()).commit();
qDebug() << events;
QCOMPARE(events.size(), 4);
QCOMPARE(events.at(0), middle);
QCOMPARE(events.at(1), right);
QCOMPARE(events.at(2), left);
QCOMPARE(events.at(3), background);
- QTest::touchEvent(window.data(), device).release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data());
+ touchSeq.release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data()).commit();
}
void tst_TouchMouse::hoverEnabled()
diff --git a/tests/auto/quicktest/quicktest.pro b/tests/auto/quicktest/quicktest.pro
index 9d909f1d16..0e3f257e33 100644
--- a/tests/auto/quicktest/quicktest.pro
+++ b/tests/auto/quicktest/quicktest.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
SUBDIRS = \
signalspy \
- quicktestmainwithsetup
+ quicktestmainwithsetup \
+ testfiltering
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp b/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp
new file mode 100644
index 0000000000..656911f842
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.cpp
@@ -0,0 +1,29 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtQuickTest/quicktest.h>
+QUICK_TEST_MAIN(quicktestmain)
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.pro b/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.pro
new file mode 100644
index 0000000000..7b3e734cb4
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/quicktestmain.pro
@@ -0,0 +1,11 @@
+CONFIG += qmltestcase
+macos:CONFIG -= app_bundle
+TARGET = quicktestmain
+
+DEFINES += QT_QMLTEST_DATADIR=\\\"$${PWD}\\\"
+
+SOURCES += quicktestmain.cpp
+
+TESTDATA += $$PWD/*.qml
+
+DESTDIR = ./
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml b/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml
new file mode 100644
index 0000000000..55c9612b78
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/tst_first.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.3
+import QtTest 1.1
+
+TestCase {
+ name: "First"
+
+ function test_foo() { }
+ function test_bar() { }
+ function test_baz() { }
+}
diff --git a/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml b/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml
new file mode 100644
index 0000000000..2143d93e12
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/quicktestmain/tst_second.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.3
+import QtTest 1.1
+
+TestCase {
+ name: "Second"
+
+ function test_dupfoo() { }
+ function test_dupbar() { }
+ function test_dupbaz() { }
+}
diff --git a/tests/auto/quicktest/testfiltering/test/test.pro b/tests/auto/quicktest/testfiltering/test/test.pro
new file mode 100644
index 0000000000..cecbdca725
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/test/test.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib
+TARGET = ../tst_testfiltering
+
+SOURCES = ../tst_testfiltering.cpp
diff --git a/tests/auto/quicktest/testfiltering/testfiltering.pro b/tests/auto/quicktest/testfiltering/testfiltering.pro
new file mode 100644
index 0000000000..ae7a039b8b
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/testfiltering.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ test \
+ quicktestmain
diff --git a/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp b/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
new file mode 100644
index 0000000000..72bb8f02b7
--- /dev/null
+++ b/tests/auto/quicktest/testfiltering/tst_testfiltering.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QProcess>
+#include <QtTest>
+
+class tst_TestFiltering : public QObject
+{
+ Q_OBJECT
+private slots:
+ void noFilters();
+ void oneMatchingFilter();
+ void filterThatDoesntMatch();
+ void twoFilters();
+ void twoFiltersWithOneMatch();
+ void manyFilters();
+};
+
+
+const QString testExe =
+#if defined(Q_OS_WIN)
+ QFINDTESTDATA("quicktestmain/quicktestmain.exe");
+#else
+ QFINDTESTDATA("quicktestmain/quicktestmain");
+#endif
+
+void tst_TestFiltering::noFilters()
+{
+ QProcess process;
+ process.start(testExe);
+
+ QVERIFY(process.waitForFinished());
+
+ const QString output = process.readAll();
+ QVERIFY(output.contains(QLatin1String("Totals: 10 passed")));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+void tst_TestFiltering::oneMatchingFilter()
+{
+ QProcess process;
+ process.start(testExe, {QLatin1String("First::test_bar")});
+
+ QVERIFY(process.waitForFinished());
+
+ const QString output = process.readAll();
+ QVERIFY(output.contains(QLatin1String("Totals: 3 passed")));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+void tst_TestFiltering::filterThatDoesntMatch()
+{
+ QProcess process;
+ process.start(testExe, {QLatin1String("First::test_nonexisting")});
+
+ QVERIFY(process.waitForFinished());
+
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 1);
+}
+
+void tst_TestFiltering::twoFilters()
+{
+ QProcess process;
+ process.start(testExe,
+ {QLatin1String("Second::test_dupfoo"), QLatin1String("Second::test_dupbaz")});
+
+ QVERIFY(process.waitForFinished());
+
+ const QString output = process.readAll();
+ QVERIFY(output.contains(QLatin1String("Totals: 4 passed")));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+void tst_TestFiltering::twoFiltersWithOneMatch()
+{
+ QProcess process;
+ process.start(testExe,
+ {QLatin1String("First::test_foo"), QLatin1String("Second::test_nonexisting")});
+
+ QVERIFY(process.waitForFinished());
+
+ const QString output = process.readAll();
+ QVERIFY(output.contains(QLatin1String("Totals: 3 passed")));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 1);
+}
+
+void tst_TestFiltering::manyFilters()
+{
+ QProcess process;
+ process.start(testExe,
+ {QLatin1String("First::test_foo"),
+ QLatin1String("First::test_baz"),
+ QLatin1String("Second::test_dupfoo"),
+ QLatin1String("Second::test_dupbaz")});
+
+ QVERIFY(process.waitForFinished());
+
+ const QString output = process.readAll();
+ QVERIFY(output.contains(QLatin1String("Totals: 8 passed")));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+}
+
+QTEST_MAIN(tst_TestFiltering);
+
+#include "tst_testfiltering.moc"
diff --git a/tests/manual/pointer/content/MultiButton.qml b/tests/manual/pointer/content/MultiButton.qml
index 2a41967a36..ca9b16a957 100644
--- a/tests/manual/pointer/content/MultiButton.qml
+++ b/tests/manual/pointer/content/MultiButton.qml
@@ -35,6 +35,7 @@ Rectangle {
property alias pressed: tap.pressed
property bool checked: false
property alias gesturePolicy: tap.gesturePolicy
+ property alias margin: tap.margin
signal tapped
width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0
diff --git a/tests/manual/pointer/map.qml b/tests/manual/pointer/map.qml
index 6ab6badfd0..880f184adb 100644
--- a/tests/manual/pointer/map.qml
+++ b/tests/manual/pointer/map.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the manual tests of the Qt Toolkit.
@@ -48,6 +48,12 @@ Item {
source: "resources/map.svgz"
Component.onCompleted: { width = implicitWidth; height = implicitHeight }
}
+
+ Text {
+ anchors.centerIn: parent
+ text: image.sourceSize.width + " x " + image.sourceSize.height +
+ " scale " + map.scale.toFixed(2) + " active scale " + pinch.activeScale.toFixed(2)
+ }
}
PinchHandler {
diff --git a/tests/manual/pointer/multibuttons.qml b/tests/manual/pointer/multibuttons.qml
index cd7c5d0b19..28c3cc0f50 100644
--- a/tests/manual/pointer/multibuttons.qml
+++ b/tests/manual/pointer/multibuttons.qml
@@ -44,6 +44,7 @@ Item {
label: "Launch Balloons"
Layout.fillWidth: true
gesturePolicy: TapHandler.WithinBounds
+ margin: 10
}
Text { text: "the goons"; font.pointSize: 12 }
MultiButton {
@@ -51,6 +52,7 @@ Item {
label: "Launch Missile"
Layout.fillWidth: true
gesturePolicy: TapHandler.ReleaseWithinBounds
+ margin: 10
onTapped: missileEmitter.burst(1)
}
MultiButton {
@@ -58,6 +60,7 @@ Item {
label: "Launch Fighters"
Layout.fillWidth: true
gesturePolicy: TapHandler.DragThreshold
+ margin: 10
}
}
ParticleSystem {
diff --git a/tests/manual/pointer/pinchDragFlingMPTA.qml b/tests/manual/pointer/pinchDragFlingMPTA.qml
index 2578d62466..0362832662 100644
--- a/tests/manual/pointer/pinchDragFlingMPTA.qml
+++ b/tests/manual/pointer/pinchDragFlingMPTA.qml
@@ -66,7 +66,7 @@ Rectangle {
minimumPointCount: 3
minimumScale: 0.1
maximumScale: 10
- onActiveChanged: if (!active) fling.restart(centroidVelocity)
+ onActiveChanged: if (!active) fling.restart(centroid.velocity)
}
DragHandler {
id: dragHandler
diff --git a/tests/manual/pointer/pinchHandler.qml b/tests/manual/pointer/pinchHandler.qml
index 409b852b55..36af1f53bd 100644
--- a/tests/manual/pointer/pinchHandler.qml
+++ b/tests/manual/pointer/pinchHandler.qml
@@ -153,7 +153,7 @@ Rectangle {
maximumScale: 10
onActiveChanged: {
if (!active)
- anim.restart(centroidVelocity)
+ anim.restart(centroid.velocity)
}
}
TapHandler { gesturePolicy: TapHandler.DragThreshold; onTapped: rect3.z = rect2.z + 1 }
@@ -164,8 +164,8 @@ Rectangle {
Rectangle {
id: centroidIndicator
property QtObject pincher: activePincher()
- x: pincher.centroid.x - radius
- y: pincher.centroid.y - radius
+ x: pincher.centroid.scenePosition.x - radius
+ y: pincher.centroid.scenePosition.y - radius
z: 1
visible: pincher.active
radius: width / 2
diff --git a/tests/manual/pointer/sidebar.qml b/tests/manual/pointer/sidebar.qml
new file mode 100644
index 0000000000..ce2c770592
--- /dev/null
+++ b/tests/manual/pointer/sidebar.qml
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import Qt.labs.handlers 1.0
+import "content"
+
+Rectangle {
+ id: root
+ width: 640
+ height: 480
+ color: "#444"
+
+ Component {
+ id: buttonsAndStuff
+ Column {
+ anchors.fill: parent
+ anchors.margins: 8
+ spacing: 8
+
+ Rectangle {
+ objectName: "buttonWithMA"
+ width: parent.width
+ height: 30
+ color: buttonMA.pressed ? "lightsteelblue" : "#999"
+ border.color: buttonMA.containsMouse ? "cyan" : "transparent"
+
+ MouseArea {
+ id: buttonMA
+ objectName: "buttonMA"
+ hoverEnabled: true
+ anchors.fill: parent
+ onClicked: console.log("clicked MA")
+ }
+
+ Text {
+ anchors.centerIn: parent
+ text: "MouseArea"
+ }
+ }
+
+ Rectangle {
+ objectName: "buttonWithHH"
+ width: parent.width
+ height: 30
+ color: flash ? "#999" : "white"
+ border.color: buttonHH.hovered ? "cyan" : "transparent"
+ property bool flash: true
+
+ HoverHandler {
+ id: buttonHH
+ objectName: "buttonHH"
+ acceptedDevices: PointerDevice.AllDevices
+ }
+
+ TapHandler {
+ onTapped: tapFlash.start()
+ }
+
+ Text {
+ anchors.centerIn: parent
+ text: "HoverHandler"
+ }
+
+ FlashAnimation on flash {
+ id: tapFlash
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: paddle
+ width: 100
+ height: 40
+ color: paddleHH.hovered ? "indianred" : "#888"
+ y: parent.height - 100
+ radius: 10
+
+ HoverHandler {
+ id: paddleHH
+ objectName: "paddleHH"
+ }
+
+ SequentialAnimation on x {
+ NumberAnimation {
+ to: root.width - paddle.width
+ duration: 2000
+ easing { type: Easing.InOutQuad }
+ }
+ PauseAnimation { duration: 100 }
+ NumberAnimation {
+ to: 0
+ duration: 2000
+ easing { type: Easing.InOutQuad }
+ }
+ PauseAnimation { duration: 100 }
+ loops: Animation.Infinite
+ }
+ }
+
+ Rectangle {
+ objectName: "topSidebar"
+ radius: 5
+ antialiasing: true
+ x: -radius
+ y: -radius
+ width: 120
+ height: 200
+ border.color: topSidebarHH.hovered ? "cyan" : "black"
+ color: "#777"
+
+ Rectangle {
+ color: "cyan"
+ width: 10
+ height: width
+ radius: width / 2
+ visible: topSidebarHH.hovered
+ x: topSidebarHH.point.position.x - width / 2
+ y: topSidebarHH.point.position.y - height / 2
+ z: 100
+ }
+
+ HoverHandler {
+ id: topSidebarHH
+ objectName: "topSidebarHH"
+ }
+
+ Loader {
+ objectName: "topSidebarLoader"
+ sourceComponent: buttonsAndStuff
+ anchors.fill: parent
+ }
+ }
+
+ Rectangle {
+ objectName: "bottomSidebar"
+ radius: 5
+ antialiasing: true
+ x: -radius
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: -radius
+ width: 120
+ height: 200
+ border.color: bottomSidebarMA.containsMouse ? "cyan" : "black"
+ color: "#777"
+
+ MouseArea {
+ id: bottomSidebarMA
+ objectName: "bottomSidebarMA"
+ hoverEnabled: true
+ anchors.fill: parent
+ }
+
+ Loader {
+ objectName: "bottomSidebarLoader"
+ sourceComponent: buttonsAndStuff
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/tests/manual/pointer/singlePointHandlerProperties.qml b/tests/manual/pointer/singlePointHandlerProperties.qml
index c11042cf14..1c044f8167 100644
--- a/tests/manual/pointer/singlePointHandlerProperties.qml
+++ b/tests/manual/pointer/singlePointHandlerProperties.qml
@@ -63,7 +63,7 @@ Rectangle {
anchors.centerIn: parent
antialiasing: true
Rectangle {
- y: -40
+ y: -56
anchors.horizontalCenter: parent.horizontalCenter
color: "lightsteelblue"
implicitWidth: label.implicitWidth
@@ -71,7 +71,8 @@ Rectangle {
Text {
id: label
text: 'id: ' + dragHandler.point.id.toString(16) + " uid: " + dragHandler.point.uniqueId.numericId +
- '\npos: (' + dragHandler.point.position.x.toFixed(2) + ', ' + dragHandler.point.position.y.toFixed(2) + ')'
+ '\npos: (' + dragHandler.point.position.x.toFixed(2) + ', ' + dragHandler.point.position.y.toFixed(2) + ')' +
+ '\nmodifiers: ' + dragHandler.point.modifiers.toString(16)
}
}
}
diff --git a/tests/manual/tableview/abstracttablemodel/abstracttablemodel.pro b/tests/manual/tableview/abstracttablemodel/abstracttablemodel.pro
new file mode 100644
index 0000000000..ade49c33a2
--- /dev/null
+++ b/tests/manual/tableview/abstracttablemodel/abstracttablemodel.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET = tableview_abstracttablemodel
+QT += qml quick
+SOURCES += main.cpp
+RESOURCES += main.qml
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/tests/manual/tableview/abstracttablemodel/main.cpp b/tests/manual/tableview/abstracttablemodel/main.cpp
new file mode 100644
index 0000000000..22dda5ca4a
--- /dev/null
+++ b/tests/manual/tableview/abstracttablemodel/main.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QAbstractTableModel>
+
+class TestTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+ Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged)
+
+public:
+ TestTableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) { }
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override { return m_rows; }
+ void setRowCount(int count) { beginResetModel(); m_rows = count; emit rowCountChanged(); endResetModel(); }
+
+ int columnCount(const QModelIndex & = QModelIndex()) const override { return m_cols; }
+ void setColumnCount(int count) { beginResetModel(); m_cols = count; emit columnCountChanged(); endResetModel(); }
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const
+ {
+ Q_UNUSED(orientation);
+ Q_UNUSED(role);
+ return QStringLiteral("Column header");
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+ return QString("[%1-%2]").arg(index.column()).arg(index.row());
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return { {Qt::DisplayRole, "display"} };
+ }
+
+signals:
+ void rowCountChanged();
+ void columnCountChanged();
+
+private:
+ int m_rows = 0;
+ int m_cols = 0;
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<TestTableModel>("TestTableModel", 0, 1, "TestTableModel");
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tests/manual/tableview/abstracttablemodel/main.qml b/tests/manual/tableview/abstracttablemodel/main.qml
new file mode 100644
index 0000000000..271752aaf1
--- /dev/null
+++ b/tests/manual/tableview/abstracttablemodel/main.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import QtQml.Models 2.2
+import Qt.labs.tableview 1.0
+import TestTableModel 0.1
+
+Window {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+
+ TestTableModel {
+ id: tableModel
+ rowCount: 200
+ columnCount: 200
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 10
+ color: "darkgray"
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ anchors.margins: 1
+ clip: true
+
+ model: tableModel
+ delegate: tableViewDelegate
+ cacheBuffer: 500
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ TableView.cellWidth: column % 3 ? 80 : 50
+ TableView.cellHeight: row % 3 ? 80 : 50
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/tests/manual/tableview/listmodel/listmodel.pro b/tests/manual/tableview/listmodel/listmodel.pro
new file mode 100644
index 0000000000..dbae0db2b1
--- /dev/null
+++ b/tests/manual/tableview/listmodel/listmodel.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET = tableview_listmodel
+QT += qml quick
+SOURCES += main.cpp
+RESOURCES += main.qml
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/tests/manual/tableview/listmodel/main.cpp b/tests/manual/tableview/listmodel/main.cpp
new file mode 100644
index 0000000000..2a3b90d392
--- /dev/null
+++ b/tests/manual/tableview/listmodel/main.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
diff --git a/tests/manual/tableview/listmodel/main.qml b/tests/manual/tableview/listmodel/main.qml
new file mode 100644
index 0000000000..ca39e6a2b9
--- /dev/null
+++ b/tests/manual/tableview/listmodel/main.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.tableview 1.0
+import QtQml.Models 2.2
+
+Window {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+
+ ListModel {
+ id: listModel
+ Component.onCompleted: {
+ for (var i = 0; i < 30; ++i)
+ listModel.append({"name" : i})
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 10
+ color: "darkgray"
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ anchors.margins: 1
+ clip: true
+ columnSpacing: 1
+ rowSpacing: 1
+ model: listModel
+ delegate: Component {
+ Rectangle {
+ id: tableDelegate
+ TableView.cellWidth: 100
+ TableView.cellHeight: 50
+
+ Text {
+ anchors.centerIn: parent
+ text: name + "\n[" + column + ", " + row + "]"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/tableview/storagemodel/main.cpp b/tests/manual/tableview/storagemodel/main.cpp
new file mode 100644
index 0000000000..97ae619ce4
--- /dev/null
+++ b/tests/manual/tableview/storagemodel/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include "storagemodel.h"
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<StorageModel>("StorageModel", 0, 1, "StorageModel");
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
+
diff --git a/tests/manual/tableview/storagemodel/main.qml b/tests/manual/tableview/storagemodel/main.qml
new file mode 100644
index 0000000000..f76da374e3
--- /dev/null
+++ b/tests/manual/tableview/storagemodel/main.qml
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.tableview 1.0
+import StorageModel 0.1
+
+Window {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+ color: "darkgray"
+ title: "Storage Volumes"
+
+ TableView {
+ id: table
+ anchors.fill: parent
+ anchors.margins: 10
+ clip: true
+ model: StorageModel { }
+ columnSpacing: 1
+ rowSpacing: 1
+ delegate: Rectangle {
+ id: tableDelegate
+ TableView.cellWidth: displayText.implicitWidth + 8
+ TableView.cellHeight: displayText.implicitHeight + 14
+
+ Text {
+ id: displayText
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ text: display
+ }
+ }
+ }
+}
diff --git a/tests/manual/tableview/storagemodel/storagemodel.cpp b/tests/manual/tableview/storagemodel/storagemodel.cpp
new file mode 100644
index 0000000000..345d1cc63f
--- /dev/null
+++ b/tests/manual/tableview/storagemodel/storagemodel.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ivan Komissarov
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "storagemodel.h"
+
+#include <QDir>
+#include <QLocale>
+#include <qmath.h>
+#include <algorithm>
+#include <cmath>
+
+StorageModel::StorageModel(QObject *parent) :
+ QAbstractTableModel(parent)
+{
+ refresh();
+}
+
+void StorageModel::refresh()
+{
+ beginResetModel();
+ m_volumes = QStorageInfo::mountedVolumes();
+ std::sort(m_volumes.begin(), m_volumes.end(),
+ [](const QStorageInfo &st1, const QStorageInfo &st2) {
+ static const QString rootSortString = QStringLiteral(" ");
+ return (st1.isRoot() ? rootSortString : st1.rootPath())
+ < (st2.isRoot() ? rootSortString : st2.rootPath());
+ });
+ endResetModel();
+}
+
+int StorageModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ return ColumnCount;
+}
+
+int StorageModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_volumes.count();
+}
+
+Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags result = QAbstractTableModel::flags(index);
+ switch (index.column()) {
+ case ColumnAvailable:
+ case ColumnIsReady:
+ case ColumnIsReadOnly:
+ case ColumnIsValid:
+ result |= Qt::ItemIsUserCheckable;
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
+QVariant StorageModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole) {
+ const QStorageInfo &volume = m_volumes.at(index.row());
+ switch (index.column()) {
+ case ColumnRootPath:
+ return QDir::toNativeSeparators(volume.rootPath());
+ case ColumnName:
+ return volume.name();
+ case ColumnDevice:
+ return volume.device();
+ case ColumnFileSystemName:
+ return volume.fileSystemType();
+ case ColumnTotal:
+ return QLocale().formattedDataSize(volume.bytesTotal());
+ case ColumnFree:
+ return QLocale().formattedDataSize(volume.bytesFree());
+ case ColumnAvailable:
+ return QLocale().formattedDataSize(volume.bytesAvailable());
+ case ColumnIsReady:
+ return volume.isReady();
+ case ColumnIsReadOnly:
+ return volume.isReadOnly();
+ case ColumnIsValid:
+ return volume.isValid();
+ default:
+ break;
+ }
+ } else if (role == Qt::CheckStateRole) {
+ const QStorageInfo &volume = m_volumes.at(index.row());
+ switch (index.column()) {
+ case ColumnIsReady:
+ return volume.isReady();
+ case ColumnIsReadOnly:
+ return volume.isReadOnly();
+ case ColumnIsValid:
+ return volume.isValid();
+ default:
+ break;
+ }
+ } else if (role == Qt::TextAlignmentRole) {
+ switch (index.column()) {
+ case ColumnTotal:
+ case ColumnFree:
+ case ColumnAvailable:
+ return Qt::AlignTrailing;
+ default:
+ break;
+ }
+ return Qt::AlignLeading;
+ } else if (role == Qt::ToolTipRole) {
+ QLocale locale;
+ const QStorageInfo &volume = m_volumes.at(index.row());
+ return tr("Root path : %1\n"
+ "Name: %2\n"
+ "Display Name: %3\n"
+ "Device: %4\n"
+ "FileSystem: %5\n"
+ "Total size: %6\n"
+ "Free size: %7\n"
+ "Available size: %8\n"
+ "Is Ready: %9\n"
+ "Is Read-only: %10\n"
+ "Is Valid: %11\n"
+ "Is Root: %12"
+ ).
+ arg(QDir::toNativeSeparators(volume.rootPath())).
+ arg(volume.name()).
+ arg(volume.displayName()).
+ arg(QString::fromUtf8(volume.device())).
+ arg(QString::fromUtf8(volume.fileSystemType())).
+ arg(locale.formattedDataSize(volume.bytesTotal())).
+ arg(locale.formattedDataSize(volume.bytesFree())).
+ arg(locale.formattedDataSize(volume.bytesAvailable())).
+ arg(volume.isReady() ? tr("true") : tr("false")).
+ arg(volume.isReadOnly() ? tr("true") : tr("false")).
+ arg(volume.isValid() ? tr("true") : tr("false")).
+ arg(volume.isRoot() ? tr("true") : tr("false"));
+ }
+ return QVariant();
+}
+
+QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation != Qt::Horizontal)
+ return QVariant();
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ switch (section) {
+ case ColumnRootPath:
+ return tr("Root Path");
+ case ColumnName:
+ return tr("Volume Name");
+ case ColumnDevice:
+ return tr("Device");
+ case ColumnFileSystemName:
+ return tr("File System");
+ case ColumnTotal:
+ return tr("Total");
+ case ColumnFree:
+ return tr("Free");
+ case ColumnAvailable:
+ return tr("Available");
+ case ColumnIsReady:
+ return tr("Ready");
+ case ColumnIsReadOnly:
+ return tr("Read-only");
+ case ColumnIsValid:
+ return tr("Valid");
+ default:
+ break;
+ }
+
+ return QVariant();
+}
diff --git a/examples/quick/demos/samegame/content/levels/level3.qml b/tests/manual/tableview/storagemodel/storagemodel.h
index 91b03a1658..787b2f04de 100644
--- a/examples/quick/demos/samegame/content/levels/level3.qml
+++ b/tests/manual/tableview/storagemodel/storagemodel.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Ivan Komissarov
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,23 +49,45 @@
**
****************************************************************************/
-import QtQuick 2.0
+#ifndef STORAGEMODEL_H
+#define STORAGEMODEL_H
-TemplateBase{
- scoreTarget: 3000
- timeTarget: 60
- goalText: "4 of 10<br>Clear the board with over 3000 points in under a minute..."
- startingGrid: [ 3 , 3 , 1 , 1 , 1 , 2 , 2 , 4 , 3 , 3 ,
- 4 , 3 , 1 , 4 , 2 , 2 , 2 , 4 , 3 , 4 ,
- 4 , 3 , 3 , 4 , 1 , 1 , 3 , 3 , 4 , 4 ,
- 3 , 3 , 3 , 3 , 3 , 1 , 3 , 2 , 2 , 4 ,
- 4 , 4 , 3 , 4 , 3 , 1 , 4 , 4 , 4 , 4 ,
- 4 , 4 , 3 , 4 , 1 , 1 , 4 , 4 , 3 , 3 ,
- 4 , 2 , 2 , 2 , 2 , 2 , 4 , 4 , 4 , 1 ,
- 4 , 4 , 2 , 4 , 2 , 2 , 1 , 1 , 1 , 1 ,
- 4 , 4 , 2 , 4 , 2 , 2 , 1 , 4 , 4 , 1 ,
- 4 , 1 , 1 , 4 , 3 , 3 , 4 , 2 , 4 , 1 ,
- 4 , 1 , 1 , 2 , 3 , 3 , 4 , 2 , 2 , 1 ,
- 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 2 , 1 ,
- 4 , 1 , 1 , 2 , 2 , 3 , 4 , 3 , 4 , 4 ]
-}
+#include <QAbstractTableModel>
+#include <QStorageInfo>
+
+class StorageModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(StorageModel)
+public:
+ enum Column {
+ ColumnRootPath = 0,
+ ColumnName,
+ ColumnDevice,
+ ColumnFileSystemName,
+ ColumnTotal,
+ ColumnFree,
+ ColumnAvailable,
+ ColumnIsReady,
+ ColumnIsReadOnly,
+ ColumnIsValid,
+ ColumnCount
+ };
+
+ explicit StorageModel(QObject *parent = nullptr);
+
+ int columnCount(const QModelIndex &parent) const override;
+ int rowCount(const QModelIndex &parent) const override;
+
+ QVariant data(const QModelIndex &index, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+
+public slots:
+ void refresh();
+
+private:
+ QList<QStorageInfo> m_volumes;
+};
+
+#endif // STORAGEMODEL_H
diff --git a/tests/manual/tableview/storagemodel/storagemodel.pro b/tests/manual/tableview/storagemodel/storagemodel.pro
new file mode 100644
index 0000000000..c6a018239e
--- /dev/null
+++ b/tests/manual/tableview/storagemodel/storagemodel.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = tableview_storage
+QT += qml quick
+SOURCES += main.cpp storagemodel.cpp
+HEADERS += storagemodel.h
+RESOURCES += main.qml
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/tests/manual/tableview/tableview.pro b/tests/manual/tableview/tableview.pro
new file mode 100644
index 0000000000..5040f0e747
--- /dev/null
+++ b/tests/manual/tableview/tableview.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS += abstracttablemodel \
+ listmodel \
+ storagemodel
diff --git a/tests/manual/touch/flicktext.qml b/tests/manual/touch/flicktext.qml
index 6e8dcfded5..9e84261687 100644
--- a/tests/manual/touch/flicktext.qml
+++ b/tests/manual/touch/flicktext.qml
@@ -48,7 +48,7 @@
**
****************************************************************************/
-import QtQuick 2.4
+import QtQuick 2.12
import "qrc:/quick/shared/" as Examples
Rectangle {
@@ -67,6 +67,7 @@ Rectangle {
contentWidth: text.implicitWidth
contentHeight: text.implicitHeight
pixelAligned: pxAlignCB.checked
+ synchronousDrag: syncDragCB.checked
Text {
id: text
text: "foo bar"
@@ -366,10 +367,15 @@ Rectangle {
}
Column {
+ spacing: 2
Examples.CheckBox {
id: pxAlignCB
text: "pixel aligned"
}
+ Examples.CheckBox {
+ id: syncDragCB
+ text: "synchronous drag"
+ }
Text {
text: "content X " + flick.contentX.toFixed(2) + " Y " + flick.contentY.toFixed(2)
}
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 73b2700ba4..6cf6ad3b2c 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -55,7 +55,9 @@
#include <QLibraryInfo>
#include <qqml.h>
#include <qqmldebug.h>
-#if QT_CONFIG(animation)
+
+#include <private/qtqmlglobal_p.h>
+#if QT_CONFIG(qml_animation)
#include <private/qabstractanimation_p.h>
#endif
@@ -483,7 +485,7 @@ int main(int argc, char *argv[])
break;
else if (arg == QLatin1String("-verbose"))
verboseMode = true;
-#if QT_CONFIG(animation)
+#if QT_CONFIG(qml_animation)
else if (arg == QLatin1String("-slow-animations"))
QUnifiedTimer::instance()->setSlowModeEnabled(true);
else if (arg == QLatin1String("-fixed-animations"))
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index 04704f9314..3f41707275 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -1,4 +1,4 @@
-QT = qml core-private
+QT = qml-private core-private
qtHaveModule(gui): QT += gui
qtHaveModule(widgets): QT += widgets
diff --git a/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake b/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in
index 49ba4edde9..e4963c3a33 100644
--- a/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake
+++ b/tools/qmlcachegen/Qt5QuickCompilerConfig.cmake.in
@@ -2,9 +2,9 @@ include(CMakeParseArguments)
function(QTQUICK_COMPILER_DETERMINE_OUTPUT_FILENAME outvariable filename)
file(RELATIVE_PATH relpath ${CMAKE_CURRENT_SOURCE_DIR} ${filename})
- string(REPLACE ".qml" "_qml" relpath ${relpath})
- string(REPLACE ".js" "_js" relpath ${relpath})
- string(REPLACE "/" "_" relpath ${relpath})
+ string(REPLACE \".qml\" \"_qml\" relpath ${relpath})
+ string(REPLACE \".js\" \"_js\" relpath ${relpath})
+ string(REPLACE \"/\" \"_\" relpath ${relpath})
set(${outvariable} ${CMAKE_CURRENT_BINARY_DIR}/${relpath}.cpp PARENT_SCOPE)
endfunction()
@@ -13,11 +13,26 @@ function(QTQUICK_COMPILER_ADD_RESOURCES outfiles)
set(oneValueArgs)
set(multiValueArgs OPTIONS)
- cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(_RCC \"${options}\" \"${oneValueArgs}\" \"${multiValueArgs}\" ${ARGN})
find_package(Qt5 COMPONENTS Qml Core)
- set(compiler_path "${_qt5Core_install_prefix}/bin/qmlcachegen")
+!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE)
+ set(compiler_path \"${_qt5Core_install_prefix}/$${CMAKE_BIN_DIR}qmlcachegen$$CMAKE_BIN_SUFFIX\")
+!!ELSE
+ set(compiler_path \"$${CMAKE_BIN_DIR}qmlcachegen$$CMAKE_BIN_SUFFIX\")
+!!ENDIF
+ if(NOT EXISTS \"${compiler_path}\" )
+ message(FATAL_ERROR \"The package \\\"Qt5QuickCompilerConfig\\\" references the file
+ \\\"${compiler_path}\\\"
+but this file does not exist. Possible reasons include:
+* The file was deleted, renamed, or moved to another location.
+* An install or uninstall procedure did not complete successfully.
+* The installation package was faulty and contained
+ \\\"${CMAKE_CURRENT_LIST_FILE}\\\"
+but not all the files it references.
+\")
+ endif()
get_target_property(rcc_path ${Qt5Core_RCC_EXECUTABLE} IMPORTED_LOCATION)
@@ -37,18 +52,18 @@ function(QTQUICK_COMPILER_ADD_RESOURCES outfiles)
execute_process(COMMAND ${compiler_path} -filter-resource-file ${input_resource} -o ${new_resource_file} OUTPUT_VARIABLE remaining_files)
if(remaining_files)
list(APPEND filtered_rcc_files ${new_resource_file})
- list(APPEND loader_flags "--resource-file-mapping=${_resource}=${new_resource_file}")
+ list(APPEND loader_flags \"--resource-file-mapping=${_resource}=${new_resource_file}\")
else()
- list(APPEND loader_flags "--resource-file-mapping=${_resource}")
+ list(APPEND loader_flags \"--resource-file-mapping=${_resource}\")
endif()
set(rcc_file_with_compilation_units)
- execute_process(COMMAND ${rcc_path} -list "${input_resource}" OUTPUT_VARIABLE rcc_contents)
- string(REGEX REPLACE "[\r\n]+" ";" rcc_contents ${rcc_contents})
+ execute_process(COMMAND ${rcc_path} -list \"${input_resource}\" OUTPUT_VARIABLE rcc_contents)
+ string(REGEX REPLACE \"[\r\n]+\" \";\" rcc_contents ${rcc_contents})
foreach(it ${rcc_contents})
get_filename_component(extension ${it} EXT)
- if(extension STREQUAL ".qml" OR extension STREQUAL ".js" OR extension STREQUAL ".ui.qml")
+ if(extension STREQUAL \".qml\" OR extension STREQUAL \".js\" OR extension STREQUAL \".ui.qml\")
qtquick_compiler_determine_output_filename(output_file ${it})
add_custom_command(OUTPUT ${output_file} COMMAND ${compiler_path} ARGS --resource=${input_resource} ${it} -o ${output_file} DEPENDS ${it})
list(APPEND compiler_output ${output_file})
@@ -70,4 +85,3 @@ function(QTQUICK_COMPILER_ADD_RESOURCES outfiles)
qt5_add_resources(output_resources ${filtered_rcc_files} OPTIONS ${options})
set(${outfiles} ${output_resources} ${compiler_output} PARENT_SCOPE)
endfunction()
-
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 8a2776e808..b9a8763c97 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -37,6 +37,7 @@
#include <private/qqmlirbuilder_p.h>
#include <private/qqmljsparser_p.h>
+#include <private/qqmljslexer_p.h>
#include "resourcefilemapper.h"
@@ -236,7 +237,7 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti
unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation;
irDocument.javaScriptCompilationUnit->data = unit;
- if (!saveFunction(irDocument.javaScriptCompilationUnit, &error->message))
+ if (!saveFunction(irDocument.javaScriptCompilationUnit.data(), &error->message))
return false;
free(unit);
@@ -304,7 +305,7 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile
&irDocument.jsGenerator.stringTable, illegalNames);
v4CodeGen.setUseFastLookups(false); // Disable lookups in non-standalone (aka QML) mode
v4CodeGen.generateFromProgram(inputFileName, inputFileUrl, sourceCode, program,
- &irDocument.jsModule, QV4::Compiler::GlobalCode);
+ &irDocument.jsModule, QV4::Compiler::ContextType::Global);
QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors();
if (!jsErrors.isEmpty()) {
for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) {
@@ -323,7 +324,7 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile
unit->flags |= QV4::CompiledData::Unit::StaticData;
irDocument.javaScriptCompilationUnit->data = unit;
- if (!saveFunction(irDocument.javaScriptCompilationUnit, &error->message)) {
+ if (!saveFunction(irDocument.javaScriptCompilationUnit.data(), &error->message)) {
engine->setDirectives(oldDirs);
return false;
}
@@ -434,9 +435,6 @@ int main(int argc, char **argv)
QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
parser.addOption(outputFileOption);
- QCommandLineOption checkIfSupportedOption(QStringLiteral("check-if-supported"), QCoreApplication::translate("main", "Check if cache generate is supported on the specified target architecture"));
- parser.addOption(checkIfSupportedOption);
-
parser.addPositionalArgument(QStringLiteral("[qml file]"),
QStringLiteral("QML source file to generate cache for."));
diff --git a/tools/qmlcachegen/qmlcachegen.pro b/tools/qmlcachegen/qmlcachegen.pro
index 391f0c3889..9662690395 100644
--- a/tools/qmlcachegen/qmlcachegen.pro
+++ b/tools/qmlcachegen/qmlcachegen.pro
@@ -14,7 +14,21 @@ build_integration.path = $$[QT_HOST_DATA]/mkspecs/features
prefix_build: INSTALLS += build_integration
else: COPIES += build_integration
-cmake_build_integration.files = Qt5QuickCompilerConfig.cmake
+load(cmake_functions)
+
+CMAKE_BIN_DIR = $$cmakeRelativePath($$[QT_HOST_BINS], $$[QT_INSTALL_PREFIX])
+contains(CMAKE_BIN_DIR, "^\\.\\./.*") {
+ CMAKE_BIN_DIR = $$[QT_HOST_BINS]/
+ CMAKE_BIN_DIR_IS_ABSOLUTE = True
+}
+
+load(qt_build_paths)
+
+cmake_config_file.input = $$PWD/Qt5QuickCompilerConfig.cmake.in
+cmake_config_file.output = $$MODULE_BASE_OUTDIR/lib/cmake/Qt5QuickCompiler/Qt5QuickCompilerConfig.cmake
+QMAKE_SUBSTITUTES += cmake_config_file
+
+cmake_build_integration.files = $$cmake_config_file.output
cmake_build_integration.path = $$[QT_INSTALL_LIBS]/cmake/Qt5QuickCompiler
prefix_build: INSTALLS += cmake_build_integration
else: COPIES += cmake_build_integration
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index ea014f3beb..c8abb7330a 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -80,6 +80,15 @@ int main(int argc, char *argv[])
bool cache = false;
if (!args.isEmpty()) {
+ if (args.constFirst() == QLatin1String("--jit")) {
+ qputenv("QV4_JIT_CALL_THRESHOLD", QByteArray("0"));
+ args.removeFirst();
+ }
+ if (args.constFirst() == QLatin1String("--interpret")) {
+ qputenv("QV4_FORCE_INTERPRETER", QByteArray("1"));
+ args.removeFirst();
+ }
+
if (args.constFirst() == QLatin1String("--qml")) {
runAsQml = true;
args.removeFirst();
@@ -120,7 +129,7 @@ int main(int argc, char *argv[])
const QString code = QString::fromUtf8(file.readAll());
file.close();
- script.reset(new QV4::Script(ctx, QV4::Compiler::GlobalCode, code, fn));
+ script.reset(new QV4::Script(ctx, QV4::Compiler::ContextType::Global, code, fn));
script->parseAsBinding = runAsQml;
script->parse();
}
diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp
index 5641e6348e..26833d2a08 100644
--- a/tools/qmlmin/main.cpp
+++ b/tools/qmlmin/main.cpp
@@ -57,15 +57,48 @@ class QmlminLexer: protected Lexer, public Directives
QString _fileName;
QString _directives;
+protected:
+ QVector<int> _stateStack;
+ QList<int> _tokens;
+ QList<QString> _tokenStrings;
+ int yytoken = -1;
+ QString yytokentext;
+
+ void lex() {
+ if (_tokens.isEmpty()) {
+ _tokens.append(Lexer::lex());
+ _tokenStrings.append(tokenText());
+ }
+
+ yytoken = _tokens.takeFirst();
+ yytokentext = _tokenStrings.takeFirst();
+ }
+
+ int lookaheadToken()
+ {
+ if (yytoken < 0)
+ lex();
+ return yytoken;
+ }
+
+ void pushToken(int token)
+ {
+ _tokens.prepend(yytoken);
+ _tokenStrings.prepend(yytokentext);
+ yytoken = token;
+ yytokentext = QString();
+ }
+
public:
- QmlminLexer(): Lexer(&_engine) {}
+ QmlminLexer()
+ : Lexer(&_engine), _stateStack(128) {}
virtual ~QmlminLexer() {}
QString fileName() const { return _fileName; }
bool operator()(const QString &fileName, const QString &code)
{
- int startToken = T_FEED_JS_PROGRAM;
+ int startToken = T_FEED_JS_SCRIPT;
const QFileInfo fileInfo(fileName);
if (fileInfo.suffix().toLower() == QLatin1String("qml"))
startToken = T_FEED_UI_PROGRAM;
@@ -154,6 +187,24 @@ protected:
ruleno == J_SCRIPT_REGEXPLITERAL_RULE2;
}
+ void handleLookaheads(int ruleno) {
+ if (ruleno == J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE) {
+ int token = lookaheadToken();
+ if (token == T_LBRACE)
+ pushToken(T_FORCE_BLOCK);
+ else if (token == T_FUNCTION || token == T_CLASS || token == T_LET || token == T_CONST)
+ pushToken(T_FORCE_DECLARATION);
+ } else if (ruleno == J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE) {
+ int token = lookaheadToken();
+ if (token == T_LBRACE)
+ pushToken(T_FORCE_BLOCK);
+ } else if (ruleno == J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE) {
+ int token = lookaheadToken();
+ if (token == T_FUNCTION || token == T_CLASS)
+ pushToken(T_FORCE_DECLARATION);
+ }
+ }
+
bool scanRestOfRegExp(int ruleno, QString *restOfRegExp)
{
if (! scanRegExp(ruleno == J_SCRIPT_REGEXPLITERAL_RULE1 ? Lexer::NoPrefix : Lexer::EqualPrefix))
@@ -187,9 +238,6 @@ protected:
class Minify: public QmlminLexer
{
- QVector<int> _stateStack;
- QList<int> _tokens;
- QList<QString> _tokenStrings;
QString _minifiedCode;
int _maxWidth;
int _width;
@@ -206,7 +254,7 @@ protected:
};
Minify::Minify(int maxWidth)
- : _stateStack(128), _maxWidth(maxWidth), _width(0)
+ : _maxWidth(maxWidth), _width(0)
{
}
@@ -250,16 +298,14 @@ void Minify::escape(const QChar &ch, QString *out)
bool Minify::parse(int startToken)
{
int yyaction = 0;
- int yytoken = -1;
int yytos = -1;
- QString yytokentext;
QString assembled;
_minifiedCode.clear();
_tokens.append(startToken);
_tokenStrings.append(QString());
- if (startToken == T_FEED_JS_PROGRAM) {
+ if (startToken == T_FEED_JS_SCRIPT) {
// parse optional pragma directive
DiagnosticMessage error;
if (scanDirectives(this, &error)) {
@@ -282,15 +328,8 @@ bool Minify::parse(int startToken)
_stateStack[yytos] = yyaction;
again:
- if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT) {
- if (_tokens.isEmpty()) {
- _tokens.append(lex());
- _tokenStrings.append(tokenText());
- }
-
- yytoken = _tokens.takeFirst();
- yytokentext = _tokenStrings.takeFirst();
- }
+ if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT)
+ lex();
yyaction = t_action(yyaction, yytoken);
if (yyaction > 0) {
@@ -366,6 +405,8 @@ bool Minify::parse(int startToken)
const int ruleno = -yyaction - 1;
yytos -= rhs[ruleno];
+ handleLookaheads(ruleno);
+
if (isRegExpRule(ruleno)) {
QString restOfRegExp;
@@ -398,13 +439,10 @@ bool Minify::parse(int startToken)
class Tokenize: public QmlminLexer
{
- QVector<int> _stateStack;
- QList<int> _tokens;
- QList<QString> _tokenStrings;
QStringList _minifiedCode;
public:
- Tokenize();
+ Tokenize() {}
QStringList tokenStream() const;
@@ -412,11 +450,6 @@ protected:
bool parse(int startToken) override;
};
-Tokenize::Tokenize()
- : _stateStack(128)
-{
-}
-
QStringList Tokenize::tokenStream() const
{
return _minifiedCode;
@@ -425,15 +458,13 @@ QStringList Tokenize::tokenStream() const
bool Tokenize::parse(int startToken)
{
int yyaction = 0;
- int yytoken = -1;
int yytos = -1;
- QString yytokentext;
_minifiedCode.clear();
_tokens.append(startToken);
_tokenStrings.append(QString());
- if (startToken == T_FEED_JS_PROGRAM) {
+ if (startToken == T_FEED_JS_SCRIPT) {
// parse optional pragma directive
DiagnosticMessage error;
if (scanDirectives(this, &error)) {
@@ -457,15 +488,8 @@ bool Tokenize::parse(int startToken)
_stateStack[yytos] = yyaction;
again:
- if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT) {
- if (_tokens.isEmpty()) {
- _tokens.append(lex());
- _tokenStrings.append(tokenText());
- }
-
- yytoken = _tokens.takeFirst();
- yytokentext = _tokenStrings.takeFirst();
- }
+ if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT)
+ lex();
yyaction = t_action(yyaction, yytoken);
if (yyaction > 0) {
@@ -484,6 +508,8 @@ bool Tokenize::parse(int startToken)
const int ruleno = -yyaction - 1;
yytos -= rhs[ruleno];
+ handleLookaheads(ruleno);
+
if (isRegExpRule(ruleno)) {
QString restOfRegExp;
diff --git a/tools/qmlpreview/main.cpp b/tools/qmlpreview/main.cpp
new file mode 100644
index 0000000000..c7a32da258
--- /dev/null
+++ b/tools/qmlpreview/main.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpreviewapplication.h"
+
+int main(int argc, char *argv[])
+{
+ QmlPreviewApplication app(argc, argv);
+ app.parseArguments();
+ return app.exec();
+}
diff --git a/tools/qmlpreview/qmlpreview.pro b/tools/qmlpreview/qmlpreview.pro
new file mode 100644
index 0000000000..7d443b5f6c
--- /dev/null
+++ b/tools/qmlpreview/qmlpreview.pro
@@ -0,0 +1,13 @@
+QT = network core qmldebug-private
+CONFIG += no_import_scan
+
+SOURCES += \
+ main.cpp \
+ qmlpreviewapplication.cpp
+
+HEADERS += \
+ qmlpreviewapplication.h
+
+QMAKE_TARGET_DESCRIPTION = QML Preview
+
+load(qt_tool)
diff --git a/tools/qmlpreview/qmlpreviewapplication.cpp b/tools/qmlpreview/qmlpreviewapplication.cpp
new file mode 100644
index 0000000000..618769502c
--- /dev/null
+++ b/tools/qmlpreview/qmlpreviewapplication.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpreviewapplication.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QTextStream>
+#include <QtCore/QProcess>
+#include <QtCore/QTimer>
+#include <QtCore/QDateTime>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QCommandLineParser>
+#include <QtCore/QTemporaryFile>
+#include <QtCore/QUrl>
+
+QmlPreviewApplication::QmlPreviewApplication(int &argc, char **argv) :
+ QCoreApplication(argc, argv),
+ m_verbose(false),
+ m_connectionAttempts(0)
+{
+ m_connection.reset(new QQmlDebugConnection);
+ m_qmlPreviewClient.reset(new QQmlPreviewClient(m_connection.data()));
+ m_connectTimer.setInterval(1000);
+
+ m_loadTimer.setInterval(100);
+ m_loadTimer.setSingleShot(true);
+ connect(&m_loadTimer, &QTimer::timeout, this, [this]() {
+ m_qmlPreviewClient->triggerLoad(QUrl());
+ });
+
+ connect(&m_connectTimer, &QTimer::timeout, this, &QmlPreviewApplication::tryToConnect);
+ connect(m_connection.data(), &QQmlDebugConnection::connected, &m_connectTimer, &QTimer::stop);
+
+ connect(m_qmlPreviewClient.data(), &QQmlPreviewClient::error,
+ this, &QmlPreviewApplication::logError);
+ connect(m_qmlPreviewClient.data(), &QQmlPreviewClient::request,
+ this, &QmlPreviewApplication::serveRequest);
+
+ connect(&m_watcher, &QFileSystemWatcher::fileChanged,
+ this, &QmlPreviewApplication::sendFile);
+ connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
+ this, &QmlPreviewApplication::sendDirectory);
+}
+
+QmlPreviewApplication::~QmlPreviewApplication()
+{
+ if (m_process && m_process->state() != QProcess::NotRunning) {
+ logStatus("Terminating process ...");
+ m_process->disconnect();
+ m_process->terminate();
+ if (!m_process->waitForFinished(1000)) {
+ logStatus("Killing process ...");
+ m_process->kill();
+ }
+ }
+}
+
+void QmlPreviewApplication::parseArguments()
+{
+ setApplicationName(QLatin1String("qmlpreview"));
+ setApplicationVersion(QLatin1String(qVersion()));
+
+ QCommandLineParser parser;
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+ parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
+
+ parser.setApplicationDescription(QChar::LineFeed + tr(
+ "The QML Preview tool watches QML and JavaScript files on disk and updates\n"
+ "the application live with any changes. The application to be previewed\n"
+ "has to enable QML debugging. See the Qt Creator documentation on how to do\n"
+ "this for different Qt versions."));
+
+ QCommandLineOption verbose(QStringList() << QLatin1String("verbose"),
+ tr("Print debugging output."));
+ parser.addOption(verbose);
+
+ parser.addHelpOption();
+ parser.addVersionOption();
+
+ parser.addPositionalArgument(QLatin1String("program"),
+ tr("The program to be started and profiled."),
+ QLatin1String("[program]"));
+ parser.addPositionalArgument(QLatin1String("parameters"),
+ tr("Parameters for the program to be started."),
+ QLatin1String("[parameters...]"));
+
+ parser.process(*this);
+
+ QTemporaryFile file;
+ if (file.open())
+ m_socketFile = file.fileName();
+
+ if (parser.isSet(verbose))
+ m_verbose = true;
+
+ m_programArguments = parser.positionalArguments();
+ if (!m_programArguments.isEmpty())
+ m_programPath = m_programArguments.takeFirst();
+
+ if (m_programPath.isEmpty()) {
+ logError(tr("You have to specify a program to start."));
+ parser.showHelp(2);
+ }
+}
+
+int QmlPreviewApplication::exec()
+{
+ QTimer::singleShot(0, this, &QmlPreviewApplication::run);
+ return QCoreApplication::exec();
+}
+
+void QmlPreviewApplication::run()
+{
+ logStatus(QString("Listening on %1 ...").arg(m_socketFile));
+ m_connection->startLocalServer(m_socketFile);
+ m_process.reset(new QProcess(this));
+ QStringList arguments;
+ arguments << QString("-qmljsdebugger=file:%1,block,services:QmlPreview").arg(m_socketFile);
+ arguments << m_programArguments;
+
+ m_process->setProcessChannelMode(QProcess::MergedChannels);
+ connect(m_process.data(), &QIODevice::readyRead,
+ this, &QmlPreviewApplication::processHasOutput);
+ connect(m_process.data(), static_cast<void(QProcess::*)(int)>(&QProcess::finished),
+ this, [this](int){ processFinished(); });
+ logStatus(QString("Starting '%1 %2' ...").arg(m_programPath, arguments.join(QLatin1Char(' '))));
+ m_process->start(m_programPath, arguments);
+ if (!m_process->waitForStarted()) {
+ logError(QString("Could not run '%1': %2").arg(m_programPath, m_process->errorString()));
+ exit(1);
+ }
+ m_connectTimer.start();
+}
+
+void QmlPreviewApplication::tryToConnect()
+{
+ Q_ASSERT(!m_connection->isConnected());
+ ++m_connectionAttempts;
+
+ if (m_verbose && !(m_connectionAttempts % 5)) {// print every 5 seconds
+ logError(QString("No connection received on %1 for %2 seconds ...")
+ .arg(m_socketFile).arg(m_connectionAttempts));
+ }
+}
+
+void QmlPreviewApplication::processHasOutput()
+{
+ Q_ASSERT(m_process);
+ while (m_process->bytesAvailable()) {
+ QTextStream out(stderr);
+ out << m_process->readAll();
+ }
+}
+
+void QmlPreviewApplication::processFinished()
+{
+ Q_ASSERT(m_process);
+ int exitCode = 0;
+ if (m_process->exitStatus() == QProcess::NormalExit) {
+ logStatus(QString("Process exited (%1).").arg(m_process->exitCode()));
+ } else {
+ logError("Process crashed!");
+ exitCode = 3;
+ }
+ exit(exitCode);
+}
+
+void QmlPreviewApplication::logError(const QString &error)
+{
+ QTextStream err(stderr);
+ err << "Error: " << error << endl;
+}
+
+void QmlPreviewApplication::logStatus(const QString &status)
+{
+ if (!m_verbose)
+ return;
+ QTextStream err(stderr);
+ err << status << endl;
+}
+
+void QmlPreviewApplication::serveRequest(const QString &path)
+{
+ QFileInfo info(path);
+
+ if (info.isDir()) {
+ m_qmlPreviewClient->sendDirectory(path, QDir(path).entryList());
+ m_watcher.addPath(path);
+ } else {
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly)) {
+ m_qmlPreviewClient->sendFile(path, file.readAll());
+ m_watcher.addPath(path);
+
+ // Also watch the directory, because editors will rather replace a file than change it.
+ // Therefore when the file changes, we can't read it, but when the file is re-added we can
+ // see that from the directory changing.
+ m_watcher.addPath(info.absolutePath());
+ } else {
+ logStatus(QString("Could not open file %1 for reading: %2").arg(path)
+ .arg(file.errorString()));
+ m_qmlPreviewClient->sendError(path);
+ }
+ }
+}
+
+bool QmlPreviewApplication::sendFile(const QString &path)
+{
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly)) {
+ m_qmlPreviewClient->sendFile(path, file.readAll());
+ m_pendingFiles.removeAll(path);
+ // Defer the Load, because files tend to change multiple times in a row.
+ m_loadTimer.start();
+ return true;
+ }
+ if (!m_pendingFiles.contains(path))
+ m_pendingFiles.append(path);
+ logStatus(QString("Could not open file %1 for reading: %2").arg(path).arg(file.errorString()));
+ return false;
+}
+
+void QmlPreviewApplication::sendDirectory(const QString &path)
+{
+ m_qmlPreviewClient->sendDirectory(path, QDir(path).entryList());
+ for (auto it = m_pendingFiles.begin(); it != m_pendingFiles.end();) {
+ const QString filePath = *it;
+ QFile file(filePath);
+ if (file.open(QIODevice::ReadOnly)) {
+ logStatus(QString("Sending replaced file %1.").arg(filePath));
+ m_qmlPreviewClient->sendFile(filePath, file.readAll());
+ m_watcher.addPath(filePath);
+ it = m_pendingFiles.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ m_loadTimer.start();
+}
diff --git a/tools/qmlpreview/qmlpreviewapplication.h b/tools/qmlpreview/qmlpreviewapplication.h
new file mode 100644
index 0000000000..eb363b0eb6
--- /dev/null
+++ b/tools/qmlpreview/qmlpreviewapplication.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPREVIEWAPPLICATION_H
+#define QMLPREVIEWAPPLICATION_H
+
+#include <private/qqmlpreviewclient_p.h>
+#include <private/qqmldebugconnection_p.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qfilesystemwatcher.h>
+
+#include <QtNetwork/qabstractsocket.h>
+
+class QmlPreviewApplication : public QCoreApplication
+{
+ Q_OBJECT
+public:
+ QmlPreviewApplication(int &argc, char **argv);
+ ~QmlPreviewApplication();
+
+ void parseArguments();
+ int exec();
+
+private:
+ void run();
+ void tryToConnect();
+ void processHasOutput();
+ void processFinished();
+
+ void logError(const QString &error);
+ void logStatus(const QString &status);
+
+ void serveRequest(const QString &request);
+ bool sendFile(const QString &path);
+ void sendDirectory(const QString &path);
+
+ QString m_programPath;
+ QStringList m_programArguments;
+ QScopedPointer<QProcess> m_process;
+ bool m_verbose;
+
+ QString m_socketFile;
+
+ QScopedPointer<QQmlDebugConnection> m_connection;
+ QScopedPointer<QQmlPreviewClient> m_qmlPreviewClient;
+ QFileSystemWatcher m_watcher;
+
+ QTimer m_loadTimer;
+ QTimer m_connectTimer;
+ uint m_connectionAttempts;
+
+ QStringList m_pendingFiles;
+};
+
+#endif // QMLPREVIEWAPPLICATION_H
diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp
index 0b63a91e5b..6732766b46 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.cpp
+++ b/tools/qmlprofiler/qmlprofilerapplication.cpp
@@ -120,6 +120,10 @@ QmlProfilerApplication::~QmlProfilerApplication()
logStatus("Killing process ...");
m_process->kill();
}
+ if (isInteractive()) {
+ QTextStream err(stderr);
+ err << endl;
+ }
delete m_process;
}
@@ -366,7 +370,7 @@ void QmlProfilerApplication::userCommand(const QString &command)
m_pendingRequest = REQUEST_NONE;
prompt();
} else {
- prompt(tr("The application is still generating data. Really quit (y/n)?"));
+ prompt(tr("Really quit (y/n)?"));
}
return;
}
diff --git a/tools/qmlprofiler/qmlprofilerclient.cpp b/tools/qmlprofiler/qmlprofilerclient.cpp
index b69c7e73e1..f6cc6f39fe 100644
--- a/tools/qmlprofiler/qmlprofilerclient.cpp
+++ b/tools/qmlprofiler/qmlprofilerclient.cpp
@@ -57,6 +57,8 @@ QmlProfilerClient::QmlProfilerClient(QQmlDebugConnection *connection, QmlProfile
{
Q_D(QmlProfilerClient);
setRequestedFeatures(std::numeric_limits<quint64>::max());
+ connect(this, &QQmlDebugClient::stateChanged,
+ this, &QmlProfilerClient::onStateChanged);
connect(this, &QQmlProfilerClient::traceStarted,
d->data, &QmlProfilerData::setTraceStartTime);
connect(this, &QQmlProfilerClient::traceFinished,
@@ -65,7 +67,7 @@ QmlProfilerClient::QmlProfilerClient(QQmlDebugConnection *connection, QmlProfile
d->data, &QmlProfilerData::complete);
}
-void QmlProfilerClient::stateChanged(State state)
+void QmlProfilerClient::onStateChanged(State state)
{
Q_D(QmlProfilerClient);
if ((d->enabled && state != Enabled) || (!d->enabled && state == Enabled)) {
diff --git a/tools/qmlprofiler/qmlprofilerclient.h b/tools/qmlprofiler/qmlprofilerclient.h
index 30f4a51751..7355688222 100644
--- a/tools/qmlprofiler/qmlprofilerclient.h
+++ b/tools/qmlprofiler/qmlprofilerclient.h
@@ -48,7 +48,7 @@ signals:
void error(const QString &error);
private:
- void stateChanged(State state) override;
+ void onStateChanged(State state);
};
#endif // QMLPROFILERCLIENT_H
diff --git a/tools/tools.pro b/tools/tools.pro
index 856906cc53..22544d60d3 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -1,17 +1,21 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += qml-private
-SUBDIRS += \
- qmlmin \
- qmlimportscanner
-qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen
+qtConfig(qml-devtools) {
+ SUBDIRS += \
+ qmlmin \
+ qmlimportscanner
+
+ qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen
+}
!android|android_app {
SUBDIRS += \
- qml \
- qmllint
+ qml
+ qtConfig(qml-devtools): SUBDIRS += qmllint
qtConfig(qml-profiler): SUBDIRS += qmlprofiler
+ qtConfig(qml-preview): SUBDIRS += qmlpreview
qtHaveModule(quick) {
!static: {
@@ -30,8 +34,10 @@ qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen
qtConfig(private_tests): SUBDIRS += qmljs
}
-qml.depends = qmlimportscanner
-qmleasing.depends = qmlimportscanner
+qtConfig(qml-devtools) {
+ qml.depends = qmlimportscanner
+ qmleasing.depends = qmlimportscanner
+}
# qmlmin, qmlimportscanner & qmlcachegen are build tools.
# qmlscene is needed by the autotests.