Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qv4script.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qv4script_p.h"
5#include <private/qv4mm_p.h>
6#include "qv4function_p.h"
7#include "qv4context_p.h"
8#include "qv4debugging_p.h"
9#include "qv4scopedvalue_p.h"
10
11#include <private/qqmljsengine_p.h>
12#include <private/qqmljslexer_p.h>
13#include <private/qqmljsparser_p.h>
14#include <private/qqmljsast_p.h>
15#include <private/qqmlengine_p.h>
16#include <private/qqmlsourcecoordinate_p.h>
17#include <private/qv4profiling_p.h>
18#include <qv4runtimecodegen_p.h>
19
20#include <QtCore/QDebug>
21#include <QtCore/QString>
22#include <QScopedValueRollback>
23
24using namespace QV4;
25using namespace QQmlJS;
26
28 : line(1), column(0), context(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
29 , compilationUnit(compilationUnit), vmFunction(nullptr), parseAsBinding(true)
30{
31 if (qml)
32 qmlContext.set(v4, *qml);
33
34 parsed = true;
35
36 vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : nullptr;
37}
38
40{
41}
42
44{
45 if (parsed)
46 return;
47
48 parsed = true;
49
51 Scope valueScope(v4);
52
53 QV4::Compiler::Module module(v4->debugger() != nullptr);
54
55 if (sourceCode.startsWith(QLatin1String("function("))) {
56 static const int snippetLength = 70;
57 qWarning() << "Warning: Using function expressions as statements in scripts is not compliant with the ECMAScript specification:\n"
58 << (QStringView{sourceCode}.left(snippetLength) + QLatin1String("..."))
59 << "\nThis will throw a syntax error in Qt 5.12. If you want a function expression, surround it by parentheses.";
60 }
61
62 Engine ee, *engine = &ee;
63 Lexer lexer(engine);
65 Parser parser(engine);
66
67 const bool parsed = parser.parseProgram();
68
69 const auto diagnosticMessages = parser.diagnosticMessages();
70 for (const DiagnosticMessage &m : diagnosticMessages) {
71 if (m.isError()) {
72 valueScope.engine->throwSyntaxError(m.message, sourceFile, m.loc.startLine, m.loc.startColumn);
73 return;
74 } else {
75 qWarning() << sourceFile << ':' << m.loc.startLine << ':' << m.loc.startColumn
76 << ": warning: " << m.message;
77 }
78 }
79
80 if (parsed) {
81 using namespace AST;
82 Program *program = AST::cast<Program *>(parser.rootNode());
83 if (!program) {
84 // if parsing was successful, and we have no program, then
85 // we're done...:
86 return;
87 }
88
89 QV4::Compiler::JSUnitGenerator jsGenerator(&module);
90 RuntimeCodegen cg(v4, &jsGenerator, strictMode);
92 cg.setUseFastLookups(false);
94 if (v4->hasException)
95 return;
96
98 vmFunction = compilationUnit->linkToEngine(v4);
99 }
100
101 if (!vmFunction) {
102 // ### FIX file/line number
103 ScopedObject error(valueScope, v4->newSyntaxErrorObject(QStringLiteral("Syntax error")));
104 v4->throwError(error);
105 }
106}
107
109{
110 if (!parsed)
111 parse();
112 if (!vmFunction)
113 return Encode::undefined();
114
116 QV4::Scope valueScope(engine);
117
118 if (qmlContext.isUndefined()) {
119 QScopedValueRollback<Function*> savedGlobalCode(engine->globalCode, vmFunction);
120
121 return vmFunction->call(thisObject ? thisObject : engine->globalObject, nullptr, 0,
122 context);
123 } else {
124 Scoped<QmlContext> qml(valueScope, qmlContext.value());
125 return vmFunction->call(thisObject, nullptr, 0, qml);
126 }
127}
128
130{
131 if (!parsed)
132 parse();
133 return vmFunction;
134}
135
137 QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine,
138 Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, const QString &finalUrl,
139 const QString &source, QList<QQmlError> *reportedErrors,
140 QV4::Compiler::ContextType contextType)
141{
142 using namespace QV4::Compiler;
143 using namespace QQmlJS::AST;
144
145 Lexer lexer(jsEngine);
146 lexer.setCode(source, /*line*/1, /*qml mode*/false);
147 Parser parser(jsEngine);
148
149 parser.parseProgram();
150
151 QList<QQmlError> errors = QQmlEnginePrivate::qmlErrorFromDiagnostics(fileName, parser.diagnosticMessages());
152 if (!errors.isEmpty()) {
153 if (reportedErrors)
154 *reportedErrors << errors;
155 return nullptr;
156 }
157
158 Program *program = AST::cast<Program *>(parser.rootNode());
159 if (!program) {
160 // if parsing was successful, and we have no program, then
161 // we're done...:
162 return nullptr;
163 }
164
165 Codegen cg(unitGenerator, /*strict mode*/false);
166 cg.generateFromProgram(fileName, finalUrl, source, program, module, contextType);
167 if (cg.hasError()) {
168 if (reportedErrors) {
169 const auto v4Error = cg.error();
171 error.setUrl(cg.url());
172 error.setLine(qmlConvertSourceCoordinate<quint32, int>(v4Error.loc.startLine));
173 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(v4Error.loc.startColumn));
174 error.setDescription(v4Error.message);
175 reportedErrors->append(error);
176 }
177 return nullptr;
178 }
179
180 return cg.generateCompilationUnit(/*generate unit data*/false);
181}
182
184{
185 if (error)
186 error->clear();
187
189 const ExecutionEngine::DiskCacheOptions options = engine->diskCacheOptions();
190 if (const QQmlPrivate::CachedQmlUnit *cachedUnit
193 originalUrl,
197 &cacheError)
198 : nullptr) {
201 QV4::CompiledData::CompilationUnit(cachedUnit->qmlData, cachedUnit->aotCompiledFunctions));
202 return new QV4::Script(engine, qmlContext, jsUnit);
203 }
204
206 if (!f.open(QIODevice::ReadOnly)) {
207 if (error) {
209 *error = originalUrl.toString() + QString::fromUtf8(" was compiled ahead of time with an incompatible version of Qt and the original source code cannot be found. Please recompile");
210 else
211 *error = QString::fromUtf8("Error opening source file %1: %2").arg(originalUrl.toString()).arg(f.errorString());
212 }
213 return nullptr;
214 }
215
216 QByteArray data = f.readAll();
218
219 auto result = new QV4::Script(engine, qmlContext, /*parseAsBinding*/false, sourceCode, originalUrl.toString());
221 result->parse();
222 return result;
223}
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qfile.h:93
QJSValue globalObject() const
Returns this engine's Global Object.
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
void append(parameter_type t)
Definition qlist.h:441
static QList< QQmlError > qmlErrorFromDiagnostics(const QString &fileName, const QList< QQmlJS::DiagnosticMessage > &diagnosticMessages)
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
void setCode(const QString &code, int lineno, bool qmlMode=true, CodeContinuation codeContinuation=CodeContinuation::Reset)
static const QQmlPrivate::CachedQmlUnit * findCachedCompilationUnit(const QUrl &uri, CacheMode mode, CachedUnitLookupError *status)
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
\inmodule QtCore
Definition qurl.h:94
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
void setUseFastLookups(bool b)
void generateFromProgram(const QString &fileName, const QString &finalUrl, const QString &sourceCode, QQmlJS::AST::Program *ast, Module *module, ContextType contextType=ContextType::Global)
QQmlJS::DiagnosticMessage error() const
QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData=true)
static QQmlRefPointer< ExecutableCompilationUnit > create()
ReturnedValue value() const
void set(ExecutionEngine *engine, const Value &value)
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
static void * context
DBusConnection const char DBusError * error
#define qWarning
Definition qlogging.h:162
const GLfloat * m
GLfloat GLfloat f
GLuint program
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLchar * source
GLenum GLenum GLsizei void GLsizei void * column
GLuint64EXT * result
[6]
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
QObject::connect nullptr
QJSEngine engine
[0]
static constexpr ReturnedValue undefined()
QV4::Debugging::Debugger * debugger() const
ReturnedValue throwError(const Value &value)
Heap::Object * newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
ReturnedValue throwSyntaxError(const QString &message)
bool call(QObject *thisObject, void **a, const QMetaType *types, int argc, ExecutionContext *context)
ExecutionEngine * engine() const
ExecutionEngine * engine
Script(ExecutionContext *scope, QV4::Compiler::ContextType mode, const QString &sourceCode, const QString &source=QString(), int line=1, int column=0)
Definition qv4script_p.h:36
Function * function()
ReturnedValue run(const QV4::Value *thisObject=nullptr)
Function * vmFunction
Definition qv4script_p.h:60
QV4::Compiler::ContextType contextType
Definition qv4script_p.h:57
QV4::PersistentValue qmlContext
Definition qv4script_p.h:58
bool parseAsBinding
Definition qv4script_p.h:61
static Script * createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl, QString *error)
bool strictMode
Definition qv4script_p.h:54
QString sourceCode
Definition qv4script_p.h:52
ExecutionContext * context
Definition qv4script_p.h:53
bool inheritContext
Definition qv4script_p.h:55
void parse()
Definition qv4script.cpp:43
QString sourceFile
Definition qv4script_p.h:49
QQmlRefPointer< ExecutableCompilationUnit > compilationUnit
Definition qv4script_p.h:59
static QV4::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, QV4::Compiler::ContextType contextType=QV4::Compiler::ContextType::Global)