aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-20 08:21:42 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-09-20 08:29:17 +0200
commitbbb78a92a910d32b2886af62c218db87325eb6ce (patch)
tree0e4b55352bb9f083826d0e80747982823f2894ed /tools
parent4b5a7b15fc6d3650c8e9b7bf619804a0a953eeba (diff)
parent8ed38c70fd29680f7981d9d23581d46cf32139d0 (diff)
Merge branch 'dev' of ssh://codereview.qt-project.org/qt/qtdeclarative into HEAD
Conflicts: src/qml/compiler/qv4isel_masm.cpp src/qml/jsruntime/qv4script.cpp src/qml/qml/qml.pri src/qml/qml/qqmltypeloader_p.h Change-Id: Ia784d855a2131e3289454f12d841ca2c65be15c1
Diffstat (limited to 'tools')
-rw-r--r--tools/qml/Info.plist49
-rw-r--r--tools/qml/conf.h99
-rw-r--r--tools/qml/conf/configuration.qml47
-rw-r--r--tools/qml/conf/qtquick.qml55
-rw-r--r--tools/qml/main.cpp466
-rw-r--r--tools/qml/qml.icnsbin0 -> 196156 bytes
-rw-r--r--tools/qml/qml.pro14
-rw-r--r--tools/qml/qml.qrc6
-rw-r--r--tools/qmlplugindump/main.cpp240
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp6
-rw-r--r--tools/qmlprofiler/qpacketprotocol.cpp1
-rw-r--r--tools/tools.pro1
-rw-r--r--tools/v4/main.cpp25
13 files changed, 934 insertions, 75 deletions
diff --git a/tools/qml/Info.plist b/tools/qml/Info.plist
new file mode 100644
index 0000000000..42d074a3af
--- /dev/null
+++ b/tools/qml/Info.plist
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.1">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.qt-project.qml</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>@TYPEINFO@</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+ <key>UTExportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeIdentifier</key>
+ <string>org.qt-project.qml</string>
+ <key>UTTypeDescription</key>
+ <string>Qt Markup Language</string>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.plain-text</string>
+ </array>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>qml</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.qt-project.qml</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/tools/qml/conf.h b/tools/qml/conf.h
new file mode 100644
index 0000000000..24ea44edb9
--- /dev/null
+++ b/tools/qml/conf.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef CONF_H
+#define CONF_H
+
+#include <QtQml>
+#include <QObject>
+#include <QUrl>
+
+class PartialScene : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl container READ container WRITE setContainer NOTIFY containerChanged)
+ Q_PROPERTY(QString itemType READ itemType WRITE setItemType NOTIFY itemTypeChanged)
+public:
+ PartialScene(QObject *parent = 0) : QObject(parent)
+ {}
+
+ const QUrl container() const { return m_container; }
+ const QString itemType() const { return m_itemType; }
+
+ void setContainer(const QUrl &a) {
+ if (a==m_container)
+ return;
+ m_container = a;
+ emit containerChanged();
+ }
+ void setItemType(const QString &a) {
+ if (a==m_itemType)
+ return;
+ m_itemType = a;
+ emit itemTypeChanged();
+ }
+
+signals:
+ void containerChanged();
+ void itemTypeChanged();
+
+private:
+ QUrl m_container;
+ QString m_itemType;
+};
+
+class Config : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<PartialScene> sceneCompleters READ sceneCompleters)
+ Q_CLASSINFO("DefaultProperty", "sceneCompleters")
+public:
+ Config (QObject* parent=0) : QObject(parent)
+ {}
+
+ QQmlListProperty<PartialScene> sceneCompleters()
+ {
+ return QQmlListProperty<PartialScene>(this, completers);
+ }
+
+ QList<PartialScene*> completers;
+};
+
+#endif
diff --git a/tools/qml/conf/configuration.qml b/tools/qml/conf/configuration.qml
new file mode 100644
index 0000000000..4a9494e8b5
--- /dev/null
+++ b/tools/qml/conf/configuration.qml
@@ -0,0 +1,47 @@
+/*****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+*****************************************************************************/
+import QmlRuntime.Config 1.0
+
+Configuration {
+ PartialScene {
+ itemType: "QQuickItem"
+ container: "qtquick.qml"
+ }
+}
diff --git a/tools/qml/conf/qtquick.qml b/tools/qml/conf/qtquick.qml
new file mode 100644
index 0000000000..3da5c09d41
--- /dev/null
+++ b/tools/qml/conf/qtquick.qml
@@ -0,0 +1,55 @@
+/*****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+*****************************************************************************/
+import QtQuick.Window 2.0
+import QtQuick 2.0
+
+Window {
+ property Item containedObject: null
+ onContainedObjectChanged: {
+ if (containedObject == undefined || containedObject == null) {
+ visible = false;
+ return;
+ }
+ width = containedObject.width;
+ height = containedObject.height;
+ containedObject.parent = contentItem;
+ visible = true;
+ }
+}
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
new file mode 100644
index 0000000000..c059373143
--- /dev/null
+++ b/tools/qml/main.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "conf.h"
+
+#include <QCoreApplication>
+#include <QGuiApplication>
+#ifdef QT_WIDGETS_LIB
+#include <QApplication>
+#endif
+#include <QWindow>
+#include <QQmlApplicationEngine>
+#include <QFileOpenEvent>
+#include <QFile>
+#include <QFileInfo>
+#include <QRegularExpression>
+#include <QStringList>
+#include <QDebug>
+#include <QStandardPaths>
+#include <QtGlobal>
+#include <qqml.h>
+#include <qqmldebug.h>
+#include <private/qabstractanimation_p.h>
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+
+#define VERSION_MAJ 1
+#define VERSION_MIN 0
+#define VERSION_STR "1.0"
+
+static Config *conf = 0;
+static QQmlApplicationEngine *qae = 0;
+
+static void loadConf(const QString &override, bool quiet) // Terminates app on failure
+{
+ const QString defaultFileName = QLatin1String("configuration.qml");
+ QUrl settingsUrl;
+ bool builtIn = false; //just for keeping track of the warning
+ if (override.isEmpty()) {
+ QFileInfo fi;
+ fi.setFile(QStandardPaths::locate(QStandardPaths::DataLocation, defaultFileName));
+ if (fi.exists()) {
+ settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
+ } else {
+ // ### If different built-in configs are needed per-platform, just apply QFileSelector to the qrc conf.qml path
+ settingsUrl = QUrl(QLatin1String("qrc:///qt-project.org/QmlRuntime/conf/") + defaultFileName);
+ builtIn = true;
+ }
+ } else {
+ QFileInfo fi;
+ fi.setFile(override);
+ if (!fi.exists()) {
+ qCritical() << QObject::tr("qml: Couldn't find required configuration file:") << fi.absoluteFilePath();
+ exit(1);
+ }
+ settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
+ }
+
+ if (!quiet) {
+ if (builtIn)
+ qWarning() << QObject::tr("qml: Using built-in configuration.");
+ else
+ qWarning() << QObject::tr("qml: Using configuration file:") << settingsUrl;
+ }
+
+ // TODO: When we have better engine control, ban QtQuick* imports on this engine
+ QQmlEngine e2;
+ QQmlComponent c2(&e2, settingsUrl);
+ conf = qobject_cast<Config*>(c2.create());
+
+ if (!conf){
+ qCritical() << QObject::tr("qml: Error loading configuration file:") << c2.errorString();
+ exit(1);
+ }
+}
+
+void contain(QObject *o, const QUrl &containPath)
+{
+ QQmlComponent c(qae, containPath);
+ QObject *o2 = c.create();
+ if (!o2)
+ return;
+ bool success = false;
+ int idx;
+ if ((idx = o2->metaObject()->indexOfProperty("containedObject")) != -1)
+ success = o2->metaObject()->property(idx).write(o2, QVariant::fromValue<QObject*>(o));
+ if (!success)
+ o->setParent(o2); //Set QObject parent, and assume container will react as needed
+}
+
+// Loads qml after receiving a QFileOpenEvent
+class LoaderApplication : public QGuiApplication
+{
+public:
+ LoaderApplication(int& argc, char **argv) : QGuiApplication(argc, argv) {}
+
+ bool event(QEvent *ev)
+ {
+ if (ev->type() == QEvent::FileOpen)
+ qae->load(static_cast<QFileOpenEvent *>(ev)->url());
+ else
+ return QGuiApplication::event(ev);
+ return true;
+ }
+};
+
+// Listens to the appEngine signals to determine if all files failed to load
+class LoadWatcher : public QObject
+{
+ Q_OBJECT
+public:
+ LoadWatcher(QQmlApplicationEngine *e, int expected)
+ : QObject(e)
+ , expect(expected)
+ , haveOne(false)
+ {
+ connect(e, SIGNAL(objectCreated(QObject*,QUrl)),
+ this, SLOT(checkFinished(QObject*)));
+ }
+
+private:
+ int expect;
+ bool haveOne;
+
+public Q_SLOTS:
+ void checkFinished(QObject *o)
+ {
+ if (o) {
+ haveOne = true;
+ if (conf && qae)
+ foreach (PartialScene *ps, conf->completers)
+ if (o->inherits(ps->itemType().toUtf8().constData()))
+ contain(o, ps->container());
+ }
+ if (haveOne)
+ return;
+
+ if (! --expect) {
+ qCritical() << QObject::tr("qml: Did not load any objects, exiting.");
+ exit(2);//Different return code from qFatal
+ }
+ }
+};
+
+void quietMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, const QString &msg)
+{
+ Q_UNUSED(ctxt);
+ Q_UNUSED(msg);
+ //Doesn't print anything
+ switch (type) {
+ case QtFatalMsg:
+ abort();
+ case QtCriticalMsg:
+ case QtDebugMsg:
+ case QtWarningMsg:
+ ;
+ }
+}
+
+
+// ### Should command line arguments have translations? Qt creator doesn't, so maybe it's not worth it.
+bool useCoreApp = false;
+bool useWidgetApp = false;
+bool quietMode = false;
+void printVersion()
+{
+ printf("qml binary version ");
+ printf(VERSION_STR);
+ printf("\nbuilt with Qt version ");
+ printf(QT_VERSION_STR);
+ printf("\n");
+ exit(0);
+}
+
+void printUsage()
+{
+ printf("Usage: qml [options] [files]\n");
+ printf("\n");
+ printf("Any argument ending in .qml will be treated as a QML file to be loaded.\n");
+ printf("Any number of QML files can be loaded. They will share the same engine.\n");
+ printf("Any argument which is not a recognized option and which does not end in .qml will be ignored.\n");
+ printf("'widget' application type is only available if the QtWidgets module is avaialble.\n");
+ printf("\n");
+ printf("General Options:\n");
+ printf("\t-h, -help..................... Print this usage information and exit.\n");
+ printf("\t-v, -version.................. Print the version information and exit.\n");
+ printf("\t-apptype [core|gui|widget] ... Select which application class to use. Default is gui.\n");
+ printf("\t-quiet ....................... Suppress all output.\n");
+ printf("\t-I [path] .................... Prepend the given path to the import paths.\n");
+ printf("\t-f [file] .................... Load the given file as a QML file.\n");
+ printf("\t-config [file] ............... Load the given file as the configuration file.\n");
+ printf("\t-- ........................... Arguments after this one are ignored by the launcher, but may be used within the QML application.\n");
+ printf("\tDebugging options:\n");
+ printf("\t-enable-debugger ............. Allow the QML debugger to connect to the application (also requires debugger arguments).\n");
+ printf("\t-translation [file] .......... Load the given file as the translations file.\n");
+ printf("\t-dummy-data [directory] ...... Load QML files from the given directory as context properties.\n");
+ printf("\t-slow-animations ............. Run all animations in slow motion.\n");
+ printf("\t-fixed-animations ............ Run animations off animation tick rather than wall time.\n");
+ exit(0);
+}
+
+//Called before application initialization, removes arguments it uses
+void getAppFlags(int &argc, char **argv)
+{
+ for (int i=0; i<argc; i++) {
+ if (!strcmp(argv[i], "-apptype")) { // Must be done before application, as it selects application
+ int type = 0;
+ if (i+1 < argc) {
+ if (!strcmp(argv[i+1], "core"))
+ type = 1;
+ else if (!strcmp(argv[i+1], "gui"))
+ type = 2;
+#ifdef QT_WIDGETS_LIB
+ else if (!strcmp(argv[i+1], "widget"))
+ type = 3;
+#endif
+ }
+
+ if (!type) {
+#ifdef QT_WIDGETS_LIB
+ printf("-apptype must be followed by one of the following: core gui widget\n");
+#else
+ printf("-apptype must be followed by one of the following: core gui\n");
+#endif
+ printUsage();
+ }
+
+ switch (type) {
+ case 1: useCoreApp = true; break;
+ case 2: useCoreApp = false; break;
+#ifdef QT_WIDGETS_LIB
+ case 3: useWidgetApp = true; break;
+#endif
+ }
+ for (int j=i; j<argc-2; j++)
+ argv[j] = argv[j+2];
+ argc -= 2;
+ } else if (!strcmp(argv[i], "-enable-debugger")) { // Normally done via a define in the include, so expects to be before application (and must be before engine)
+ static QQmlDebuggingEnabler qmlEnableDebuggingHelper(true);
+ for (int j=i; j<argc-1; j++)
+ argv[j] = argv[j+1];
+ argc --;
+ }
+ }
+}
+
+void getFileSansBangLine(const QString &path, QByteArray &output)
+{
+ QFile f(path);
+ if (!f.open(QFile::ReadOnly | QFile::Text))
+ return;
+ output = f.readAll();
+ if (output.startsWith("#!"))//Remove first line in this case (except \n, to avoid disturbing line count)
+ output.remove(0, output.indexOf('\n'));
+}
+
+static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory)
+{
+ QDir dir(directory+"/dummydata", "*.qml");
+ QStringList list = dir.entryList();
+ for (int i = 0; i < list.size(); ++i) {
+ QString qml = list.at(i);
+ QFile f(dir.filePath(qml));
+ f.open(QIODevice::ReadOnly);
+ QByteArray data = f.readAll();
+ QQmlComponent comp(&engine);
+ comp.setData(data, QUrl());
+ QObject *dummyData = comp.create();
+
+ if (comp.isError()) {
+ QList<QQmlError> errors = comp.errors();
+ foreach (const QQmlError &error, errors)
+ qWarning() << error;
+ }
+
+ if (dummyData && !quietMode) {
+ qWarning() << QObject::tr("qml: Loaded dummy data:") << dir.filePath(qml);
+ qml.truncate(qml.length()-4);
+ engine.rootContext()->setContextProperty(qml, dummyData);
+ dummyData->setParent(&engine);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ getAppFlags(argc, argv);
+ QCoreApplication *app;
+ if (useCoreApp)
+ app = new QCoreApplication(argc, argv);
+#ifdef QT_WIDGETS_LIB
+ else if (useWidgetApp)
+ app = new QApplication(argc, argv);
+#endif
+ else
+ app = new LoaderApplication(argc, argv);
+
+ app->setApplicationName("Qml Runtime");
+ app->setOrganizationName("Qt Project");
+ app->setOrganizationDomain("qt-project.org");
+
+ qmlRegisterType<Config>("QmlRuntime.Config", VERSION_MAJ, VERSION_MIN, "Configuration");
+ qmlRegisterType<PartialScene>("QmlRuntime.Config", VERSION_MAJ, VERSION_MIN, "PartialScene");
+ QQmlApplicationEngine e;
+ QStringList files;
+ QString confFile;
+ QString translationFile;
+ QString dummyDir;
+
+ //Handle main arguments
+ QStringList argList = app->arguments();
+ for (int i = 0; i < argList.count(); i++) {
+ const QString &arg = argList[i];
+ if (arg == QLatin1String("-quiet"))
+ quietMode = true;
+ else if (arg == QLatin1String("-v") || arg == QLatin1String("-version"))
+ printVersion();
+ else if (arg == QLatin1String("-h") || arg == QLatin1String("-help"))
+ printUsage();
+ else if (arg == QLatin1String("--"))
+ break;
+ else if (arg == QLatin1String("-slow-animations"))
+ QUnifiedTimer::instance()->setSlowModeEnabled(true);
+ else if (arg == QLatin1String("-fixed-animations"))
+ QUnifiedTimer::instance()->setConsistentTiming(true);
+ else if (arg == QLatin1String("-I")) {
+ if (i+1 == argList.count())
+ continue;//Invalid usage, but just ignore it
+ e.addImportPath(argList[i+1]);
+ i++;
+ } else if (arg == QLatin1String("-f")) {
+ if (i+1 == argList.count())
+ continue;//Invalid usage, but just ignore it
+ files << argList[i+1];
+ i++;
+ } else if (arg == QLatin1String("-config")){
+ if (i+1 == argList.count())
+ continue;//Invalid usage, but just ignore it
+ confFile = argList[i+1];
+ i++;
+ } else if (arg == QLatin1String("-translation")){
+ if (i+1 == argList.count())
+ continue;//Invalid usage, but just ignore it
+ translationFile = argList[i+1];
+ i++;
+ } else if (arg == QLatin1String("-dummy-data")){
+ if (i+1 == argList.count())
+ continue;//Invalid usage, but just ignore it
+ dummyDir = argList[i+1];
+ i++;
+ } else {
+ //If it ends in .qml, treat it as a file. Else ignore it
+ if (arg.endsWith(".qml"))
+ files << arg;
+ }
+ }
+
+#ifndef QT_NO_TRANSLATION
+ //qt_ translations loaded by QQmlApplicationEngine
+ QTranslator qmlTranslator;
+ QString sysLocale = QLocale::system().name();
+ if (qmlTranslator.load(QLatin1String("qml_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ app->installTranslator(&qmlTranslator);
+
+ if (!translationFile.isEmpty()) { //Note: installed before QQmlApplicationEngine's automatic translation loading
+ QTranslator translator;
+
+ if (translator.load(translationFile)) {
+ app->installTranslator(&translator);
+ } else {
+ if (!quietMode)
+ qWarning() << "qml: Could not load the translation file" << translationFile;
+ }
+ }
+#else
+ if (!translationFile.isEmpty() && !quietMode)
+ qWarning() << "qml: Translation file specified, but Qt built without translation support.";
+#endif
+
+ if (quietMode)
+ qInstallMessageHandler(quietMessageHandler);
+
+ if (files.count() <= 0) {
+ if (!quietMode)
+ qCritical() << QObject::tr("qml: No files specified. Terminating.");
+ exit(1);
+ }
+
+ qae = &e;
+ loadConf(confFile, quietMode);
+
+ //Load files
+ LoadWatcher lw(&e, files.count());
+
+ foreach (const QString &path, files) {
+ //QUrl::fromUserInput doesn't treat no scheme as relative file paths
+ QRegularExpression urlRe("[[:word:]]+://.*");
+ if (urlRe.match(path).hasMatch()) { //Treat as a URL
+ QUrl url = QUrl::fromUserInput(path);
+ if (!quietMode)
+ qDebug() << QObject::tr("qml: loading ") << url;
+ e.load(url);
+ } else { //Local file path
+ if (!quietMode) {
+ qDebug() << QObject::tr("qml: loading ") << path;
+ QByteArray strippedFile;
+ getFileSansBangLine(path, strippedFile);
+ if (strippedFile.isEmpty())
+ // If there's an error opening the file, this will give us the right error message
+ e.load(path);
+ else
+ e.loadData(strippedFile, QUrl::fromLocalFile(path));
+ } else {
+ e.load(path);
+ }
+ }
+ }
+
+
+ if (!dummyDir.isEmpty() && QFileInfo (dummyDir).isDir())
+ loadDummyDataFiles(e, dummyDir);
+
+ return app->exec();
+}
+
+#include "main.moc"
diff --git a/tools/qml/qml.icns b/tools/qml/qml.icns
new file mode 100644
index 0000000000..c76051626a
--- /dev/null
+++ b/tools/qml/qml.icns
Binary files differ
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
new file mode 100644
index 0000000000..fd4021c340
--- /dev/null
+++ b/tools/qml/qml.pro
@@ -0,0 +1,14 @@
+QT += qml gui core-private
+qtHaveModule(widgets): QT += widgets
+
+HEADERS += conf.h
+SOURCES += main.cpp
+RESOURCES += qml.qrc
+
+mac {
+ OTHER_FILES += Info.plist
+ QMAKE_INFO_PLIST = Info.plist
+ ICON = qml.icns
+}
+
+load(qt_tool)
diff --git a/tools/qml/qml.qrc b/tools/qml/qml.qrc
new file mode 100644
index 0000000000..1f0ffdace2
--- /dev/null
+++ b/tools/qml/qml.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="qt-project.org/QmlRuntime">
+ <file>conf/configuration.qml</file>
+ <file>conf/qtquick.qml</file>
+ </qresource>
+</RCC>
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 4337db1689..6939ce92e2 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -58,6 +58,7 @@
#include <QtCore/private/qmetaobject_p.h>
#include <iostream>
+#include <algorithm>
#include "qmlstreamwriter.h"
@@ -139,6 +140,9 @@ public:
*/
static QHash<QByteArray, QSet<const QQmlType *> > qmlTypesByCppName;
+// No different versioning possible for a composite type.
+static QMap<QString, const QQmlType * > qmlTypesByCompositeName;
+
static QHash<QByteArray, QByteArray> cppToId;
/* Takes a C++ type name, such as Qt::LayoutDirection or QString and
@@ -190,8 +194,9 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
if (ty->isExtendedType())
extensions[ty->typeName()].insert(ty->metaObject()->className());
collectReachableMetaObjects(ty, &metas);
+ } else {
+ qmlTypesByCompositeName[ty->elementName()] = ty;
}
- // TODO actually handle composite types
}
// Adjust exports of the base object if there are extensions.
@@ -249,7 +254,16 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
if (ty->isSingleton()) {
QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo();
+ if (!siinfo) {
+ qWarning() << "Internal error, " << tyName
+ << "(" << QString::fromUtf8(ty->typeName()) << ")"
+ << " is singleton, but has no singletonInstanceInfo";
+ continue;
+ }
if (siinfo->qobjectCallback) {
+ if (verbose)
+ qDebug() << "Trying to get singleton for " << tyName
+ << " (" << siinfo->typeName << ")";
siinfo->init(engine);
collectReachableMetaObjects(object, &metas);
object = siinfo->qobjectApi(engine);
@@ -258,15 +272,22 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
continue; // we don't handle QJSValue singleton types.
}
} else {
+ if (verbose)
+ qDebug() << "Trying to create object " << tyName
+ << " (" << QString::fromUtf8(ty->typeName()) << ")";
object = ty->create();
}
inObjectInstantiation.clear();
- if (object)
+ if (object) {
+ if (verbose)
+ qDebug() << "Got " << tyName
+ << " (" << QString::fromUtf8(ty->typeName()) << ")";
collectReachableMetaObjects(object, &metas);
- else
+ } else {
qWarning() << "Could not create" << tyName;
+ }
}
}
@@ -287,6 +308,135 @@ public:
relocatableModuleUri = uri;
}
+ const QString getExportString(QString qmlTyName, int majorVersion, int minorVersion)
+ {
+ if (qmlTyName.startsWith(relocatableModuleUri + QLatin1Char('/'))) {
+ qmlTyName.remove(0, relocatableModuleUri.size() + 1);
+ }
+ if (qmlTyName.startsWith("./")) {
+ qmlTyName.remove(0, 2);
+ }
+ if (qmlTyName.startsWith("/")) {
+ qmlTyName.remove(0, 1);
+ }
+ const QString exportString = enquote(
+ QString("%1 %2.%3").arg(
+ qmlTyName,
+ QString::number(majorVersion),
+ QString::number(minorVersion)));
+ return exportString;
+ }
+
+ void writeMetaContent(const QMetaObject *meta)
+ {
+ QSet<QString> implicitSignals;
+ for (int index = meta->propertyOffset(); index < meta->propertyCount(); ++index) {
+ const QMetaProperty &property = meta->property(index);
+ dump(property);
+ implicitSignals.insert(QString("%1Changed").arg(QString::fromUtf8(property.name())));
+ }
+
+ if (meta == &QObject::staticMetaObject) {
+ // for QObject, hide deleteLater() and onDestroyed
+ for (int index = meta->methodOffset(); index < meta->methodCount(); ++index) {
+ QMetaMethod method = meta->method(index);
+ QByteArray signature = method.methodSignature();
+ if (signature == QByteArrayLiteral("destroyed(QObject*)")
+ || signature == QByteArrayLiteral("destroyed()")
+ || signature == QByteArrayLiteral("deleteLater()"))
+ continue;
+ dump(method, implicitSignals);
+ }
+
+ // and add toString(), destroy() and destroy(int)
+ qml->writeStartObject(QLatin1String("Method"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("toString")));
+ qml->writeEndObject();
+ qml->writeStartObject(QLatin1String("Method"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
+ qml->writeEndObject();
+ qml->writeStartObject(QLatin1String("Method"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
+ qml->writeStartObject(QLatin1String("Parameter"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("delay")));
+ qml->writeScriptBinding(QLatin1String("type"), enquote(QLatin1String("int")));
+ qml->writeEndObject();
+ qml->writeEndObject();
+ } else {
+ for (int index = meta->methodOffset(); index < meta->methodCount(); ++index)
+ dump(meta->method(index), implicitSignals);
+ }
+ }
+
+ QString getPrototypeNameForCompositeType(const QMetaObject *metaObject, QSet<QByteArray> &defaultReachableNames)
+ {
+ QString prototypeName;
+ if (!defaultReachableNames.contains(metaObject->className())) {
+ const QMetaObject *superMetaObject = metaObject->superClass();
+ if (!superMetaObject)
+ prototypeName = "QObject";
+ else
+ prototypeName = getPrototypeNameForCompositeType(superMetaObject, defaultReachableNames);
+ } else {
+ prototypeName = convertToId(metaObject->className());
+ }
+ return prototypeName;
+ }
+
+ void dumpComposite(QQmlEngine *engine, const QQmlType *compositeType, QSet<QByteArray> &defaultReachableNames)
+ {
+ QQmlComponent e(engine, compositeType->sourceUrl());
+ QObject *object = e.create();
+
+ if (!object)
+ return;
+
+ qml->writeStartObject("Component");
+
+ const QMetaObject *mainMeta = object->metaObject();
+
+ // Get C++ base class name for the composite type
+ QString prototypeName = getPrototypeNameForCompositeType(mainMeta, defaultReachableNames);
+ qml->writeScriptBinding(QLatin1String("prototype"), enquote(prototypeName));
+
+ QString qmlTyName = compositeType->qmlTypeName();
+ // name should be unique
+ qml->writeScriptBinding(QLatin1String("name"), enquote(qmlTyName));
+ const QString exportString = getExportString(qmlTyName, compositeType->majorVersion(), compositeType->minorVersion());
+ qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString);
+ qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType->minorVersion()));
+
+ for (int index = mainMeta->classInfoCount() - 1 ; index >= 0 ; --index) {
+ QMetaClassInfo classInfo = mainMeta->classInfo(index);
+ if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
+ qml->writeScriptBinding(QLatin1String("defaultProperty"), enquote(QLatin1String(classInfo.value())));
+ break;
+ }
+ }
+
+ QSet<const QMetaObject *> metas;
+ QSet<const QMetaObject *> candidatesComposite;
+ collectReachableMetaObjects(mainMeta, &candidatesComposite);
+
+ // Also eliminate meta objects with the same classname.
+ // This is required because extended objects seem not to share
+ // a single meta object instance.
+ foreach (const QMetaObject *mo, candidatesComposite) {
+ if (!defaultReachableNames.contains(mo->className()))
+ metas.insert(mo);
+ }
+
+ // put the metaobjects into a map so they are always dumped in the same order
+ QMap<QString, const QMetaObject *> nameToMeta;
+ foreach (const QMetaObject *meta, metas)
+ nameToMeta.insert(convertToId(meta), meta);
+
+ foreach (const QMetaObject *meta, nameToMeta)
+ writeMetaContent(meta);
+
+ qml->writeEndObject();
+ }
+
void dump(const QMetaObject *meta)
{
qml->writeStartObject("Component");
@@ -310,27 +460,13 @@ public:
QHash<QString, const QQmlType *> exports;
foreach (const QQmlType *qmlTy, qmlTypes) {
- QString qmlTyName = qmlTy->qmlTypeName();
- if (qmlTyName.startsWith(relocatableModuleUri + QLatin1Char('/'))) {
- qmlTyName.remove(0, relocatableModuleUri.size() + 1);
- }
- if (qmlTyName.startsWith("./")) {
- qmlTyName.remove(0, 2);
- }
- if (qmlTyName.startsWith("/")) {
- qmlTyName.remove(0, 1);
- }
- const QString exportString = enquote(
- QString("%1 %2.%3").arg(
- qmlTyName,
- QString::number(qmlTy->majorVersion()),
- QString::number(qmlTy->minorVersion())));
+ const QString exportString = getExportString(qmlTy->qmlTypeName(), qmlTy->majorVersion(), qmlTy->minorVersion());
exports.insert(exportString, qmlTy);
}
// ensure exports are sorted and don't change order when the plugin is dumped again
QStringList exportStrings = exports.keys();
- qSort(exportStrings);
+ std::sort(exportStrings.begin(), exportStrings.end());
qml->writeArrayBinding(QLatin1String("exports"), exportStrings);
// write meta object revisions
@@ -354,43 +490,7 @@ public:
for (int index = meta->enumeratorOffset(); index < meta->enumeratorCount(); ++index)
dump(meta->enumerator(index));
- QSet<QString> implicitSignals;
- for (int index = meta->propertyOffset(); index < meta->propertyCount(); ++index) {
- const QMetaProperty &property = meta->property(index);
- dump(property);
- implicitSignals.insert(QString("%1Changed").arg(QString::fromUtf8(property.name())));
- }
-
- if (meta == &QObject::staticMetaObject) {
- // for QObject, hide deleteLater() and onDestroyed
- for (int index = meta->methodOffset(); index < meta->methodCount(); ++index) {
- QMetaMethod method = meta->method(index);
- QByteArray signature = method.methodSignature();
- if (signature == QByteArrayLiteral("destroyed(QObject*)")
- || signature == QByteArrayLiteral("destroyed()")
- || signature == QByteArrayLiteral("deleteLater()"))
- continue;
- dump(method, implicitSignals);
- }
-
- // and add toString(), destroy() and destroy(int)
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("toString")));
- qml->writeEndObject();
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
- qml->writeEndObject();
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
- qml->writeStartObject(QLatin1String("Parameter"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("delay")));
- qml->writeScriptBinding(QLatin1String("type"), enquote(QLatin1String("int")));
- qml->writeEndObject();
- qml->writeEndObject();
- } else {
- for (int index = meta->methodOffset(); index < meta->methodCount(); ++index)
- dump(meta->method(index), implicitSignals);
- }
+ writeMetaContent(meta);
qml->writeEndObject();
}
@@ -461,7 +561,7 @@ private:
void dump(const QMetaMethod &meth, const QSet<QString> &implicitSignals)
{
if (meth.methodType() == QMetaMethod::Signal) {
- if (meth.access() != QMetaMethod::Protected)
+ if (meth.access() != QMetaMethod::Public)
return; // nothing to do.
} else if (meth.access() != QMetaMethod::Public) {
return; // nothing to do.
@@ -543,7 +643,7 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
qWarning() << qPrintable(QString(
- "Usage: %1 [-v] [-noinstantiate] [-[non]relocatable] module.uri version [module/import/path]\n"
+ "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] module.uri version [module/import/path]\n"
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
" %1 [-v] -builtins\n"
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
@@ -570,7 +670,17 @@ int main(int argc, char *argv[])
#endif
// don't require a window manager even though we're a QGuiApplication
- qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("minimal"));
+ bool requireWindowManager = false;
+ for (int index = 1; index < argc; ++index) {
+ if (QString::fromLocal8Bit(argv[index]) == "--defaultplatform"
+ || QString::fromLocal8Bit(argv[index]) == "-defaultplatform") {
+ requireWindowManager = true;
+ break;
+ }
+ }
+
+ if (!requireWindowManager)
+ qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("minimal"));
QGuiApplication app(argc, argv);
const QStringList args = app.arguments();
@@ -612,6 +722,9 @@ int main(int argc, char *argv[])
action = Builtins;
} else if (arg == QLatin1String("-v")) {
verbose = true;
+ } else if (arg == QLatin1String("--defaultplatform")
+ || arg == QLatin1String("-defaultplatform")) {
+ continue;
} else {
qWarning() << "Invalid argument: " << arg;
return EXIT_INVALIDARGUMENTS;
@@ -672,6 +785,7 @@ int main(int argc, char *argv[])
// add some otherwise unreachable QMetaObjects
defaultReachable.insert(&QQuickMouseEvent::staticMetaObject);
// QQuickKeyEvent, QQuickPinchEvent, QQuickDropEvent are not exported
+ QSet<QByteArray> defaultReachableNames;
// this will hold the meta objects we want to dump information of
QSet<const QMetaObject *> metas;
@@ -723,7 +837,6 @@ int main(int argc, char *argv[])
// Also eliminate meta objects with the same classname.
// This is required because extended objects seem not to share
// a single meta object instance.
- QSet<QByteArray> defaultReachableNames;
foreach (const QMetaObject *mo, defaultReachable)
defaultReachableNames.insert(QByteArray(mo->className()));
foreach (const QMetaObject *mo, candidates) {
@@ -746,8 +859,9 @@ int main(int argc, char *argv[])
"// This file describes the plugin-supplied types contained in the library.\n"
"// It is used for QML tooling purposes only.\n"
"//\n"
- "// This file was auto-generated with the command '%1'.\n"
- "\n").arg(args.join(QLatin1String(" "))));
+ "// This file was auto-generated by:\n"
+ "// '%1 %2'\n"
+ "\n").arg(QFileInfo(args.at(0)).fileName()).arg(QStringList(args.mid(1)).join(QLatin1String(" "))));
qml.writeStartObject("Module");
// put the metaobjects into a map so they are always dumped in the same order
@@ -761,6 +875,8 @@ int main(int argc, char *argv[])
foreach (const QMetaObject *meta, nameToMeta) {
dumper.dump(meta);
}
+ foreach (const QQmlType *compositeType, qmlTypesByCompositeName)
+ dumper.dumpComposite(&engine, compositeType, defaultReachableNames);
// define QEasingCurve as an extension of QQmlEasingValueType, this way
// properties using the QEasingCurve type get useful type information.
diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp
index 5d387d6234..038d2177f9 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -47,6 +47,8 @@
#include <QFile>
#include <QXmlStreamReader>
+#include <algorithm>
+
namespace Constants {
const char TYPE_PAINTING_STR[] = "Painting";
const char TYPE_COMPILING_STR[] = "Compiling";
@@ -437,9 +439,9 @@ void QmlProfilerData::sortStartTimes()
itFrom--;
if (itTo->startTime <= itFrom->startTime)
- qSort(itFrom, itTo + 1, compareStartTimes);
+ std::sort(itFrom, itTo + 1, compareStartTimes);
else
- qSort(itFrom + 1, itTo + 1, compareStartTimes);
+ std::sort(itFrom + 1, itTo + 1, compareStartTimes);
// move to next block
itTo = itFrom;
diff --git a/tools/qmlprofiler/qpacketprotocol.cpp b/tools/qmlprofiler/qpacketprotocol.cpp
index b0cb289c10..e0fe08740d 100644
--- a/tools/qmlprofiler/qpacketprotocol.cpp
+++ b/tools/qmlprofiler/qpacketprotocol.cpp
@@ -288,6 +288,7 @@ void QPacketProtocol::send(const QPacket & p)
d->sendingPackets.append(sendSize);
qint32 sendSize32 = sendSize;
qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_UNUSED(writeBytes);
Q_ASSERT(writeBytes == sizeof(qint32));
writeBytes = d->dev->write(p.b);
Q_ASSERT(writeBytes == p.b.size());
diff --git a/tools/tools.pro b/tools/tools.pro
index 43b6c14022..ecca12d266 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
qtHaveModule(quick): SUBDIRS += qmlscene qmlplugindump
qtHaveModule(qmltest): SUBDIRS += qmltestrunner
SUBDIRS += \
+ qml \
qmlmin \
qmlprofiler \
qmlbundle \
diff --git a/tools/v4/main.cpp b/tools/v4/main.cpp
index a49c7093cf..3404de2c30 100644
--- a/tools/v4/main.cpp
+++ b/tools/v4/main.cpp
@@ -77,16 +77,16 @@ struct Print: FunctionObject
name = scope->engine->newString("print");
}
- static Value call(Managed *, CallData *callData)
+ static ReturnedValue call(Managed *, CallData *callData)
{
for (int i = 0; i < callData->argc; ++i) {
- QString s = callData->args[i].toQString();
+ QString s = callData->args[i].toQStringNoThrow();
if (i)
std::cout << ' ';
std::cout << qPrintable(s);
}
std::cout << std::endl;
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
static const ManagedVTable static_vtbl;
@@ -102,10 +102,10 @@ struct GC: public FunctionObject
vtbl = &static_vtbl;
name = scope->engine->newString("gc");
}
- static Value call(Managed *m, CallData *)
+ static ReturnedValue call(Managed *m, CallData *)
{
m->engine()->memoryManager->runGC();
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
static const ManagedVTable static_vtbl;
@@ -117,11 +117,13 @@ DEFINE_MANAGED_VTABLE(GC);
static void showException(QV4::ExecutionContext *ctx, const QV4::Exception &exception)
{
- QV4::ErrorObject *e = exception.value().asErrorObject();
+ QV4::Scope scope(ctx);
+ QV4::ScopedValue ex(scope, exception.value());
+ QV4::ErrorObject *e = ex->asErrorObject();
if (!e) {
- std::cerr << "Uncaught exception: " << qPrintable(exception.value().toString(ctx)->toQString()) << std::endl;
+ std::cerr << "Uncaught exception: " << qPrintable(ex->toString(ctx)->toQString()) << std::endl;
} else {
- std::cerr << "Uncaught exception: " << qPrintable(e->get(ctx->engine->newString(QStringLiteral("message")), 0).toString(ctx)->toQString()) << std::endl;
+ std::cerr << "Uncaught exception: " << qPrintable(QV4::Value::fromReturnedValue(e->get(ctx->engine->newString(QStringLiteral("message")), 0)).toString(ctx)->toQString()) << std::endl;
}
foreach (const QV4::ExecutionEngine::StackFrame &frame, exception.stackTrace()) {
@@ -187,6 +189,7 @@ int main(int argc, char *argv[])
QV4::ExecutionEngine vm(iSelFactory);
QV4::ExecutionContext *ctx = vm.rootContext;
+ QV4::Scope scope(ctx);
QV4::Object *globalObject = vm.globalObject;
QV4::Object *print = new (ctx->engine->memoryManager) builtins::Print(ctx);
@@ -204,10 +207,10 @@ int main(int argc, char *argv[])
QV4::Script script(ctx, code, fn);
script.parseAsBinding = runAsQml;
script.parse();
- QV4::Value result = script.run();
- if (!result.isUndefined()) {
+ QV4::ScopedValue result(scope, script.run());
+ if (!result->isUndefined()) {
if (! qgetenv("SHOW_EXIT_VALUE").isEmpty())
- std::cout << "exit value: " << qPrintable(result.toString(ctx)->toQString()) << std::endl;
+ std::cout << "exit value: " << qPrintable(result->toString(ctx)->toQString()) << std::endl;
}
} catch (QV4::Exception& ex) {
ex.accept(ctx);