diff options
Diffstat (limited to 'src/qml/compiler/qv4codegen_p.h')
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 467 |
1 files changed, 265 insertions, 202 deletions
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 958dd16816..3a27cb1487 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QV4CODEGEN_P_H #define QV4CODEGEN_P_H @@ -50,18 +14,20 @@ // We mean it. // -#include "private/qv4global_p.h" #include <private/qqmljsastvisitor_p.h> +#include <private/qqmljsengine_p.h> #include <private/qqmljsast_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <private/qv4compiler_p.h> #include <private/qv4compilercontext_p.h> #include <private/qv4util_p.h> #include <private/qv4bytecodegenerator_p.h> -#include <private/qv4stackframe_p.h> +#include <private/qv4calldata_p.h> -QT_BEGIN_NAMESPACE +#include <QtCore/qsharedpointer.h> +#include <stack> -using namespace QQmlJS; +QT_BEGIN_NAMESPACE namespace QV4 { @@ -79,26 +45,42 @@ struct ControlFlow; struct ControlFlowCatch; struct ControlFlowFinally; -class Q_QML_PRIVATE_EXPORT Codegen: protected QQmlJS::AST::Visitor +class Q_QML_COMPILER_EXPORT CodegenWarningInterface +{ +public: + virtual void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName, + QQmlJS::SourceLocation declarationLocation, + QQmlJS::SourceLocation accessLocation); + virtual ~CodegenWarningInterface() = default; +}; + +inline CodegenWarningInterface *defaultCodegenWarningInterface() +{ + static CodegenWarningInterface iface; + return &iface; +} + +class Q_QML_COMPILER_EXPORT Codegen: protected QQmlJS::AST::Visitor { protected: using BytecodeGenerator = QV4::Moth::BytecodeGenerator; using Instruction = QV4::Moth::Instruction; public: - Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict); - + Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict, + CodegenWarningInterface *iface = defaultCodegenWarningInterface(), + bool storeSourceLocations = false); void generateFromProgram(const QString &fileName, const QString &finalUrl, const QString &sourceCode, - AST::Program *ast, + QQmlJS::AST::Program *ast, Module *module, ContextType contextType = ContextType::Global); void generateFromModule(const QString &fileName, const QString &finalUrl, const QString &sourceCode, - AST::ESModule *ast, + QQmlJS::AST::ESModule *ast, Module *module); public: @@ -106,15 +88,15 @@ public: class VolatileMemoryLocations { friend VolatileMemoryLocationScanner; bool allVolatile = false; - QVector<QStringView> specificLocations; + QList<QStringView> specificLocations; public: - bool isVolatile(const QStringView &name) { + bool isVolatile(QStringView name) { if (allVolatile) return true; return specificLocations.contains(name); } - void add(const QStringRef &name) { if (!allVolatile) specificLocations.append(name); } + void add(QStringView name) { if (!allVolatile) specificLocations.append(name); } void setAllVolatile() { allVolatile = true; } }; class RValue { @@ -207,7 +189,11 @@ public: stackSlotIsLocalOrArgument(false), isVolatile(false), global(false), - qmlGlobal(false) + qmlGlobal(false), + throwsReferenceError(false), + subscriptLoadedForCall(false), + isOptional(false), + hasSavedCallBaseSlot(false) {} Reference(const Reference &) = default; @@ -254,13 +240,6 @@ public: r.stackSlotIsLocalOrArgument = isLocal; return r; } - static Reference fromArgument(Codegen *cg, int index, bool isVolatile) { - Reference r(cg, StackSlot); - r.theStackSlot = Moth::StackSlot::createRegister(index + sizeof(CallData)/sizeof(Value) - 1); - r.stackSlotIsLocalOrArgument = true; - r.isVolatile = isVolatile; - return r; - } static Reference fromScopedLocal(Codegen *cg, int index, int scope) { Reference r(cg, ScopedLocal); r.index = index; @@ -277,11 +256,20 @@ public: r.name = name; return r; } - static Reference fromMember(const Reference &baseRef, const QString &name) { + static Reference + fromMember(const Reference &baseRef, const QString &name, + QQmlJS::SourceLocation sourceLocation = QQmlJS::SourceLocation(), + bool isOptional = false, + std::vector<Moth::BytecodeGenerator::Jump> *optionalChainJumpsToPatch = nullptr) + { + Q_ASSERT(baseRef.isValid()); Reference r(baseRef.codegen, Member); r.propertyBase = baseRef.asRValue(); r.propertyNameIndex = r.codegen->registerString(name); r.requiresTDZCheck = baseRef.requiresTDZCheck; + r.sourceLocation = sourceLocation; + r.optionalChainJumpsToPatch = optionalChainJumpsToPatch; + r.isOptional = isOptional; return r; } static Reference fromSuperProperty(const Reference &property) { @@ -345,6 +333,14 @@ public: return theStackSlot; } + void tdzCheck() const + { + if (isAccumulator()) + tdzCheck(requiresTDZCheck, throwsReferenceError); + else if (isStackSlot()) + tdzCheckStackSlot(stackSlot(), requiresTDZCheck, throwsReferenceError); + } + union { Moth::StackSlot theStackSlot; QV4::ReturnedValue constant; @@ -358,7 +354,10 @@ public: }; struct { Moth::StackSlot elementBase; - RValue elementSubscript; + union { + RValue elementSubscript; + Moth::StackSlot element; + }; }; Moth::StackSlot property; // super property }; @@ -374,10 +373,21 @@ public: quint32 isVolatile:1; quint32 global:1; quint32 qmlGlobal:1; + quint32 throwsReferenceError:1; + quint32 subscriptLoadedForCall:1; + quint32 isOptional: 1; + quint32 hasSavedCallBaseSlot: 1; + QQmlJS::SourceLocation sourceLocation = QQmlJS::SourceLocation(); + std::vector<Moth::BytecodeGenerator::Jump> *optionalChainJumpsToPatch = nullptr; + int savedCallBaseSlot = -1; + int savedCallPropertyNameIndex = -1; private: void storeAccumulator() const; Reference doStoreOnStack(int tempIndex) const; + void tdzCheck(bool requiresCheck, bool throwsReferenceError) const; + void tdzCheckStackSlot( + Moth::StackSlot slot, bool requiresCheck, bool throwsReferenceError) const; }; struct RegisterScope { @@ -484,10 +494,10 @@ protected: } }; - void enterContext(AST::Node *node); + void enterContext(QQmlJS::AST::Node *node); int leaveContext(); public: - Context *enterBlock(AST::Node *node); + Context *enterBlock(QQmlJS::AST::Node *node); int leaveBlock() { return leaveContext(); } protected: void leaveLoop(); @@ -511,27 +521,42 @@ public: int registerString(const QString &name) { return jsUnitGenerator->registerString(name); } - int registerConstant(QV4::ReturnedValue v) { return jsUnitGenerator->registerConstant(v); } - int registerGetterLookup(int nameIndex) { return jsUnitGenerator->registerGetterLookup(nameIndex); } - int registerSetterLookup(int nameIndex) { return jsUnitGenerator->registerSetterLookup(nameIndex); } - int registerGlobalGetterLookup(int nameIndex) { return jsUnitGenerator->registerGlobalGetterLookup(nameIndex); } - int registerQmlContextPropertyGetterLookup(int nameIndex) { return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex); } + int registerConstant(QV4::ReturnedValue v) + { + return jsUnitGenerator->registerConstant(v); + } + int registerGetterLookup(int nameIndex, JSUnitGenerator::LookupMode mode) + { + return jsUnitGenerator->registerGetterLookup(nameIndex, mode); + } + int registerSetterLookup(int nameIndex) + { + return jsUnitGenerator->registerSetterLookup(nameIndex); + } + int registerGlobalGetterLookup(int nameIndex, JSUnitGenerator::LookupMode mode) + { + return jsUnitGenerator->registerGlobalGetterLookup(nameIndex, mode); + } + int registerQmlContextPropertyGetterLookup(int nameIndex, JSUnitGenerator::LookupMode mode) + { + return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex, mode); + } // Returns index in _module->functions - virtual int defineFunction(const QString &name, AST::Node *ast, - AST::FormalParameterList *formals, - AST::StatementList *body); + virtual int defineFunction(const QString &name, QQmlJS::AST::Node *ast, + QQmlJS::AST::FormalParameterList *formals, + QQmlJS::AST::StatementList *body); protected: - void statement(AST::Statement *ast); - void statement(AST::ExpressionNode *ast); - void condition(AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue, + void statement(QQmlJS::AST::Statement *ast); + void statement(QQmlJS::AST::ExpressionNode *ast); + void condition(QQmlJS::AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue, const BytecodeGenerator::Label *iffalse, bool trueBlockFollowsCondition); - inline Reference expression(AST::ExpressionNode *ast, const QString &name = QString()) + inline Reference expression(QQmlJS::AST::ExpressionNode *ast, const QString &name = QString()) { - if (!ast || hasError) + if (!ast || hasError()) return Reference(); pushExpr(name); @@ -539,160 +564,179 @@ protected: return popResult(); } - inline void accept(AST::Node *node) + inline void accept(QQmlJS::AST::Node *node) { - if (!hasError && node) + if (!hasError() && node) node->accept(this); } - void program(AST::Program *ast); - void statementList(AST::StatementList *ast); - void variableDeclaration(AST::PatternElement *ast); - void variableDeclarationList(AST::VariableDeclarationList *ast); + void program(QQmlJS::AST::Program *ast); + void statementList(QQmlJS::AST::StatementList *ast); + void variableDeclaration(QQmlJS::AST::PatternElement *ast); + void variableDeclarationList(QQmlJS::AST::VariableDeclarationList *ast); - 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); + Reference targetForPatternElement(QQmlJS::AST::PatternElement *p); + void initializeAndDestructureBindingElement(QQmlJS::AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false); + void destructurePropertyList(const Reference &object, QQmlJS::AST::PatternPropertyList *bindingList, bool isDefinition = false); + void destructureElementList(const Reference &array, QQmlJS::AST::PatternElementList *bindingList, bool isDefinition = false); + void destructurePattern(QQmlJS::AST::Pattern *p, const Reference &rhs); - Reference referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name); + Reference referenceForPropertyName(const Codegen::Reference &object, QQmlJS::AST::PropertyName *name); void emitReturn(const Reference &expr); // nodes - bool visit(AST::ArgumentList *ast) override; - bool visit(AST::CaseBlock *ast) override; - bool visit(AST::CaseClause *ast) override; - bool visit(AST::CaseClauses *ast) override; - bool visit(AST::Catch *ast) override; - bool visit(AST::DefaultClause *ast) override; - bool visit(AST::Elision *ast) override; - bool visit(AST::Finally *ast) override; - bool visit(AST::FormalParameterList *ast) override; - bool visit(AST::Program *ast) override; - bool visit(AST::StatementList *ast) override; - bool visit(AST::UiArrayMemberList *ast) override; - bool visit(AST::UiImport *ast) override; - bool visit(AST::UiHeaderItemList *ast) override; - bool visit(AST::UiPragma *ast) override; - bool visit(AST::UiObjectInitializer *ast) override; - bool visit(AST::UiObjectMemberList *ast) override; - bool visit(AST::UiParameterList *ast) override; - bool visit(AST::UiProgram *ast) override; - bool visit(AST::UiQualifiedId *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; - - bool visit(AST::ExportDeclaration *ast) override; + bool visit(QQmlJS::AST::ArgumentList *ast) override; + bool visit(QQmlJS::AST::CaseBlock *ast) override; + bool visit(QQmlJS::AST::CaseClause *ast) override; + bool visit(QQmlJS::AST::CaseClauses *ast) override; + bool visit(QQmlJS::AST::Catch *ast) override; + bool visit(QQmlJS::AST::DefaultClause *ast) override; + bool visit(QQmlJS::AST::Elision *ast) override; + bool visit(QQmlJS::AST::Finally *ast) override; + bool visit(QQmlJS::AST::FormalParameterList *ast) override; + bool visit(QQmlJS::AST::Program *ast) override; + bool visit(QQmlJS::AST::StatementList *ast) override; + bool visit(QQmlJS::AST::UiArrayMemberList *ast) override; + bool visit(QQmlJS::AST::UiImport *ast) override; + bool visit(QQmlJS::AST::UiHeaderItemList *ast) override; + bool visit(QQmlJS::AST::UiPragmaValueList *ast) override; + bool visit(QQmlJS::AST::UiPragma *ast) override; + bool visit(QQmlJS::AST::UiObjectInitializer *ast) override; + bool visit(QQmlJS::AST::UiObjectMemberList *ast) override; + bool visit(QQmlJS::AST::UiParameterList *ast) override; + bool visit(QQmlJS::AST::UiProgram *ast) override; + bool visit(QQmlJS::AST::UiQualifiedId *ast) override; + bool visit(QQmlJS::AST::VariableDeclarationList *ast) override; + + bool visit(QQmlJS::AST::PatternElement *ast) override; + bool visit(QQmlJS::AST::PatternElementList *ast) override; + bool visit(QQmlJS::AST::PatternProperty *ast) override; + bool visit(QQmlJS::AST::PatternPropertyList *ast) override; + + bool visit(QQmlJS::AST::ExportDeclaration *ast) override; + + bool visit(QQmlJS::AST::TypeAnnotation *ast) override; // expressions - bool visit(AST::Expression *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; - bool visit(AST::NewExpression *ast) override; - bool visit(AST::NewMemberExpression *ast) override; - bool visit(AST::NotExpression *ast) override; - bool visit(AST::NullExpression *ast) override; - bool visit(AST::NumericLiteral *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; - bool visit(AST::TypeOfExpression *ast) override; - bool visit(AST::UnaryMinusExpression *ast) override; - bool visit(AST::UnaryPlusExpression *ast) override; - bool visit(AST::VoidExpression *ast) override; - bool visit(AST::FunctionDeclaration *ast) override; - bool visit(AST::YieldExpression *ast) override; - bool visit(AST::ClassExpression *ast) override; - bool visit(AST::ClassDeclaration *ast) override; + bool visit(QQmlJS::AST::Expression *ast) override; + bool visit(QQmlJS::AST::ArrayPattern *ast) override; + bool visit(QQmlJS::AST::ArrayMemberExpression *ast) override; + bool visit(QQmlJS::AST::BinaryExpression *ast) override; + bool visit(QQmlJS::AST::CallExpression *ast) override; + void endVisit(QQmlJS::AST::CallExpression *ast) override; + bool visit(QQmlJS::AST::ConditionalExpression *ast) override; + bool visit(QQmlJS::AST::DeleteExpression *ast) override; + void endVisit(QQmlJS::AST::DeleteExpression *ast) override; + bool visit(QQmlJS::AST::FalseLiteral *ast) override; + bool visit(QQmlJS::AST::SuperLiteral *ast) override; + bool visit(QQmlJS::AST::FieldMemberExpression *ast) override; + void endVisit(QQmlJS::AST::FieldMemberExpression *ast) override; + bool visit(QQmlJS::AST::TaggedTemplate *ast) override; + bool visit(QQmlJS::AST::FunctionExpression *ast) override; + bool visit(QQmlJS::AST::IdentifierExpression *ast) override; + bool visit(QQmlJS::AST::NestedExpression *ast) override; + bool visit(QQmlJS::AST::NewExpression *ast) override; + bool visit(QQmlJS::AST::NewMemberExpression *ast) override; + bool visit(QQmlJS::AST::NotExpression *ast) override; + bool visit(QQmlJS::AST::NullExpression *ast) override; + bool visit(QQmlJS::AST::NumericLiteral *ast) override; + bool visit(QQmlJS::AST::ObjectPattern *ast) override; + bool visit(QQmlJS::AST::PostDecrementExpression *ast) override; + bool visit(QQmlJS::AST::PostIncrementExpression *ast) override; + bool visit(QQmlJS::AST::PreDecrementExpression *ast) override; + bool visit(QQmlJS::AST::PreIncrementExpression *ast) override; + bool visit(QQmlJS::AST::RegExpLiteral *ast) override; + bool visit(QQmlJS::AST::StringLiteral *ast) override; + bool visit(QQmlJS::AST::TemplateLiteral *ast) override; + bool visit(QQmlJS::AST::ThisExpression *ast) override; + bool visit(QQmlJS::AST::TildeExpression *ast) override; + bool visit(QQmlJS::AST::TrueLiteral *ast) override; + bool visit(QQmlJS::AST::TypeOfExpression *ast) override; + bool visit(QQmlJS::AST::UnaryMinusExpression *ast) override; + bool visit(QQmlJS::AST::UnaryPlusExpression *ast) override; + bool visit(QQmlJS::AST::VoidExpression *ast) override; + bool visit(QQmlJS::AST::FunctionDeclaration *ast) override; + bool visit(QQmlJS::AST::YieldExpression *ast) override; + bool visit(QQmlJS::AST::ClassExpression *ast) override; + bool visit(QQmlJS::AST::ClassDeclaration *ast) override; // statements - bool visit(AST::Block *ast) override; - bool visit(AST::BreakStatement *ast) override; - bool visit(AST::ContinueStatement *ast) override; - bool visit(AST::DebuggerStatement *ast) override; - bool visit(AST::DoWhileStatement *ast) override; - bool visit(AST::EmptyStatement *ast) override; - bool visit(AST::ExpressionStatement *ast) override; - bool visit(AST::ForEachStatement *ast) override; - bool visit(AST::ForStatement *ast) override; - bool visit(AST::IfStatement *ast) override; - bool visit(AST::LabelledStatement *ast) override; - bool visit(AST::ReturnStatement *ast) override; - bool visit(AST::SwitchStatement *ast) override; - bool visit(AST::ThrowStatement *ast) override; - bool visit(AST::TryStatement *ast) override; - bool visit(AST::VariableStatement *ast) override; - bool visit(AST::WhileStatement *ast) override; - bool visit(AST::WithStatement *ast) override; + bool visit(QQmlJS::AST::Block *ast) override; + bool visit(QQmlJS::AST::BreakStatement *ast) override; + bool visit(QQmlJS::AST::ContinueStatement *ast) override; + bool visit(QQmlJS::AST::DebuggerStatement *ast) override; + bool visit(QQmlJS::AST::DoWhileStatement *ast) override; + bool visit(QQmlJS::AST::EmptyStatement *ast) override; + bool visit(QQmlJS::AST::ExpressionStatement *ast) override; + bool visit(QQmlJS::AST::ForEachStatement *ast) override; + bool visit(QQmlJS::AST::ForStatement *ast) override; + bool visit(QQmlJS::AST::IfStatement *ast) override; + bool visit(QQmlJS::AST::LabelledStatement *ast) override; + bool visit(QQmlJS::AST::ReturnStatement *ast) override; + bool visit(QQmlJS::AST::SwitchStatement *ast) override; + bool visit(QQmlJS::AST::ThrowStatement *ast) override; + bool visit(QQmlJS::AST::TryStatement *ast) override; + bool visit(QQmlJS::AST::VariableStatement *ast) override; + bool visit(QQmlJS::AST::WhileStatement *ast) override; + bool visit(QQmlJS::AST::WithStatement *ast) override; // ui object members - bool visit(AST::UiArrayBinding *ast) override; - bool visit(AST::UiObjectBinding *ast) override; - bool visit(AST::UiObjectDefinition *ast) override; - bool visit(AST::UiPublicMember *ast) override; - bool visit(AST::UiScriptBinding *ast) override; - bool visit(AST::UiSourceElement *ast) override; - - bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, const AST::SourceLocation &loc); - virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail); - virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail); + bool visit(QQmlJS::AST::UiArrayBinding *ast) override; + bool visit(QQmlJS::AST::UiObjectBinding *ast) override; + bool visit(QQmlJS::AST::UiObjectDefinition *ast) override; + bool visit(QQmlJS::AST::UiPublicMember *ast) override; + bool visit(QQmlJS::AST::UiScriptBinding *ast) override; + bool visit(QQmlJS::AST::UiSourceElement *ast) override; + + bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, + const QQmlJS::SourceLocation &loc); + virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail); + virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail); void throwRecursionDepthError() override { - throwSyntaxError(AST::SourceLocation(), + throwSyntaxError(QQmlJS::SourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded")); } public: - QList<DiagnosticMessage> errors() const; -#ifndef V4_BOOTSTRAP - QList<QQmlError> qmlErrors() const; -#endif + enum ErrorType { + NoError, + SyntaxError, + ReferenceError + }; - Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right); + ErrorType errorType() const { return _errorType; } + bool hasError() const { return _errorType != NoError; } + QQmlJS::DiagnosticMessage error() const; + QUrl url() const; + + Reference binopHelper(QQmlJS::AST::BinaryExpression *ast, QSOperator::Op oper, Reference &left, + Reference &right); Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right); struct Arguments { int argc; int argv; bool hasSpread; }; - Arguments pushArgs(AST::ArgumentList *args); - void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject); + Arguments pushArgs(QQmlJS::AST::ArgumentList *args); + void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject, bool optional = false); - Arguments pushTemplateArgs(AST::TemplateLiteral *args); - bool handleTaggedTemplate(Reference base, AST::TaggedTemplate *ast); - void createTemplateObject(AST::TemplateLiteral *t); + Arguments pushTemplateArgs(QQmlJS::AST::TemplateLiteral *args); + bool handleTaggedTemplate(Reference base, QQmlJS::AST::TaggedTemplate *ast); + void createTemplateObject(QQmlJS::AST::TemplateLiteral *t); void setUseFastLookups(bool b) { useFastLookups = b; } - void handleTryCatch(AST::TryStatement *ast); - void handleTryFinally(AST::TryStatement *ast); + void handleTryCatch(QQmlJS::AST::TryStatement *ast); + void handleTryFinally(QQmlJS::AST::TryStatement *ast); - Reference referenceForName(const QString &name, bool lhs, const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation()); + Reference referenceForName( + const QString &name, bool lhs, + const QQmlJS::SourceLocation &accessLocation = QQmlJS::SourceLocation()); - QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(bool generateUnitData = true); - static QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading(); + QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit( + bool generateUnitData = true); + static QQmlRefPointer<QV4::CompiledData::CompilationUnit> compileModule( + bool debugMode, const QString &url, const QString &sourceCode, + const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics); Context *currentContext() const { return _context; } BytecodeGenerator *generator() const { return bytecodeGenerator; } @@ -751,7 +795,7 @@ protected: int _returnAddress; Context *_context; Context *_functionContext = nullptr; - AST::LabelledStatement *_labelledStatement; + QQmlJS::AST::LabelledStatement *_labelledStatement; QV4::Compiler::JSUnitGenerator *jsUnitGenerator; BytecodeGenerator *bytecodeGenerator = nullptr; Moth::BytecodeGenerator::Label *_returnLabel = nullptr; @@ -762,13 +806,24 @@ protected: bool inFormalParameterList = false; bool functionEndsWithReturn = false; bool _tailCallsAreAllowed = true; + bool storeSourceLocations = false; QSet<QString> m_globalNames; + struct OptionalChainState + { + QQmlJS::AST::Node *tailNodeOfChain = nullptr; + std::vector<Moth::BytecodeGenerator::Jump> jumpsToPatch; + bool actuallyHasOptionals = false; + }; + QSet<QQmlJS::AST::Node*> m_seenOptionalChainNodes; + std::stack<OptionalChainState> m_optionalChainsStates; + ControlFlow *controlFlow = nullptr; bool _fileNameIsUrl; - bool hasError; - QList<QQmlJS::DiagnosticMessage> _errors; + ErrorType _errorType = NoError; + QQmlJS::DiagnosticMessage _error; + CodegenWarningInterface *_interface; class TailCallBlocker { @@ -795,8 +850,16 @@ protected: }; private: - VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast); - void handleConstruct(const Reference &base, AST::ArgumentList *args); + Q_DISABLE_COPY(Codegen) + VolatileMemoryLocations scanVolatileMemoryLocations(QQmlJS::AST::Node *ast); + void handleConstruct(const Reference &base, QQmlJS::AST::ArgumentList *args); + void throwError(ErrorType errorType, const QQmlJS::SourceLocation &loc, + const QString &detail); + bool traverseOptionalChain(QQmlJS::AST::Node *node); + void optionalChainFinalizer(const Reference &expressionResult, bool tailOfChain, + bool isDeleteExpression = false); + Reference loadSubscriptForCall(const Reference &base); + void generateThrowException(const QString &type, const QString &text = QString()); }; } |