1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the V4VM module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "private/qv4object_p.h"
30#include "private/qv4runtime_p.h"
31#include "private/qv4functionobject_p.h"
32#include "private/qv4errorobject_p.h"
33#include "private/qv4globalobject_p.h"
34#include "private/qv4codegen_p.h"
35#include "private/qv4objectproto_p.h"
36#include "private/qv4mm_p.h"
37#include "private/qv4context_p.h"
38#include "private/qv4script_p.h"
39#include "private/qv4string_p.h"
40#include "private/qv4module_p.h"
41#include "private/qqmlbuiltinfunctions_p.h"
42
43#include <QtCore/QCoreApplication>
44#include <QtCore/QFile>
45#include <QtCore/QFileInfo>
46#include <QtCore/QDateTime>
47#include <private/qqmljsengine_p.h>
48#include <private/qqmljslexer_p.h>
49#include <private/qqmljsparser_p.h>
50#include <private/qqmljsast_p.h>
51
52#include <iostream>
53
54static void showException(QV4::ExecutionContext *ctx, const QV4::Value &exception, const QV4::StackTrace &trace)
55{
56 QV4::Scope scope(ctx);
57 QV4::ScopedValue ex(scope, exception);
58 QV4::ErrorObject *e = ex->as<QV4::ErrorObject>();
59 if (!e) {
60 std::cerr << "Uncaught exception: " << qPrintable(ex->toQString()) << std::endl;
61 } else {
62 std::cerr << "Uncaught exception: " << qPrintable(e->toQStringNoThrow()) << std::endl;
63 }
64
65 for (const QV4::StackFrame &frame : trace) {
66 std::cerr << " at " << qPrintable(frame.function) << " (" << qPrintable(frame.source);
67 if (frame.line >= 0)
68 std::cerr << ':' << frame.line;
69 std::cerr << ')' << std::endl;
70 }
71}
72
73int main(int argc, char *argv[])
74{
75 QCoreApplication app(argc, argv);
76 QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
77 QStringList args = app.arguments();
78 args.removeFirst();
79
80 bool runAsQml = false;
81 bool runAsModule = false;
82 bool cache = false;
83
84 if (!args.isEmpty()) {
85 if (args.constFirst() == QLatin1String("--jit")) {
86 qputenv(varName: "QV4_JIT_CALL_THRESHOLD", value: QByteArray("0"));
87 args.removeFirst();
88 }
89 if (args.constFirst() == QLatin1String("--interpret")) {
90 qputenv(varName: "QV4_FORCE_INTERPRETER", value: QByteArray("1"));
91 args.removeFirst();
92 }
93
94 if (args.constFirst() == QLatin1String("--qml")) {
95 runAsQml = true;
96 args.removeFirst();
97 }
98
99 if (args.constFirst() == QLatin1String("--module")) {
100 runAsModule = true;
101 args.removeFirst();
102 }
103
104 if (args.constFirst() == QLatin1String("--cache")) {
105 cache = true;
106 args.removeFirst();
107 }
108
109 if (args.constFirst() == QLatin1String("--help")) {
110 std::cerr << "Usage: qmljs [|--jit|--interpret|--qml] file..." << std::endl;
111 return EXIT_SUCCESS;
112 }
113 }
114
115 QV4::ExecutionEngine vm;
116
117 QV4::Scope scope(&vm);
118 QV4::ScopedContext ctx(scope, vm.rootContext());
119
120 QV4::GlobalExtensions::init(globalObject: vm.globalObject, extensions: QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
121
122 for (const QString &fn : qAsConst(t&: args)) {
123 QV4::ScopedValue result(scope);
124 if (runAsModule) {
125 auto moduleUnit = vm.loadModule(url: QUrl::fromLocalFile(localfile: QFileInfo(fn).absoluteFilePath()));
126 if (moduleUnit) {
127 if (moduleUnit->instantiate(engine: &vm))
128 moduleUnit->evaluate();
129 } else {
130 vm.throwError(QStringLiteral("Could not load module file"));
131 }
132 } else {
133 QFile file(fn);
134 if (!file.open(flags: QFile::ReadOnly)) {
135 std::cerr << "Error: cannot open file " << fn.toUtf8().constData() << std::endl;
136 return EXIT_FAILURE;
137 }
138 QScopedPointer<QV4::Script> script;
139 if (cache && QFile::exists(fileName: fn + QLatin1Char('c'))) {
140 QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
141 = QV4::ExecutableCompilationUnit::create();
142 QString error;
143 if (unit->loadFromDisk(url: QUrl::fromLocalFile(localfile: fn), sourceTimeStamp: QFileInfo(fn).lastModified(), errorString: &error)) {
144 script.reset(other: new QV4::Script(&vm, nullptr, unit));
145 } else {
146 std::cout << "Error loading" << qPrintable(fn) << "from disk cache:" << qPrintable(error) << std::endl;
147 }
148 }
149 if (!script) {
150 QByteArray ba = file.readAll();
151 const QString code = QString::fromUtf8(str: ba.constData(), size: ba.length());
152 file.close();
153
154 script.reset(other: new QV4::Script(ctx, QV4::Compiler::ContextType::Global, code, fn));
155 script->parseAsBinding = runAsQml;
156 script->parse();
157 }
158 if (!scope.engine->hasException) {
159 const auto unit = script->compilationUnit;
160 if (cache && unit && !(unit->unitData()->flags & QV4::CompiledData::Unit::StaticData)) {
161 if (unit->unitData()->sourceTimeStamp == 0) {
162 const_cast<QV4::CompiledData::Unit*>(unit->unitData())->sourceTimeStamp = QFileInfo(fn).lastModified().toMSecsSinceEpoch();
163 }
164 QString saveError;
165 if (!unit->saveToDisk(unitUrl: QUrl::fromLocalFile(localfile: fn), errorString: &saveError)) {
166 std::cout << "Error saving JS cache file: " << qPrintable(saveError) << std::endl;
167 }
168 }
169// QElapsedTimer t; t.start();
170 result = script->run();
171// std::cout << t.elapsed() << " ms. elapsed" << std::endl;
172 }
173 }
174 if (scope.engine->hasException) {
175 QV4::StackTrace trace;
176 QV4::ScopedValue ex(scope, scope.engine->catchException(trace: &trace));
177 showException(ctx, exception: ex, trace);
178 return EXIT_FAILURE;
179 }
180 if (!result->isUndefined()) {
181 if (! qgetenv(varName: "SHOW_EXIT_VALUE").isEmpty())
182 std::cout << "exit value: " << qPrintable(result->toQString()) << std::endl;
183 }
184 }
185
186 return EXIT_SUCCESS;
187}
188

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