diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index ef0fffeb4d..1c4c07dddd 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -84,7 +84,7 @@ void ConsoleScriptingInterface::time(QString labelName) { QString message = QString("%1: Timer started").arg(labelName); Q_ASSERT(engine); if (ScriptManager* scriptManager = engine()->manager()) { - scriptManager->scriptPrintedMessage(message); + scriptManager->scriptPrintedMessage(message, context()->currentFileName(), context()->currentLineNumber()); } } @@ -92,13 +92,13 @@ void ConsoleScriptingInterface::timeEnd(QString labelName) { Q_ASSERT(engine); if (ScriptManager* scriptManager = engine()->manager()) { if (!_timerDetails.contains(labelName)) { - scriptManager->scriptErrorMessage("No such label found " + labelName); + scriptManager->scriptErrorMessage("No such label found " + labelName, context()->currentFileName(), context()->currentLineNumber()); return; } if (_timerDetails.value(labelName).isNull()) { _timerDetails.remove(labelName); - scriptManager->scriptErrorMessage("Invalid start time for " + labelName); + scriptManager->scriptErrorMessage("Invalid start time for " + labelName, context()->currentFileName(), context()->currentLineNumber()); return; } QDateTime _startTime = _timerDetails.value(labelName); @@ -108,7 +108,7 @@ void ConsoleScriptingInterface::timeEnd(QString labelName) { QString message = QString("%1: %2ms").arg(labelName).arg(QString::number(diffInMS)); _timerDetails.remove(labelName); - scriptManager->scriptPrintedMessage(message); + scriptManager->scriptPrintedMessage(message, context()->currentFileName(), context()->currentLineNumber()); } } @@ -131,7 +131,7 @@ ScriptValue ConsoleScriptingInterface::assertion(ScriptContext* context, ScriptE assertionResult = QString("Assertion failed : %1").arg(message); } if (ScriptManager* scriptManager = engine->manager()) { - scriptManager->scriptErrorMessage(assertionResult); + scriptManager->scriptErrorMessage(assertionResult, context->currentFileName(), context->currentLineNumber()); } } return engine->nullValue(); @@ -143,7 +143,7 @@ void ConsoleScriptingInterface::trace() { if (ScriptManager* scriptManager = scriptEngine->manager()) { scriptManager->scriptPrintedMessage (QString(STACK_TRACE_FORMAT).arg(LINE_SEPARATOR, - scriptEngine->currentContext()->backtrace().join(LINE_SEPARATOR))); + scriptEngine->currentContext()->backtrace().join(LINE_SEPARATOR)), context()->currentFileName(), context()->currentLineNumber()); } } @@ -190,6 +190,6 @@ void ConsoleScriptingInterface::logGroupMessage(QString message, ScriptEngine* e } logMessage.append(message); if (ScriptManager* scriptManager = engine->manager()) { - scriptManager->scriptPrintedMessage(logMessage); + scriptManager->scriptPrintedMessage(logMessage, context()->currentFileName(), context()->currentLineNumber()); } } diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index 06752d57a7..ccdc917f0b 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -225,7 +225,12 @@ QString encodeEntityIdIntoEntityUrl(const QString& url, const QString& entityID) QString ScriptManager::logException(const ScriptValue& exception) { auto message = formatException(exception, _enableExtendedJSExceptions.get()); - scriptErrorMessage(message); + auto context = _engine->currentContext(); + if (context) { + scriptErrorMessage(message, context->currentFileName(), context->currentLineNumber()); + } else { + scriptErrorMessage(message, "", -1); + } return message; } @@ -330,6 +335,11 @@ ScriptManager::ScriptManager(Context context, const QString& scriptContents, con }); } + //Gather entity script messages for transmission when running server side. + if (_type == Type::ENTITY_SERVER) { + ; + } + if (!_areMetaTypesInitialized) { initMetaTypes(); } @@ -514,7 +524,7 @@ void ScriptManager::waitTillDoneRunning(bool shutdown) { } #endif - scriptInfoMessage("Script Engine has stopped:" + getFilename()); + scriptInfoMessage("Script Engine has stopped:" + getFilename(), "", -1); } } @@ -549,7 +559,7 @@ void ScriptManager::loadURL(const QUrl& scriptURL, bool reload) { // Check that script has a supported file extension if (!hasValidScriptSuffix(_fileNameString)) { - scriptErrorMessage("File extension of file: " + _fileNameString + " is not a currently supported script type"); + scriptErrorMessage("File extension of file: " + _fileNameString + " is not a currently supported script type", _fileNameString, -1); emit errorLoadingScript(_fileNameString); return; } @@ -559,7 +569,7 @@ void ScriptManager::loadURL(const QUrl& scriptURL, bool reload) { scriptCache->getScriptContents(url.toString(), [this](const QString& url, const QString& scriptContents, bool isURL, bool success, const QString&status) { qCDebug(scriptengine) << "loadURL" << url << status << QThread::currentThread(); if (!success) { - scriptErrorMessage("ERROR Loading file (" + status + "):" + url); + scriptErrorMessage("ERROR Loading file (" + status + "):" + url, url, -1); emit errorLoadingScript(_fileNameString); return; } @@ -570,40 +580,35 @@ void ScriptManager::loadURL(const QUrl& scriptURL, bool reload) { }, reload, maxRetries); } -void ScriptManager::scriptErrorMessage(const QString& message) { +void ScriptManager::scriptErrorMessage(const QString& message, const QString& fileName, int lineNumber) { qCCritical(scriptengine, "[%s] %s", qUtf8Printable(getFilename()), qUtf8Printable(message)); emit errorMessage(message, getFilename()); if (!currentEntityIdentifier.isInvalidID()) { - // TODO: add line number and proper file name - //if (engine() && engine()->currentContext() && engine()->currentContext()->) - emit errorEntityMessage(message, getFilename(), currentEntityIdentifier); + emit errorEntityMessage(message, fileName, lineNumber, currentEntityIdentifier); } } -void ScriptManager::scriptWarningMessage(const QString& message) { +void ScriptManager::scriptWarningMessage(const QString& message, const QString& fileName, int lineNumber) { qCWarning(scriptengine, "[%s] %s", qUtf8Printable(getFilename()), qUtf8Printable(message)); emit warningMessage(message, getFilename()); if (!currentEntityIdentifier.isInvalidID()) { - // TODO: add line number and proper file name - emit warningEntityMessage(message, getFilename(), currentEntityIdentifier); + emit warningEntityMessage(message, fileName, lineNumber, currentEntityIdentifier); } } -void ScriptManager::scriptInfoMessage(const QString& message) { +void ScriptManager::scriptInfoMessage(const QString& message, const QString& fileName, int lineNumber) { qCInfo(scriptengine, "[%s] %s", qUtf8Printable(getFilename()), qUtf8Printable(message)); emit infoMessage(message, getFilename()); if (!currentEntityIdentifier.isInvalidID()) { - // TODO: add line number and proper file name - emit infoEntityMessage(message, getFilename(), currentEntityIdentifier); + emit infoEntityMessage(message, fileName, lineNumber, currentEntityIdentifier); } } -void ScriptManager::scriptPrintedMessage(const QString& message) { +void ScriptManager::scriptPrintedMessage(const QString& message, const QString& fileName, int lineNumber) { qCDebug(scriptengine, "[%s] %s", qUtf8Printable(getFilename()), qUtf8Printable(message)); emit printedMessage(message, getFilename()); if (!currentEntityIdentifier.isInvalidID()) { - // TODO: add line number and proper file name - emit printedEntityMessage(message, getFilename(), currentEntityIdentifier); + emit printedEntityMessage(message, fileName, lineNumber, currentEntityIdentifier); } } @@ -929,7 +934,7 @@ void ScriptManager::run() { return; // bail early - avoid setting state in init(), as evaluate() will bail too } - scriptInfoMessage("Script Engine starting:" + getFilename()); + scriptInfoMessage("Script Engine starting:" + getFilename(), getFilename(), -1); if (!_isInitialized) { init(); @@ -1081,7 +1086,7 @@ void ScriptManager::run() { _engine->clearExceptions(); } } - scriptInfoMessage("Script Engine stopping:" + getFilename()); + scriptInfoMessage("Script Engine stopping:" + getFilename(), getFilename(), -1); stopAllTimers(); // make sure all our timers are stopped if the script is ending emit scriptEnding(); @@ -1156,7 +1161,7 @@ void ScriptManager::updateMemoryCost(const qint64& deltaSize) { void ScriptManager::timerFired() { if (isStopped()) { - scriptWarningMessage("Script.timerFired() while shutting down is ignored... parent script:" + getFilename()); + scriptWarningMessage("Script.timerFired() while shutting down is ignored... parent script:" + getFilename(), getFilename(), -1); return; // bail early } @@ -1223,7 +1228,14 @@ QTimer* ScriptManager::setupTimerWithInterval(const ScriptValue& function, int i QTimer* ScriptManager::setInterval(const ScriptValue& function, int intervalMS) { if (isStopped()) { - scriptWarningMessage("Script.setInterval() while shutting down is ignored... parent script:" + getFilename()); + int lineNumber = -1; + QString fileName = getFilename(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } + scriptWarningMessage("Script.setInterval() while shutting down is ignored... parent script:" + getFilename(), fileName, lineNumber); return NULL; // bail early } @@ -1232,7 +1244,14 @@ QTimer* ScriptManager::setInterval(const ScriptValue& function, int intervalMS) QTimer* ScriptManager::setTimeout(const ScriptValue& function, int timeoutMS) { if (isStopped()) { - scriptWarningMessage("Script.setTimeout() while shutting down is ignored... parent script:" + getFilename()); + int lineNumber = -1; + QString fileName = getFilename(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } + scriptWarningMessage("Script.setTimeout() while shutting down is ignored... parent script:" + getFilename(), fileName, lineNumber); return NULL; // bail early } @@ -1668,8 +1687,15 @@ void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& return; } if (isStopped()) { + int lineNumber = -1; + QString fileName = getFilename(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } scriptWarningMessage("Script.include() while shutting down is ignored... includeFiles:" - + includeFiles.join(",") + "parent script:" + getFilename()); + + includeFiles.join(",") + "parent script:" + getFilename(), fileName, lineNumber); return; // bail early } QList urls; @@ -1682,8 +1708,15 @@ void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file))); QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); if (!defaultScriptsLoc.isParentOf(thisURL)) { + int lineNumber = -1; + QString fileName = getFilename(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } //V8TODO this probably needs to be done per context, otherwise file cannot be included again in a module - scriptWarningMessage("Script.include() -- skipping" + file + "-- outside of standard libraries"); + scriptWarningMessage("Script.include() -- skipping" + file + "-- outside of standard libraries", fileName, lineNumber); continue; } isStandardLibrary = true; @@ -1693,8 +1726,15 @@ void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& bool disallowOutsideFiles = thisURL.isLocalFile() && !isStandardLibrary && !currentSandboxURL.isLocalFile(); if (disallowOutsideFiles && !PathUtils::isDescendantOf(thisURL, currentSandboxURL)) { + int lineNumber = -1; + QString fileName = currentSandboxURL.toString(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } scriptWarningMessage("Script.include() ignoring file path" + thisURL.toString() - + "outside of original entity script" + currentSandboxURL.toString()); + + "outside of original entity script" + currentSandboxURL.toString(), fileName, lineNumber); } else { // We could also check here for CORS, but we don't yet. // It turns out that QUrl.resolve will not change hosts and copy authority, so we don't need to check that here. @@ -1716,7 +1756,14 @@ void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& for (QUrl url : urls) { QString contents = data[url]; if (contents.isNull()) { - scriptErrorMessage("Error loading file (" + status[url] +"): " + url.toString()); + int lineNumber = -1; + QString fileName = url.toString(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } + scriptErrorMessage("Error loading file (" + status[url] +"): " + url.toString(), fileName, lineNumber); } else { std::lock_guard lock(_lock); if (!_includedURLs.contains(url)) { @@ -1736,7 +1783,14 @@ void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& _engine->clearExceptions(); } } else { - scriptPrintedMessage("Script.include() skipping evaluation of previously included url:" + url.toString()); + int lineNumber = -1; + QString fileName = url.toString(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } + scriptPrintedMessage("Script.include() skipping evaluation of previously included url:" + url.toString(), fileName, lineNumber); } } } @@ -1765,8 +1819,15 @@ void ScriptManager::include(const QStringList& includeFiles, const ScriptValue& void ScriptManager::include(const QString& includeFile, const ScriptValue& callback) { if (isStopped()) { + int lineNumber = -1; + QString fileName = currentSandboxURL.toString(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } scriptWarningMessage("Script.include() while shutting down is ignored... includeFile:" - + includeFile + "parent script:" + getFilename()); + + includeFile + "parent script:" + getFilename(), fileName, lineNumber); return; // bail early } @@ -1782,14 +1843,21 @@ void ScriptManager::load(const QString& loadFile) { if (!_engine->IS_THREADSAFE_INVOCATION(__FUNCTION__)) { return; } + int lineNumber = -1; + QString fileName = getFilename(); + auto context = _engine->currentContext(); + if (context) { + lineNumber = context->currentLineNumber(); + fileName = context->currentFileName(); + } if (isStopped()) { scriptWarningMessage("Script.load() while shutting down is ignored... loadFile:" - + loadFile + "parent script:" + getFilename()); + + loadFile + "parent script:" + getFilename(), fileName, lineNumber); return; // bail early } if (!currentEntityIdentifier.isInvalidID()) { scriptWarningMessage("Script.load() from entity script is ignored... loadFile:" - + loadFile + "parent script:" + getFilename() + "entity: " + currentEntityIdentifier.toString()); + + loadFile + "parent script:" + getFilename() + "entity: " + currentEntityIdentifier.toString(), fileName, lineNumber); return; // bail early } @@ -2457,7 +2525,7 @@ void ScriptManager::refreshFileScript(const EntityItemID& entityID) { QString filePath = QUrl(details.scriptText).toLocalFile(); auto lastModified = QFileInfo(filePath).lastModified().toMSecsSinceEpoch(); if (lastModified > details.lastModified) { - scriptInfoMessage("Reloading modified script " + details.scriptText); + scriptInfoMessage("Reloading modified script " + details.scriptText, filePath, -1); loadEntityScript(entityID, details.scriptText, true); } } diff --git a/libraries/script-engine/src/ScriptMessage.cpp b/libraries/script-engine/src/ScriptMessage.cpp index b80b1e3c56..cb920fa569 100644 --- a/libraries/script-engine/src/ScriptMessage.cpp +++ b/libraries/script-engine/src/ScriptMessage.cpp @@ -11,12 +11,30 @@ #include "ScriptMessage.h" +#include + QJsonObject ScriptMessage::toJson() { QJsonObject object; object["message"] = _messageContent; object["lineNumber"] = _lineNumber; object["fileName"] = _fileName; - object["type"] = scriptTypeToString(_scriptType); - object["severity"] = severityToString(_severity); + object["type"] = static_cast(_scriptType); + object["severity"] = static_cast(_severity); return object; +} + +bool ScriptMessage::fromJson(const QJsonObject &object) { + if (!object["message"].isString() + || !object["lineNumber"].isDouble() + || !object["fileName"].isString() + || !object["type"].isDouble() + || !object["severity"].isDouble()) { + qDebug() << "ScriptMessage::fromJson failed to find required fields in JSON file"; + return false; + } + _messageContent = object["message"].toString(); + _lineNumber = object["lineNumber"].toInt(); + _fileName = object["fileName"].toInt(); + _scriptType = static_cast(object["type"].toInt()); + _severity = static_cast(object["severity"].toInt()); } \ No newline at end of file diff --git a/libraries/script-engine/src/ScriptMessage.h b/libraries/script-engine/src/ScriptMessage.h index adf92d7683..a0a9f52615 100644 --- a/libraries/script-engine/src/ScriptMessage.h +++ b/libraries/script-engine/src/ScriptMessage.h @@ -34,17 +34,12 @@ public: SEVERITY_ERROR }; - static QString scriptTypeToString(ScriptType scriptType); - static QString severityToString(Severity severity); - - static ScriptType scriptTypeFromString(ScriptType scriptType); - static Severity severityFromString(Severity severity); - ScriptMessage() {}; ScriptMessage(QString messageContent, QString fileName, int lineNumber, ScriptType scriptType, Severity severity) : _messageContent(messageContent), _fileName(fileName), _lineNumber(lineNumber), _scriptType(scriptType) {} QJsonObject toJson(); + bool fromJson(const QJsonObject &object); private: QString _messageContent; diff --git a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp index 2b92a9ae8a..11e90b3a5a 100644 --- a/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptContextV8Wrapper.cpp @@ -111,6 +111,37 @@ QStringList ScriptContextV8Wrapper::backtrace() const { return backTrace; } +int ScriptContextV8Wrapper::currentLineNumber() const { + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_context.Get(isolate)); + v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 1); + if (stackTrace->GetFrameCount() > 0) { + v8::Local stackFrame = stackTrace->GetFrame(isolate, 0); + return stackFrame->GetLineNumber(); + } else { + return -1; + } +} + +QString ScriptContextV8Wrapper::currentFileName() const { + auto isolate = _engine->getIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolateScope(isolate); + v8::HandleScope handleScope(isolate); + v8::Context::Scope contextScope(_context.Get(isolate)); + v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 1); + QStringList backTrace; + if (stackTrace->GetFrameCount() > 0) { + v8::Local stackFrame = stackTrace->GetFrame(isolate, 0); + return *v8::String::Utf8Value(isolate, stackFrame->GetScriptNameOrSourceURL()); + } else { + return ""; + } +} + ScriptValue ScriptContextV8Wrapper::callee() const { Q_ASSERT(false); //V8TODO diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index 61dbdd00e0..d10b1c2d15 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -77,6 +77,17 @@ bool ScriptEngineV8::IS_THREADSAFE_INVOCATION(const QThread* thread, const QStri return false; } +QString getFileNameFromTryCatch(v8::TryCatch &tryCatch, v8::Isolate *isolate, v8::Local &context ) { + v8::Local exceptionMessage = tryCatch.Message(); + QString errorFileName; + auto resource = exceptionMessage->GetScriptResourceName(); + v8::Local v8resourceString; + if (resource->ToString(context).ToLocal(&v8resourceString)) { + errorFileName = QString(*v8::String::Utf8Value(isolate, v8resourceString)); + } + return errorFileName; +} + ScriptValue ScriptEngineV8::makeError(const ScriptValue& _other, const QString& type) { if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { return nullValue(); @@ -726,7 +737,13 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, + "tryCatch details:" + formatErrorMessageFromTryCatch(tryCatch); v8Result = v8::Null(_v8Isolate); if (_manager) { - _manager->scriptErrorMessage(errorMessage); + v8::Local exceptionMessage = tryCatch.Message(); + int errorLineNumber = -1; + if (!exceptionMessage.IsEmpty()) { + errorLineNumber = exceptionMessage->GetLineNumber(closureContext).FromJust(); + } + _manager->scriptErrorMessage(errorMessage, getFileNameFromTryCatch(tryCatch, _v8Isolate, closureContext), + errorLineNumber); } else { qWarning(scriptengine_v8) << errorMessage; } @@ -781,7 +798,13 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f if (!v8::Script::Compile(context, v8::String::NewFromUtf8(getIsolate(), sourceCode.toStdString().c_str()).ToLocalChecked(), &scriptOrigin).ToLocal(&script)) { QString errorMessage(QString("Error while compiling script: \"") + fileName + QString("\" ") + formatErrorMessageFromTryCatch(tryCatch)); if (_manager) { - _manager->scriptErrorMessage(errorMessage); + v8::Local exceptionMessage = tryCatch.Message(); + int errorLineNumber = -1; + if (!exceptionMessage.IsEmpty()) { + errorLineNumber = exceptionMessage->GetLineNumber(context).FromJust(); + } + _manager->scriptErrorMessage(errorMessage, getFileNameFromTryCatch(tryCatch, _v8Isolate, context), + errorLineNumber); } else { qDebug(scriptengine_v8) << errorMessage; } @@ -799,7 +822,13 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(this, runError->Get()))); QString errorMessage(QString("Running script: \"") + fileName + QString("\" ") + formatErrorMessageFromTryCatch(tryCatchRun)); if (_manager) { - _manager->scriptErrorMessage(errorMessage); + v8::Local exceptionMessage = tryCatchRun.Message(); + int errorLineNumber = -1; + if (!exceptionMessage.IsEmpty()) { + errorLineNumber = exceptionMessage->GetLineNumber(context).FromJust(); + } + _manager->scriptErrorMessage(errorMessage, getFileNameFromTryCatch(tryCatchRun, _v8Isolate, context), + errorLineNumber); } else { qDebug(scriptengine_v8) << errorMessage; } diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.h b/libraries/script-engine/src/v8/ScriptEngineV8.h index 5badba271e..02352c9ed7 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.h +++ b/libraries/script-engine/src/v8/ScriptEngineV8.h @@ -309,6 +309,8 @@ private: ScriptEngineV8* _engine; }; +QString getFileNameFromTryCatch(v8::TryCatch &tryCatch, v8::Isolate *isolate, v8::Local &context ); + #include "V8Types.h" #endif // hifi_ScriptEngineV8_h diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index 3803f09abf..48572c30f9 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -1281,8 +1281,14 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu QString errorMessage(QString("Signal proxy ") + fullName() + " connection call failed: \"" + _engine->formatErrorMessageFromTryCatch(tryCatch) + "\nThis provided: " + QString::number(conn.thisValue.get()->IsObject())); + v8::Local exceptionMessage = tryCatch.Message(); + int errorLineNumber = -1; + if (!exceptionMessage.IsEmpty()) { + errorLineNumber = exceptionMessage->GetLineNumber(context).FromJust(); + } if (_engine->_manager) { - _engine->_manager->scriptErrorMessage(errorMessage); + _engine->_manager->scriptErrorMessage(errorMessage, getFileNameFromTryCatch(tryCatch, isolate, context), + errorLineNumber); } else { qDebug(scriptengine_v8) << errorMessage; } diff --git a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp index 40bfde0807..7f9faf21f2 100644 --- a/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp +++ b/libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp @@ -104,7 +104,13 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri if (tryCatch.HasCaught()) { QString errorMessage(QString("Function call failed: \"") + _engine->formatErrorMessageFromTryCatch(tryCatch)); if (_engine->_manager) { - _engine->_manager->scriptErrorMessage(errorMessage); + v8::Local exceptionMessage = tryCatch.Message(); + int errorLineNumber = -1; + if (!exceptionMessage.IsEmpty()) { + errorLineNumber = exceptionMessage->GetLineNumber(context).FromJust(); + } + _engine->_manager->scriptErrorMessage(errorMessage, getFileNameFromTryCatch(tryCatch, isolate, context), + errorLineNumber); } else { qDebug(scriptengine_v8) << errorMessage; } @@ -114,9 +120,10 @@ ScriptValue ScriptValueV8Wrapper::call(const ScriptValue& thisObject, const Scri if (maybeResult.ToLocal(&result)) { return ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, result))); } else { - QString errorMessage("JS function call failed: " + _engine->currentContext()->backtrace().join("\n")); + auto currentContext = _engine->currentContext(); + QString errorMessage("JS function call failed: " + currentContext->backtrace().join("\n")); if (_engine->_manager) { - _engine->_manager->scriptErrorMessage(errorMessage); + _engine->_manager->scriptErrorMessage(errorMessage, currentContext->currentFileName(), currentContext->currentLineNumber()); } else { qDebug(scriptengine_v8) << errorMessage; }