1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "private/qv4object_p.h"
5#include "private/qv4runtime_p.h"
6#include "private/qv4functionobject_p.h"
7#include "private/qv4errorobject_p.h"
8#include "private/qv4globalobject_p.h"
9#include "private/qv4codegen_p.h"
10#include "private/qv4objectproto_p.h"
11#include "private/qv4mm_p.h"
12#include "private/qv4context_p.h"
13#include "private/qv4script_p.h"
14#include "private/qv4string_p.h"
15#include "private/qv4module_p.h"
16#include "private/qqmlbuiltinfunctions_p.h"
17
18#include <QtCore/QCoreApplication>
19#include <QtCore/QFile>
20#include <QtCore/QFileInfo>
21#include <QtCore/QDateTime>
22#include <QtCore/qcommandlineparser.h>
23#include <private/qqmljsengine_p.h>
24#include <private/qqmljslexer_p.h>
25#include <private/qqmljsparser_p.h>
26#include <private/qqmljsast_p.h>
27
28#include <iostream>
29
30static void showException(QV4::ExecutionContext *ctx, const QV4::Value &exception, const QV4::StackTrace &trace)
31{
32 QV4::Scope scope(ctx);
33 QV4::ScopedValue ex(scope, exception);
34 QV4::ErrorObject *e = ex->as<QV4::ErrorObject>();
35 if (!e) {
36 std::cerr << "Uncaught exception: " << qPrintable(ex->toQString()) << std::endl;
37 } else {
38 std::cerr << "Uncaught exception: " << qPrintable(e->toQStringNoThrow()) << std::endl;
39 }
40
41 for (const QV4::StackFrame &frame : trace) {
42 std::cerr << " at " << qPrintable(frame.function) << " (" << qPrintable(frame.source);
43 if (frame.line >= 0)
44 std::cerr << ':' << frame.line;
45 std::cerr << ')' << std::endl;
46 }
47}
48
49int main(int argc, char *argv[])
50{
51 QCoreApplication app(argc, argv);
52 QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
53
54 QCommandLineParser parser;
55 parser.addHelpOption();
56 parser.setApplicationDescription("Utility to execute scripts in QML's V4 engine");
57 parser.addVersionOption();
58 parser.addPositionalArgument(name: "files", description: "Files to execute.", syntax: "[files...]");
59
60
61 QCommandLineOption forceJit("jit", "Force JIT.");
62 parser.addOption(commandLineOption: forceJit);
63
64 QCommandLineOption forceInterpreter("interpret", "Force interpreter.");
65 parser.addOption(commandLineOption: forceInterpreter);
66
67 QCommandLineOption qml("qml", "Run as QML.");
68 parser.addOption(commandLineOption: qml);
69
70 QCommandLineOption module("module", "Run as Module.");
71 parser.addOption(commandLineOption: module);
72
73 QCommandLineOption cache("cache", "Use cache.");
74 parser.addOption(commandLineOption: cache);
75
76 parser.process(app);
77
78 bool jitEnabled = false;
79
80 if (parser.isSet(option: forceJit)) {
81 qputenv(varName: "QV4_JIT_CALL_THRESHOLD", value: QByteArray("0"));
82 jitEnabled = true;
83 }
84 if (parser.isSet(option: forceInterpreter)) {
85 qputenv(varName: "QV4_FORCE_INTERPRETER", value: QByteArray("1"));
86 if (jitEnabled) {
87 std::cerr << "You cannot use 'Force JIT' and 'Force Interpreter' at the same time.";
88 return EXIT_FAILURE;
89 }
90 }
91 const bool runAsQml = parser.isSet(option: qml);
92 const bool runAsModule = parser.isSet(option: module);
93 const bool useCache = parser.isSet(option: cache);
94 const QStringList args = parser.positionalArguments();
95
96 QV4::ExecutionEngine vm;
97
98 QV4::Scope scope(&vm);
99 QV4::ScopedContext ctx(scope, vm.rootContext());
100
101 QV4::GlobalExtensions::init(globalObject: vm.globalObject, extensions: QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
102
103 for (const QString &fn : args) {
104 QV4::ScopedValue result(scope);
105 if (runAsModule) {
106 if (auto module
107 = vm.loadModule(url: QUrl::fromLocalFile(localfile: QFileInfo(fn).absoluteFilePath()))) {
108 if (module->instantiate())
109 module->evaluate();
110 } else {
111 vm.throwError(QStringLiteral("Could not load module file"));
112 }
113 } else {
114 QFile file(fn);
115 if (!file.open(flags: QFile::ReadOnly)) {
116 std::cerr << "Error: cannot open file " << fn.toUtf8().constData() << std::endl;
117 return EXIT_FAILURE;
118 }
119 QScopedPointer<QV4::Script> script;
120 if (useCache && QFile::exists(fileName: fn + QLatin1Char('c'))) {
121 auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
122 QString error;
123 if (unit->loadFromDisk(url: QUrl::fromLocalFile(localfile: fn), sourceTimeStamp: QFileInfo(fn).lastModified(), errorString: &error)) {
124 script.reset(other: new QV4::Script(
125 &vm, nullptr, vm.insertCompilationUnit(unit: std::move(unit))));
126 } else {
127 std::cout << "Error loading" << qPrintable(fn) << "from disk cache:" << qPrintable(error) << std::endl;
128 }
129 }
130 if (!script) {
131 QByteArray ba = file.readAll();
132 const QString code = QString::fromUtf8(utf8: ba.constData(), size: ba.size());
133 file.close();
134
135 script.reset(other: new QV4::Script(ctx, QV4::Compiler::ContextType::Global, code, fn));
136 script->parseAsBinding = runAsQml;
137 script->parse();
138 }
139 if (!scope.hasException()) {
140 const auto unit = script->compilationUnit;
141 if (useCache && unit && !(unit->unitData()->flags & QV4::CompiledData::Unit::StaticData)) {
142 if (unit->unitData()->sourceTimeStamp == 0) {
143 const_cast<QV4::CompiledData::Unit*>(unit->unitData())->sourceTimeStamp = QFileInfo(fn).lastModified().toMSecsSinceEpoch();
144 }
145 QString saveError;
146 if (!unit->baseCompilationUnit()->saveToDisk(
147 unitUrl: QUrl::fromLocalFile(localfile: fn), errorString: &saveError)) {
148 std::cout << "Error saving JS cache file: " << qPrintable(saveError) << std::endl;
149 }
150 }
151// QElapsedTimer t; t.start();
152 result = script->run();
153// std::cout << t.elapsed() << " ms. elapsed" << std::endl;
154 }
155 }
156 if (scope.hasException()) {
157 QV4::StackTrace trace;
158 QV4::ScopedValue ex(scope, scope.engine->catchException(trace: &trace));
159 showException(ctx, exception: ex, trace);
160 return EXIT_FAILURE;
161 }
162 if (!result->isUndefined()) {
163 if (! qgetenv(varName: "SHOW_EXIT_VALUE").isEmpty())
164 std::cout << "exit value: " << qPrintable(result->toQString()) << std::endl;
165 }
166 }
167
168 return EXIT_SUCCESS;
169}
170

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/tools/qmljs/qmljs.cpp