diff --git a/docsrc/manual/scripting-capabilities.rst b/docsrc/manual/scripting-capabilities.rst index 129159e4..6a48ab62 100644 --- a/docsrc/manual/scripting-capabilities.rst +++ b/docsrc/manual/scripting-capabilities.rst @@ -72,7 +72,7 @@ The grass-randomizer script above happens implicitly when the user paints on the .. code-block:: js - function applyNightTint() { + export function applyNightTint() { // Apply night palette tinting... } @@ -556,7 +556,7 @@ These are some miscellaneous functions that can be very useful when building cus .. js:function:: map.registerAction(functionName, actionName, shortcut = "") - Registers a JavaScript function to an action that can be manually triggered in Porymap's ``Tools`` menu. Optionally, a keyboard shortcut (e.g. ``"Ctrl+P"``) can also be specified, assuming it doesn't collide with any existing shortcuts used by Porymap. + Registers a JavaScript function to an action that can be manually triggered in Porymap's ``Tools`` menu. Optionally, a keyboard shortcut (e.g. ``"Ctrl+P"``) can also be specified, assuming it doesn't collide with any existing shortcuts used by Porymap. The function specified by ``functionName`` must have the ``export`` keyword. :param string functionName: name of the JavaScript function :param string actionName: name of the action that will be displayed in the ``Tools`` menu diff --git a/include/scripting.h b/include/scripting.h index 6f3b0d16..3e86f1b8 100644 --- a/include/scripting.h +++ b/include/scripting.h @@ -30,6 +30,7 @@ public: static void cb_ProjectClosed(QString projectPath); static void cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock); static void cb_MapOpened(QString mapName); + static bool tryErrorJS(QJSValue js); private: QJSEngine *engine; diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index 2084973e..20543c64 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -507,7 +507,7 @@ void MainWindow::setTimeout(QJSValue callback, int milliseconds) { } void MainWindow::invokeCallback(QJSValue callback) { - callback.call(); + Scripting::tryErrorJS(callback.call()); } void MainWindow::log(QString message) { diff --git a/src/scripting.cpp b/src/scripting.cpp index b14b0858..7879ea03 100644 --- a/src/scripting.cpp +++ b/src/scripting.cpp @@ -51,23 +51,25 @@ void Scripting::loadModules(QStringList moduleFiles) { } } +bool Scripting::tryErrorJS(QJSValue js) { + if (!js.isError()) return false; + + QFileInfo file(js.property("fileName").toString()); + logError(QString("Error in custom script '%1' at line %2: '%3'") + .arg(file.fileName()) + .arg(js.property("lineNumber").toString()) + .arg(js.toString())); + return true; +} + void Scripting::invokeCallback(CallbackType type, QJSValueList args) { for (QJSValue module : this->modules) { QString functionName = callbackFunctions[type]; QJSValue callbackFunction = module.property(functionName); - if (callbackFunction.isError()) { - continue; - } + if (tryErrorJS(callbackFunction)) continue; QJSValue result = callbackFunction.call(args); - if (result.isError()) { - QFileInfo file(result.property("fileName").toString()); - logError(QString("Error in custom script '%1' at line %2: '%3'") - .arg(file.fileName()) - .arg(result.property("lineNumber").toString()) - .arg(result.toString())); - continue; - } + if (tryErrorJS(result)) continue; } } @@ -88,19 +90,14 @@ void Scripting::invokeAction(QString actionName) { QString functionName = instance->registeredActions.value(actionName); for (QJSValue module : instance->modules) { QJSValue callbackFunction = module.property(functionName); - if (callbackFunction.isError()) { + if (callbackFunction.isUndefined() || !callbackFunction.isCallable()) { + logError(QString("Unknown custom script function '%1'").arg(functionName)); continue; } + if (tryErrorJS(callbackFunction)) continue; QJSValue result = callbackFunction.call(QJSValueList()); - if (result.isError()) { - QFileInfo file(result.property("fileName").toString()); - logError(QString("Error in custom script '%1' at line %2: '%3'") - .arg(file.fileName()) - .arg(result.property("lineNumber").toString()) - .arg(result.toString())); - continue; - } + if (tryErrorJS(result)) continue; } }