/**************************************************************************** ** ** Copyright (C) 2023 David Xanatos (xanasoft.com) All rights reserved. ** Contact: XanatosDavid@gmil.com ** ** ** To use the V4ScriptTools in a commercial project, you must obtain ** an appropriate business use license. ** ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** ** ****************************************************************************/ #include "stdafx.h" #include "JSEngineExt.h" #include #include #include #include #include #include #include static QMutex g_engineMutex; static QMap g_engineMap; CJSEngineExt* CJSEngineExt::getEngineByHandle(void* handle) { QMutexLocker locker(&g_engineMutex); return g_engineMap.value(handle); } static QV4::ReturnedValue printCall(const QV4::FunctionObject* b, const QV4::Value* v, const QV4::Value* argv, int argc); static QV4::ReturnedValue debuggerCall(const QV4::FunctionObject* b, const QV4::Value* v, const QV4::Value* argv, int argc); //static QV4::ReturnedValue evalCall(const QV4::FunctionObject* b, const QV4::Value* v, const QV4::Value* argv, int argc); CJSEngineExt::CJSEngineExt(QObject* parent) : QJSEngine(parent) { QV4::Scope scope(handle()); // provide a print function to write to console scope.engine->globalObject->defineDefaultProperty(QStringLiteral("print"), printCall); // provide ability to invoke the debugger scope.engine->globalObject->defineDefaultProperty(QStringLiteral("_debugger"), debuggerCall); // overwrite the eval function with our own copy which traces the scripts //scope.engine->globalObject->defineDefaultProperty(QStringLiteral("eval"), evalCall); QMutexLocker locker(&g_engineMutex); g_engineMap.insert(handle(), this); } CJSEngineExt::~CJSEngineExt() { QMutexLocker locker(&g_engineMutex); g_engineMap.remove(handle()); } QJSValue CJSEngineExt::evaluateScript(const QString& program, const QString& fileName, int lineNumber) { QJSValue ret = QJSEngine::evaluate(program, trackScript(program, fileName, lineNumber), lineNumber); emit evaluateFinished(ret); return ret; } QString CJSEngineExt::trackScript(const QString& program, const QString& fileName, int lineNumber) { QString Name = QUrl(fileName).fileName(); QString FileName = Name; for (int i = 0; m_ScriptIDs.contains(FileName.toLower());) FileName = Name + " (" + QString::number(++i) + ")"; m_ScriptIDs.insert(FileName.toLower(), m_Scripts.count()); m_Scripts.append(SScript{ FileName, lineNumber, program }); return FileName; } QV4::ReturnedValue printCall(const QV4::FunctionObject* b, const QV4::Value* v, const QV4::Value* argv, int argc) { QV4::Scope scope(b); QV4::ExecutionEngine* v4 = scope.engine; QString Result; for (int i = 0; i < argc; i++) { if (i > 0) Result.append(" "); Result.append(argv[i].toQStringNoThrow()); } QMutexLocker locker(&g_engineMutex); emit g_engineMap.value(v4)->printTrace(Result); return QV4::Encode::undefined(); } QV4::ReturnedValue debuggerCall(const QV4::FunctionObject* b, const QV4::Value* v, const QV4::Value* argv, int argc) { QV4::Scope scope(b); QV4::ExecutionEngine* v4 = scope.engine; QMutexLocker locker(&g_engineMutex); emit g_engineMap.value(v4)->invokeDebugger(); return QV4::Encode::undefined(); } //QV4::ReturnedValue evalCall(const QV4::FunctionObject* b, const QV4::Value* v, const QV4::Value* argv, int argc) //{ // // not implemented // // return QV4::Encode::undefined(); //}