JavaScriptFilter: Use QScriptEngine to avoid endless loops

QJSEngine does not provide a means to interrupt the
evaluation when then engine stucks in an endless loop.

The (deprecated) QScriptEngine does allow this,
so use this for now. As QBS also needs QScriptEngine,
no extra dependency is created. For Qt installations
without QtScript, the JavaScriptFilter is not compiled.

Task-number: QTCREATORBUG-19690
Change-Id: I172b7e7042eea0d40a765c836b2d1c57b6a529e6
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Andre Hartmann
2018-01-31 20:48:21 +01:00
committed by André Hartmann
parent 38807f3ded
commit 5f69507573
5 changed files with 56 additions and 15 deletions

View File

@@ -17,11 +17,18 @@ Project {
condition: qbs.targetOS.contains("windows") condition: qbs.targetOS.contains("windows")
} }
Depends { name: "Qt.script"; required: false }
Depends { name: "Utils" } Depends { name: "Utils" }
Depends { name: "Aggregation" } Depends { name: "Aggregation" }
Depends { name: "app_version_header" } Depends { name: "app_version_header" }
Properties {
condition: Qt.script.present
cpp.defines: base.concat("WITH_JAVASCRIPTFILTER")
}
cpp.dynamicLibraries: { cpp.dynamicLibraries: {
if (qbs.targetOS.contains("windows")) if (qbs.targetOS.contains("windows"))
return ["ole32", "user32"] return ["ole32", "user32"]
@@ -343,8 +350,6 @@ Project {
"filesystemfilter.ui", "filesystemfilter.ui",
"ilocatorfilter.cpp", "ilocatorfilter.cpp",
"ilocatorfilter.h", "ilocatorfilter.h",
"javascriptfilter.cpp",
"javascriptfilter.h",
"locatorconstants.h", "locatorconstants.h",
"locatorfiltersfilter.cpp", "locatorfiltersfilter.cpp",
"locatorfiltersfilter.h", "locatorfiltersfilter.h",
@@ -364,6 +369,16 @@ Project {
] ]
} }
Group {
name: "Locator Javascript Filter"
condition: Qt.script.present
prefix: "locator/"
files: [
"javascriptfilter.cpp",
"javascriptfilter.h",
]
}
Group { Group {
name: "Locator_mac" name: "Locator_mac"
condition: qbs.targetOS.contains("macos") condition: qbs.targetOS.contains("macos")

View File

@@ -27,14 +27,16 @@
#include <QClipboard> #include <QClipboard>
#include <QGuiApplication> #include <QGuiApplication>
#include <QJSEngine> #include <QScriptEngine>
#include <QTimer>
namespace Core { namespace Core {
namespace Internal { namespace Internal {
enum JavaScriptAction enum JavaScriptAction
{ {
ResetEngine = QVariant::UserType + 1 ResetEngine = QVariant::UserType + 1,
AbortEngine
}; };
JavaScriptFilter::JavaScriptFilter() JavaScriptFilter::JavaScriptFilter()
@@ -66,12 +68,24 @@ QList<LocatorFilterEntry> JavaScriptFilter::matchesFor(
if (entry.trimmed().isEmpty()) { if (entry.trimmed().isEmpty()) {
entries.append({this, tr("Reset Engine"), QVariant(ResetEngine, nullptr)}); entries.append({this, tr("Reset Engine"), QVariant(ResetEngine, nullptr)});
} else { } else {
const QString result = m_engine->evaluate(entry).toString(); bool aborted = false;
const QString expression = entry + " = " + result;
entries.append({this, expression, QVariant()}); QTimer::singleShot(1000, this, [this, &aborted]() {
entries.append({this, tr("Copy to clipboard: %1").arg(result), result}); m_engine->abortEvaluation();
entries.append({this, tr("Copy to clipboard: %1").arg(expression), expression}); aborted = true;
});
const QString result = m_engine->evaluate(entry).toString();
if (aborted) {
const QString message = entry + " = " + tr("Engine aborted after timeout.");
entries.append({this, message, QVariant(AbortEngine, nullptr)});
} else {
const QString expression = entry + " = " + result;
entries.append({this, expression, QVariant()});
entries.append({this, tr("Copy to clipboard: %1").arg(result), result});
entries.append({this, tr("Copy to clipboard: %1").arg(expression), expression});
}
} }
return entries; return entries;
@@ -104,7 +118,7 @@ void JavaScriptFilter::refresh(QFutureInterface<void> &future)
void JavaScriptFilter::setupEngine() void JavaScriptFilter::setupEngine()
{ {
m_engine.reset(new QJSEngine); m_engine.reset(new QScriptEngine);
m_engine->evaluate( m_engine->evaluate(
"function abs(x) { return Math.abs(x); }\n" "function abs(x) { return Math.abs(x); }\n"
"function acos(x) { return Math.acos(x); }\n" "function acos(x) { return Math.acos(x); }\n"

View File

@@ -30,7 +30,7 @@
#include <memory> #include <memory>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QJSEngine; class QScriptEngine;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {
@@ -53,7 +53,7 @@ public:
private: private:
void setupEngine(); void setupEngine();
mutable std::unique_ptr<QJSEngine> m_engine; mutable std::unique_ptr<QScriptEngine> m_engine;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -122,8 +122,10 @@ void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *)
new LocatorManager(this); new LocatorManager(this);
#ifdef WITH_JAVASCRIPTFILTER
m_javaScriptFilter = new JavaScriptFilter; m_javaScriptFilter = new JavaScriptFilter;
m_corePlugin->addObject(m_javaScriptFilter); m_corePlugin->addObject(m_javaScriptFilter);
#endif
m_openDocumentsFilter = new OpenDocumentsFilter; m_openDocumentsFilter = new OpenDocumentsFilter;
m_corePlugin->addObject(m_openDocumentsFilter); m_corePlugin->addObject(m_openDocumentsFilter);

View File

@@ -15,8 +15,7 @@ HEADERS += \
$$PWD/executefilter.h \ $$PWD/executefilter.h \
$$PWD/locatorsearchutils.h \ $$PWD/locatorsearchutils.h \
$$PWD/locatorsettingspage.h \ $$PWD/locatorsettingspage.h \
$$PWD/externaltoolsfilter.h \ $$PWD/externaltoolsfilter.h
$$PWD/javascriptfilter.h
SOURCES += \ SOURCES += \
$$PWD/locator.cpp \ $$PWD/locator.cpp \
@@ -33,7 +32,18 @@ SOURCES += \
$$PWD/locatorsearchutils.cpp \ $$PWD/locatorsearchutils.cpp \
$$PWD/locatorsettingspage.cpp \ $$PWD/locatorsettingspage.cpp \
$$PWD/externaltoolsfilter.cpp \ $$PWD/externaltoolsfilter.cpp \
$$PWD/javascriptfilter.cpp
qtHaveModule(script) {
QT *= script
DEFINES += WITH_JAVASCRIPTFILTER
HEADERS += \
$$PWD/javascriptfilter.h
SOURCES += \
$$PWD/javascriptfilter.cpp
}
FORMS += \ FORMS += \
$$PWD/filesystemfilter.ui \ $$PWD/filesystemfilter.ui \