File indexing completed on 2025-01-05 05:23:44
0001 /* 0002 This file is part of the Okteta Kasten Framework, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2010, 2011, 2012 Alex Richardson <alex.richardson@gmx.de> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "scriptfileparser.hpp" 0010 0011 #include "scriptvalueconverter.hpp" 0012 #include "parserutils.hpp" 0013 #include "../datatypes/topleveldatainformation.hpp" 0014 #include "../datatypes/dummydatainformation.hpp" 0015 #include "../script/scriptengineinitializer.hpp" 0016 #include "../script/scriptlogger.hpp" 0017 0018 #include <QScriptEngine> 0019 0020 ScriptFileParser::ScriptFileParser(const QString& pluginName, const QString& absolutePath) 0021 : AbstractStructureParser(pluginName, absolutePath) 0022 { 0023 } 0024 0025 ScriptFileParser::~ScriptFileParser() = default; 0026 0027 QStringList ScriptFileParser::parseStructureNames() const 0028 { 0029 return {mPluginName}; 0030 } 0031 0032 QVector<TopLevelDataInformation*> ScriptFileParser::parseStructures() const 0033 { 0034 QVector<TopLevelDataInformation*> ret; 0035 0036 QScriptEngine* engine = ScriptEngineInitializer::newEngine(); 0037 auto* logger = new ScriptLogger(); 0038 0039 QScriptValue value = loadScriptValue(logger, engine); 0040 DataInformation* dataInf; 0041 if (!value.isValid()) { 0042 dataInf = new DummyDataInformation(nullptr, mPluginName); 0043 } else { 0044 dataInf = ScriptValueConverter::convert(value, mPluginName, logger); 0045 } 0046 0047 if (!dataInf) { 0048 dataInf = new DummyDataInformation(nullptr, mPluginName); 0049 } 0050 const QFileInfo fileInfo(mAbsolutePath); 0051 auto* top = new TopLevelDataInformation(dataInf, logger, engine, fileInfo); 0052 // handle default lock offset 0053 QScriptValue lockOffset = value.property(ParserStrings::PROPERTY_DEFAULT_LOCK_OFFSET()); 0054 if (lockOffset.isValid()) { 0055 ParsedNumber<quint64> offset = ParserUtils::uint64FromScriptValue(lockOffset); 0056 if (!offset.isValid) { 0057 dataInf->logError() << "Default lock offset is not a valid number:" << offset.string; 0058 } else { 0059 top->setDefaultLockOffset(offset.value); 0060 } 0061 } 0062 ret.append(top); 0063 return ret; 0064 } 0065 0066 QScriptValue ScriptFileParser::loadScriptValue(ScriptLogger* logger, QScriptEngine* engine) const 0067 { 0068 QFile scriptFile(mAbsolutePath); 0069 if (!scriptFile.open(QIODevice::ReadOnly)) { 0070 logger->error() << "Could not open file " << mAbsolutePath; 0071 return {}; 0072 } 0073 0074 QTextStream stream(&scriptFile); 0075 QString contents = stream.readAll(); 0076 scriptFile.close(); 0077 engine->evaluate(contents, mAbsolutePath); 0078 if (engine->hasUncaughtException()) { 0079 // check if it was a syntax error: 0080 QScriptSyntaxCheckResult syntaxError = QScriptEngine::checkSyntax(contents); 0081 if (syntaxError.state() == QScriptSyntaxCheckResult::Error) { 0082 // give a detailed syntax error message 0083 logger->error() << "Syntax error in script: " << syntaxError.errorMessage(); 0084 logger->error() << "Line number: " << syntaxError.errorLineNumber() 0085 << "Column:" << syntaxError.errorColumnNumber(); 0086 } else { 0087 // just print the generic exception message 0088 logger->error() << "Error evaluating script: " << engine->uncaughtException().toString(); 0089 logger->error() << "Line number: " << engine->uncaughtExceptionLineNumber(); 0090 logger->error() << "Backtrace: " << engine->uncaughtExceptionBacktrace(); 0091 } 0092 return {}; 0093 } 0094 QScriptValue obj = engine->globalObject(); 0095 QScriptValue initMethod = obj.property(QStringLiteral("init")); 0096 if (!initMethod.isFunction()) { 0097 logger->error() << "Script has no 'init' function! Cannot evaluate script!"; 0098 return {}; 0099 } 0100 0101 QScriptValue thisObj = engine->newObject(); 0102 QScriptValueList args; 0103 QScriptValue result = initMethod.call(thisObj, args); 0104 if (result.isError()) { 0105 logger->error() << "Exception occurred while calling init():" << result.toString(); 0106 return {}; 0107 } 0108 return result; 0109 }