Index: src/script/data/indentation/cstyle.js =================================================================== --- src/script/data/indentation/cstyle.js +++ src/script/data/indentation/cstyle.js @@ -514,6 +514,8 @@ if (currentString.search(/^\s*(if\b|[}]?\s*else|do\b|while\b|for)[^{]*$/) != -1) indentation = firstPosVirtual; break; + } else if (currentLine == 0 || lineDelimiter == 0) { + return indentation; } } } Index: src/script/katecommandlinescript.cpp =================================================================== --- src/script/katecommandlinescript.cpp +++ src/script/katecommandlinescript.cpp @@ -55,6 +55,7 @@ errorMessage = i18n("Function '%1' not found in script: %2", cmd, url()); return false; } + V4JITDisabler maybeDisableQMLJITCompiler; // add the arguments that we are going to pass to the function QJSValueList arguments; @@ -123,6 +124,7 @@ if (!helpFunction.isCallable()) { return false; } + V4JITDisabler maybeDisableQMLJITCompiler; // add the arguments that we are going to pass to the function QJSValueList arguments; Index: src/script/kateindentscript.cpp =================================================================== --- src/script/kateindentscript.cpp +++ src/script/kateindentscript.cpp @@ -69,6 +69,8 @@ if (!indentFunction.isCallable()) { return qMakePair(-2, -2); } + V4JITDisabler maybeDisableQMLJITCompiler; + // add the arguments that we are going to pass to the function QJSValueList arguments; arguments << QJSValue(position.line()); Index: src/script/katescript.h =================================================================== --- src/script/katescript.h +++ src/script/katescript.h @@ -188,6 +188,23 @@ /** Return the general header */ KateScriptHeader &generalHeader(); + /** + * Helper class to disable the JIT during its scope. Kate's scripts have been known + * to trigger a bug in JIT-compiled QML that would crash the application. + * Creating a V4JITDisabler instance disables the JIT in affected Qt versions, and + * restores the setting before going out of scope. + */ + class V4JITDisabler + { + public: + V4JITDisabler(); + ~V4JITDisabler(); + private: + QByteArray m_cachedValue; + bool m_hasCache; + static bool s_infoPrinted; + }; + protected: /** Checks for exception and gives feedback on the console. */ bool hasException(const QJSValue &object, const QString &file); Index: src/script/katescript.cpp =================================================================== --- src/script/katescript.cpp +++ src/script/katescript.cpp @@ -40,6 +40,43 @@ //END +KateScript::V4JITDisabler::V4JITDisabler() + : m_hasCache(false) +{ +#if QT_VERSION < QT_VERSION_CHECK(5, 9, 1) + if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER")) { + m_cachedValue = qgetenv("QV4_FORCE_INTERPRETER"); + m_hasCache = true; + } + // disable the JIT for this call as it may trigger a bug in QML + // that would crash the application. Crude but effective. + qputenv("QV4_FORCE_INTERPRETER", QByteArrayLiteral("1")); + qCDebug(LOG_KTE) << "QV4_FORCE_INTERPRETER set to" << qgetenv("QV4_FORCE_INTERPRETER"); +#endif +} + +KateScript::V4JITDisabler::~V4JITDisabler() +{ +#if QT_VERSION < QT_VERSION_CHECK(5, 9, 1) + if (m_hasCache) { + // restore + qputenv("QV4_FORCE_INTERPRETER", m_cachedValue); + qCWarning(LOG_KTE) << "QV4_FORCE_INTERPRETER reset to" << qgetenv("QV4_FORCE_INTERPRETER"); + } else { + qunsetenv("QV4_FORCE_INTERPRETER"); + qCDebug(LOG_KTE) << "QV4_FORCE_INTERPRETER unset"; + if (!s_infoPrinted) { + QTextStream info(stderr); + info << i18n("Please disregard any warnings about JIT being disabled for QML; " + "this applies only to KTextEditor scripts.\n"); + s_infoPrinted = true; + } + } +#endif +} + +bool KateScript::V4JITDisabler::s_infoPrinted = false; + KateScript::KateScript(const QString &urlOrScript, enum InputType inputType) : m_loaded(false) , m_loadSuccessful(false) @@ -118,6 +155,11 @@ m_loaded = true; m_loadSuccessful = false; // here set to false, and at end of function to true + // disable the JIT for this call as it may trigger a bug in QML + // that would crash the application. V4JITDisabler disables the JIT + // in affected Qt versions, and restores it before exitting from this function. + V4JITDisabler maybeDisableQMLJITCompiler; + // read the script file into memory QString source; if (m_inputType == InputURL) { @@ -202,6 +244,7 @@ qWarning() << "load of script failed:" << program; return QJSValue(); } + V4JITDisabler maybeDisableQMLJITCompiler; // Wrap the arguments in a function to avoid poluting the global object QString programWithContext = QStringLiteral("function(") + Index: src/script/katescripthelpers.cpp =================================================================== --- src/script/katescripthelpers.cpp +++ src/script/katescripthelpers.cpp @@ -116,6 +116,7 @@ { QStringList files; files << file; + KateScript::V4JITDisabler maybeDisableQMLJITCompiler; /** * just search for all given scripts and eval them */