Index: templates/CMakeLists.txt =================================================================== --- templates/CMakeLists.txt +++ templates/CMakeLists.txt @@ -1,6 +1,6 @@ find_package(Qt5Core 5.2.0 REQUIRED) -find_package(Qt5Script 5.2.0) +find_package(Qt5Qml 5.2.0) add_subdirectory(lib) @@ -16,11 +16,6 @@ add_subdirectory(i18n) endif() - -if (BUILD_SCRIPT_PLUGIN) -# add_subdirectory(scriptabletags) -endif() - if (BUILD_TESTS) add_subdirectory(tests) endif() Index: templates/lib/CMakeLists.txt =================================================================== --- templates/lib/CMakeLists.txt +++ templates/lib/CMakeLists.txt @@ -88,7 +88,7 @@ PLUGINS_PREFER_DEBUG_POSTFIX=$ ) -if (Qt5Script_FOUND) +if (Qt5Qml_FOUND) set(scriptabletags_FILES scriptablecontext.cpp scriptablefilterexpression.cpp @@ -108,7 +108,7 @@ target_sources(Grantlee_Templates PRIVATE ${scriptabletags_SRCS}) target_include_directories(Grantlee_Templates PRIVATE ../scriptabletags) target_link_libraries(Grantlee_Templates - LINK_PRIVATE Qt5::Script + LINK_PRIVATE Qt5::Qml ) endif() Index: templates/lib/engine.cpp =================================================================== --- templates/lib/engine.cpp +++ templates/lib/engine.cpp @@ -24,7 +24,7 @@ #include "exception.h" #include "grantlee_config_p.h" #include "grantlee_version.h" -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB #include "scriptabletags.h" #endif #include "template_p.h" @@ -52,7 +52,7 @@ Engine::~Engine() { -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB qDeleteAll(d_ptr->m_scriptableLibraries); #endif d_ptr->m_libraries.clear(); @@ -142,7 +142,7 @@ { Q_D(Engine); -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB // Make sure we can load default scriptable libraries if we're supposed to. if (d->m_defaultLibraries.contains(QLatin1String(__scriptableLibName)) && !d->m_scriptableTagLibrary) { @@ -196,7 +196,7 @@ // that. uint minorVersion = GRANTLEE_VERSION_MINOR; while (acceptableVersion(minorVersion)) { -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB // Although we don't use scripted libaries here, we need to // recognize them // being first @@ -224,7 +224,7 @@ { Q_D(Engine); -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB if (name == QLatin1String(__scriptableLibName)) return 0; #endif @@ -251,7 +251,7 @@ TagLibraryInterface *EnginePrivate::loadLibrary(const QString &name, uint minorVersion) { -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB auto scriptableLibrary = loadScriptableLibrary(name, minorVersion); if (scriptableLibrary) return scriptableLibrary; @@ -264,7 +264,7 @@ EnginePrivate::EnginePrivate(Engine *engine) : q_ptr(engine) -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB , m_scriptableTagLibrary(0) #endif @@ -301,7 +301,7 @@ return QString(); } -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB ScriptableLibraryContainer * EnginePrivate::loadScriptableLibrary(const QString &name, uint minorVersion) { Index: templates/lib/engine_p.h =================================================================== --- templates/lib/engine_p.h +++ templates/lib/engine_p.h @@ -86,7 +86,7 @@ TagLibraryInterface *loadLibrary(const QString &name, uint minorVersion); QString getScriptLibraryName(const QString &name, uint minorVersion) const; -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB ScriptableLibraryContainer *loadScriptableLibrary(const QString &name, uint minorVersion); #endif @@ -97,14 +97,14 @@ Engine *const q_ptr; QHash> m_libraries; -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB QHash m_scriptableLibraries; #endif QList> m_loaders; QStringList m_pluginDirs; QStringList m_defaultLibraries; -#ifdef QT_SCRIPT_LIB +#ifdef QT_QML_LIB ScriptableTagLibrary *m_scriptableTagLibrary; #endif bool m_smartTrimEnabled; Index: templates/scriptabletags/CMakeLists.txt =================================================================== --- templates/scriptabletags/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -project(grantlee_scriptabletags) - -add_library(grantlee_scriptabletags MODULE - scriptablecontext.cpp - scriptablefilterexpression.cpp - scriptablenode.cpp - scriptableparser.cpp - scriptablesafestring.cpp - scriptabletags.cpp - scriptabletemplate.cpp - scriptablevariable.cpp - scriptablefilter.cpp -) -grantlee_adjust_plugin_name(grantlee_scriptabletags) - -target_link_libraries(grantlee_scriptabletags - Grantlee5::Templates - Qt4::QtScript -) - -install(TARGETS grantlee_scriptabletags - LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} -) Index: templates/scriptabletags/scriptablecontext.h =================================================================== --- templates/scriptabletags/scriptablecontext.h +++ templates/scriptabletags/scriptablecontext.h @@ -45,7 +45,7 @@ void push(); void pop(); - QString render(const QObjectList &list) const; + QString render(const QList &list) const; private: Context *m_c; Index: templates/scriptabletags/scriptablecontext.cpp =================================================================== --- templates/scriptabletags/scriptablecontext.cpp +++ templates/scriptabletags/scriptablecontext.cpp @@ -42,7 +42,7 @@ void ScriptableContext::pop() { m_c->pop(); } -QString ScriptableContext::render(const QObjectList &list) const +QString ScriptableContext::render(const QList &list) const { NodeList nodeList; QListIterator it(list); Index: templates/scriptabletags/scriptablefilter.h =================================================================== --- templates/scriptabletags/scriptablefilter.h +++ templates/scriptabletags/scriptablefilter.h @@ -21,26 +21,26 @@ #ifndef SCRIPTABLE_FILTER_H #define SCRIPTABLE_FILTER_H -#include +#include #include "filter.h" using namespace Grantlee; class ScriptableFilter : public Filter { public: - ScriptableFilter(const QScriptValue &filterObject, QScriptEngine *engine); + ScriptableFilter(const QJSValue &filterObject, QJSEngine *engine); ~ScriptableFilter() override; QVariant doFilter(const QVariant &input, const QVariant &argument, bool autoescape = false) const override; bool isSafe() const override; private: - QScriptValue m_filterObject; - QScriptEngine *m_scriptEngine; + QJSValue m_filterObject; + QJSEngine *m_scriptEngine; }; #endif Index: templates/scriptabletags/scriptablefilter.cpp =================================================================== --- templates/scriptabletags/scriptablefilter.cpp +++ templates/scriptabletags/scriptablefilter.cpp @@ -21,12 +21,13 @@ #include "scriptablefilter.h" #include "scriptablesafestring.h" +#include "exception.h" #include "util.h" -#include +#include -ScriptableFilter::ScriptableFilter(const QScriptValue &filterObject, - QScriptEngine *engine) +ScriptableFilter::ScriptableFilter(const QJSValue &filterObject, + QJSEngine *engine) : m_filterObject(filterObject), m_scriptEngine(engine) { } @@ -47,16 +48,16 @@ bool autoescape) const { Q_UNUSED(autoescape) - QScriptValueList args; + QJSValueList args; if (input.userType() == qMetaTypeId()) { auto inputList = input.value(); auto array = m_scriptEngine->newArray(inputList.size()); for (auto i = 0; i < inputList.size(); ++i) { if (inputList.at(i).canConvert()) { array.setProperty( i, m_scriptEngine->newQObject(inputList.at(i).value())); } else { - array.setProperty(i, m_scriptEngine->newVariant(inputList.at(i))); + array.setProperty(i, m_scriptEngine->toScriptValue(inputList.at(i))); } } args << array; @@ -68,34 +69,36 @@ } else if (input.canConvert()) { args << m_scriptEngine->newQObject(input.value()); } else { - args << m_scriptEngine->newVariant(input); + args << m_scriptEngine->toScriptValue(input); } } if (argument.userType() == qMetaTypeId()) { auto ssObj = new ScriptableSafeString(m_scriptEngine); ssObj->setContent(getSafeString(argument)); args << m_scriptEngine->newQObject(ssObj); } else { - args << m_scriptEngine->newVariant(argument); + args << m_scriptEngine->toScriptValue(argument); } auto filterObject = m_filterObject; - auto returnValue = filterObject.call(QScriptValue(), args); + auto returnValue = filterObject.call(args); + if (returnValue.isError()) + throw Grantlee::Exception(UnknownFilterError, returnValue.toString()); if (returnValue.isString()) { return getSafeString(returnValue.toString()); } else if (returnValue.isQObject()) { - auto returnedObject = qscriptvalue_cast(returnValue); + auto returnedObject = qjsvalue_cast(returnValue); auto returnedStringObject = qobject_cast(returnedObject); if (!returnedStringObject) return QVariant(); auto returnedString = returnedStringObject->wrappedString(); return returnedString; } else if (returnValue.isVariant()) { - return qscriptvalue_cast(returnValue); + return qjsvalue_cast(returnValue); } else if (returnValue.isArray()) { - return qscriptvalue_cast(returnValue); + return qjsvalue_cast(returnValue); } return QVariant(); } Index: templates/scriptabletags/scriptablefilterexpression.h =================================================================== --- templates/scriptabletags/scriptablefilterexpression.h +++ templates/scriptabletags/scriptablefilterexpression.h @@ -23,39 +23,32 @@ #include -#include +#include #include "filterexpression.h" -class QScriptContext; - -class ScriptableContext; - -QScriptValue ScriptableFilterExpressionConstructor(QScriptContext *context, - QScriptEngine *engine); - class ScriptableFilterExpression : public QObject { Q_OBJECT public: ScriptableFilterExpression(QObject *parent = 0); - ScriptableFilterExpression(QScriptEngine *engine, QObject *parent = 0); + ScriptableFilterExpression(QJSEngine *engine, QObject *parent = 0); void init(const QString &content, Grantlee::Parser *parser); public Q_SLOTS: - QVariant resolve(ScriptableContext *c); + QVariant resolve(QObject *c); - bool isTrue(ScriptableContext *c); + bool isTrue(QObject *c); bool equals(ScriptableFilterExpression *other, - ScriptableContext *scriptableC); + QObject *scriptableC); - // list? QScriptValueList? Make this a ScriptClass? + // list? QJSValueList? Make this a ScriptClass? private: Grantlee::FilterExpression m_filterExpression; - QScriptEngine *m_engine; + QJSEngine *m_engine; }; #endif Index: templates/scriptabletags/scriptablefilterexpression.cpp =================================================================== --- templates/scriptabletags/scriptablefilterexpression.cpp +++ templates/scriptabletags/scriptablefilterexpression.cpp @@ -20,36 +20,21 @@ #include "scriptablefilterexpression.h" -#include +#include #include "parser.h" #include "scriptablecontext.h" #include "scriptablesafestring.h" #include "util.h" using namespace Grantlee; -Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptableFilterExpression, QObject *) - -QScriptValue ScriptableFilterExpressionConstructor(QScriptContext *context, - QScriptEngine *engine) -{ - auto object = new ScriptableFilterExpression(engine); - - auto parserObj = context->argument(1).toQObject(); - auto p = qobject_cast(parserObj); - - object->init(context->argument(0).toString(), p); - - return engine->newQObject(object); -} - ScriptableFilterExpression::ScriptableFilterExpression(QObject *parent) : QObject(parent), m_engine(0) { } -ScriptableFilterExpression::ScriptableFilterExpression(QScriptEngine *engine, +ScriptableFilterExpression::ScriptableFilterExpression(QJSEngine *engine, QObject *parent) : QObject(parent), m_engine(engine) { @@ -61,8 +46,9 @@ m_filterExpression = FilterExpression(content, parser); } -QVariant ScriptableFilterExpression::resolve(ScriptableContext *c) +QVariant ScriptableFilterExpression::resolve(QObject *o) { + ScriptableContext *c = qobject_cast(o); auto var = m_filterExpression.resolve(c->context()); if (Grantlee::isSafeString(var)) { @@ -73,14 +59,16 @@ return var; } -bool ScriptableFilterExpression::isTrue(ScriptableContext *c) +bool ScriptableFilterExpression::isTrue(QObject *o) { + ScriptableContext *c = qobject_cast(o); return m_filterExpression.isTrue(c->context()); } bool ScriptableFilterExpression::equals(ScriptableFilterExpression *other, - ScriptableContext *scriptableC) + QObject *scriptableO) { + ScriptableContext *scriptableC = qobject_cast(scriptableO); auto c = scriptableC->context(); return Grantlee::equals(m_filterExpression.resolve(c), other->m_filterExpression.resolve(c)); Index: templates/scriptabletags/scriptablenode.h =================================================================== --- templates/scriptabletags/scriptablenode.h +++ templates/scriptabletags/scriptablenode.h @@ -21,68 +21,60 @@ #ifndef SCRIPTABLE_NODE_H #define SCRIPTABLE_NODE_H -#include +#include #include #include "node.h" -class QScriptEngine; -class QScriptContext; +QT_FORWARD_DECLARE_CLASS(QJSEngine) namespace Grantlee { class Context; class Engine; } -typedef QSharedPointer ScriptEnginePointer; +typedef QSharedPointer ScriptEnginePointer; using namespace Grantlee; -QScriptValue ScriptableNodeConstructor(QScriptContext *context, - QScriptEngine *engine); - -QScriptValue nodeToScriptValue(QScriptEngine *engine, Node *const &node); - -void nodeFromScriptValue(const QScriptValue &object, Node *&out); - class ScriptableNode : public Node { Q_OBJECT public: ScriptableNode(QObject *parent = 0); - void setScriptEngine(QScriptEngine *engine); - void init(const QScriptValue &concreteNode, const QScriptValue &renderMethod); + void setScriptEngine(QJSEngine *engine); + void init(const QJSValue &concreteNode, const QJSValue &renderMethod); - QScriptEngine *engine(); + QJSEngine *engine(); void render(OutputStream *stream, Context *c) const override; private: - QScriptEngine *m_scriptEngine; - QScriptValue m_concreteNode; - QScriptValue m_renderMethod; + QJSEngine *m_scriptEngine; + QJSValue m_concreteNode; + QJSValue m_renderMethod; public Q_SLOTS: - void setNodeList(const QString &name, const QObjectList &); + void setNodeList(const QString &name, const QList &); }; class ScriptableNodeFactory : public AbstractNodeFactory { Q_OBJECT public: ScriptableNodeFactory(QObject *parent = 0); - void setScriptEngine(QScriptEngine *engine); + void setScriptEngine(QJSEngine *engine); /* reimp */ void setEngine(Grantlee::Engine *engine) override; - void setFactory(const QScriptValue &factoryMethod); + void setFactory(const QJSValue &factoryMethod); Node *getNode(const QString &tagContent, Parser *p = 0) const override; private: - QScriptEngine *m_scriptEngine; - QScriptValue m_factoryMethod; + QJSEngine *m_scriptEngine; + QJSValue m_factoryMethod; }; #endif Index: templates/scriptabletags/scriptablenode.cpp =================================================================== --- templates/scriptabletags/scriptablenode.cpp +++ templates/scriptabletags/scriptablenode.cpp @@ -20,62 +20,27 @@ #include "scriptablenode.h" -#include +#include #include "context.h" #include "engine.h" #include "exception.h" #include "parser.h" #include "scriptablecontext.h" #include "scriptableparser.h" -QScriptValue nodeToScriptValue(QScriptEngine *engine, Node *const &node) -{ - return engine->newQObject(node); -} - -void nodeFromScriptValue(const QScriptValue &object, Node *&out) -{ - out = qobject_cast(object.toQObject()); -} - -Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptableNode, Node *) - -QScriptValue ScriptableNodeConstructor(QScriptContext *context, - QScriptEngine *engine) -{ - auto scriptableNodeName = context->argument(0).toString(); - auto concreteNode = engine->globalObject().property(scriptableNodeName); - - QScriptValueList args; - // First is the node type - for (auto i = 1; i < context->argumentCount(); ++i) { - args << context->argument(i); - } - - concreteNode.call(concreteNode, args); - - auto renderMethod = concreteNode.property(QStringLiteral("render")); - - auto object = new ScriptableNode(engine); - object->setObjectName(scriptableNodeName); - object->setScriptEngine(engine); - object->init(concreteNode, renderMethod); - return engine->newQObject(object); -} - ScriptableNode::ScriptableNode(QObject *parent) : Node(parent), m_scriptEngine(0) { } -void ScriptableNode::setScriptEngine(QScriptEngine *engine) +void ScriptableNode::setScriptEngine(QJSEngine *engine) { m_scriptEngine = engine; } -void ScriptableNode::init(const QScriptValue &concreteNode, - const QScriptValue &renderMethod) +void ScriptableNode::init(const QJSValue &concreteNode, + const QJSValue &renderMethod) { m_concreteNode = concreteNode; m_renderMethod = renderMethod; @@ -86,23 +51,25 @@ ScriptableContext sc(c); auto contextObject = m_scriptEngine->newQObject(&sc); - QScriptValueList args; + QJSValueList args; args << contextObject; // Call the render method in the context of the concreteNode - auto value - = const_cast(m_renderMethod).call(m_concreteNode, args); + auto value = const_cast(m_renderMethod).callWithInstance(m_concreteNode, args); - if (value.isValid() && !value.isUndefined()) + if (!value.isError() && !value.isUndefined()) (*stream) << value.toString(); + + if (value.isError()) + throw Grantlee::Exception(TagSyntaxError, value.toString()); } ScriptableNodeFactory::ScriptableNodeFactory(QObject *parent) : AbstractNodeFactory(parent), m_scriptEngine(0) { } -void ScriptableNodeFactory::setScriptEngine(QScriptEngine *engine) +void ScriptableNodeFactory::setScriptEngine(QJSEngine *engine) { m_scriptEngine = engine; } @@ -112,42 +79,35 @@ m_scriptEngine->setProperty("templateEngine", QVariant::fromValue(engine)); } -void ScriptableNodeFactory::setFactory(const QScriptValue &factoryMethod) +void ScriptableNodeFactory::setFactory(const QJSValue &factoryMethod) { m_factoryMethod = factoryMethod; } Node *ScriptableNodeFactory::getNode(const QString &tagContent, Parser *p) const { - if (m_scriptEngine->hasUncaughtException()) { - throw Grantlee::Exception(TagSyntaxError, - m_scriptEngine->uncaughtExceptionBacktrace().join( - QChar::fromLatin1(' '))); - } auto sp = new ScriptableParser(p, m_scriptEngine); auto parserObject = m_scriptEngine->newQObject(sp); - QScriptValueList args; + QJSValueList args; args << tagContent; args << parserObject; auto factory = m_factoryMethod; - auto scriptNode = factory.call(factory, args); - if (m_scriptEngine->hasUncaughtException()) - throw Grantlee::Exception(TagSyntaxError, - m_scriptEngine->uncaughtExceptionBacktrace().join( - QChar::fromLatin1(' '))); + QJSValue scriptNode = factory.callWithInstance(factory, args); + if (scriptNode.isError()) + throw Grantlee::Exception(TagSyntaxError, scriptNode.toString()); - auto node = qscriptvalue_cast(scriptNode); + auto node = qjsvalue_cast(scriptNode); node->setParent(p); return node; } -QScriptEngine *ScriptableNode::engine() { return m_scriptEngine; } +QJSEngine *ScriptableNode::engine() { return m_scriptEngine; } void ScriptableNode::setNodeList(const QString &name, - const QObjectList &objectList) + const QList &objectList) { auto objectListArray = m_scriptEngine->newArray(objectList.size()); Index: templates/scriptabletags/scriptableparser.h =================================================================== --- templates/scriptabletags/scriptableparser.h +++ templates/scriptabletags/scriptableparser.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "token.h" @@ -39,24 +39,25 @@ { Q_OBJECT public: - explicit ScriptableParser(Parser *p, QObject *parent = 0); + explicit ScriptableParser(Parser *p, QJSEngine *engine); Parser *parser() { return m_p; } public Q_SLOTS: - QObjectList parse(QObject *parent, const QString &stopAt); - QObjectList parse(QObject *parent, const QStringList &stopAt = QStringList()); + QList parse(QObject *parent, const QString &stopAt); + QList parse(QObject *parent, const QStringList &stopAt = QStringList()); void skipPast(const QString &tag); - Token takeNextToken(); + QJSValue takeNextToken(); bool hasNextToken() const; void removeNextToken(); void loadLib(const QString &name); private: Parser *m_p; + QJSEngine *m_engine; }; #endif Index: templates/scriptabletags/scriptableparser.cpp =================================================================== --- templates/scriptabletags/scriptableparser.cpp +++ templates/scriptabletags/scriptableparser.cpp @@ -22,9 +22,10 @@ #include "scriptablenode.h" #include "parser.h" +#include -ScriptableParser::ScriptableParser(Grantlee::Parser *p, QObject *parent) - : QObject(parent), m_p(p) +ScriptableParser::ScriptableParser(Grantlee::Parser *p, QJSEngine *engine) + : QObject(engine), m_p(p), m_engine(engine) { } @@ -34,16 +35,23 @@ void ScriptableParser::loadLib(const QString &name) { m_p->loadLib(name); } -Token ScriptableParser::takeNextToken() { return m_p->takeNextToken(); } +QJSValue ScriptableParser::takeNextToken() +{ + Token t = m_p->takeNextToken(); + auto obj = m_engine->newObject(); + obj.setProperty(QStringLiteral("tokenType"), t.tokenType); + obj.setProperty(QStringLiteral("content"), t.content); + return obj; +} void ScriptableParser::skipPast(const QString &tag) { m_p->skipPast(tag); } -QObjectList ScriptableParser::parse(QObject *parent, const QString &stopAt) +QList ScriptableParser::parse(QObject *parent, const QString &stopAt) { return parse(parent, QStringList() << stopAt); } -QObjectList ScriptableParser::parse(QObject *parent, const QStringList &stopAt) +QList ScriptableParser::parse(QObject *parent, const QStringList &stopAt) { auto node = qobject_cast(parent); Q_ASSERT(node); Index: templates/scriptabletags/scriptablesafestring.h =================================================================== --- templates/scriptabletags/scriptablesafestring.h +++ templates/scriptabletags/scriptablesafestring.h @@ -22,16 +22,12 @@ #define SCRIPTABLE_SAFESTRING #include -#include +#include #include "safestring.h" -class QScriptContext; - using namespace Grantlee; -QScriptValue markSafeFunction(QScriptContext *context, QScriptEngine *engine); - class ScriptableSafeString : public QObject { Q_OBJECT Index: templates/scriptabletags/scriptablesafestring.cpp =================================================================== --- templates/scriptabletags/scriptablesafestring.cpp +++ templates/scriptabletags/scriptablesafestring.cpp @@ -20,30 +20,7 @@ #include "scriptablesafestring.h" -#include - -#include "util.h" - -QScriptValue markSafeFunction(QScriptContext *context, QScriptEngine *engine) -{ - auto inputValue = context->argument(0); - if (inputValue.isQObject()) { - auto obj = inputValue.toQObject(); - auto ssObj = qobject_cast(obj); - if (!ssObj) - return engine->nullValue(); - - ssObj->setSafety(true); - return engine->newQObject(ssObj); - - } else if (inputValue.isString()) { - auto str = inputValue.toString(); - auto ssObj = new ScriptableSafeString(engine); - ssObj->setContent(markSafe(str)); - return engine->newQObject(ssObj); - } - return engine->nullValue(); -} +#include ScriptableSafeString::ScriptableSafeString(QObject *parent) : QObject(parent) {} Index: templates/scriptabletags/scriptabletags.h =================================================================== --- templates/scriptabletags/scriptabletags.h +++ templates/scriptabletags/scriptabletags.h @@ -24,18 +24,32 @@ #include "node.h" #include "taglibraryinterface.h" -// #include +#include -// #include -// typedef QSharedPointer ScriptEnginePointer; +// #include +// typedef QSharedPointer ScriptEnginePointer; -class QScriptEngine; +QT_FORWARD_DECLARE_CLASS(QJSEngine) namespace Grantlee { class Engine; class Parser; +class ScriptableHelperFunctions : public QObject +{ + Q_OBJECT + QJSEngine *m_scriptEngine; +public: + ScriptableHelperFunctions(QJSEngine *scriptEngine) : m_scriptEngine(scriptEngine) { } + + Q_INVOKABLE QJSValue markSafeFunction(QJSValue inputValue); + Q_INVOKABLE QJSValue ScriptableFilterExpressionConstructor(QString name, QObject *parserObj = nullptr); + Q_INVOKABLE QJSValue ScriptableNodeConstructor(QJSValue callContext); + Q_INVOKABLE QJSValue ScriptableVariableConstructor(QString name); + Q_INVOKABLE QJSValue ScriptableTemplateConstructor(QString content, QString name, QObject *parent); +}; + class ScriptableTagLibrary : public QObject, public TagLibraryInterface { Q_OBJECT @@ -60,7 +74,8 @@ private: // ScriptEnginePointer m_scriptEngine; - QScriptEngine *m_scriptEngine; + QJSEngine *m_scriptEngine; + QJSValue m_functions; QHash m_nodeFactories; QHash m_factoryNames; QStringList m_filterNames; Index: templates/scriptabletags/scriptabletags.cpp =================================================================== --- templates/scriptabletags/scriptabletags.cpp +++ templates/scriptabletags/scriptabletags.cpp @@ -23,82 +23,152 @@ #include #include -#include +#include +#include #include "nodebuiltins_p.h" +#include "engine.h" #include "exception.h" +#include "parser.h" #include "scriptablefilter.h" #include "scriptablefilterexpression.h" #include "scriptablenode.h" #include "scriptablesafestring.h" #include "scriptabletemplate.h" #include "scriptablevariable.h" #include "token.h" +#include "util.h" Q_DECLARE_METATYPE(Token) using namespace Grantlee; -QScriptValue tokenToScriptValue(QScriptEngine *engine, const Token &t) +QJSValue tokenToScriptValue(QJSEngine *engine, const Token &t) { auto obj = engine->newObject(); obj.setProperty(QStringLiteral("tokenType"), t.tokenType); obj.setProperty(QStringLiteral("content"), t.content); return obj; } -void tokenFromScriptValue(const QScriptValue &obj, Token &t) +void tokenFromScriptValue(const QJSValue &obj, Token &t) { - t.tokenType = obj.property(QStringLiteral("tokenType")).toInt32(); + t.tokenType = obj.property(QStringLiteral("tokenType")).toInt(); t.content = obj.property(QStringLiteral("content")).toString(); } -ScriptableTagLibrary::ScriptableTagLibrary(QObject *parent) - : QObject(parent), m_scriptEngine(0) +QJSValue ScriptableHelperFunctions::markSafeFunction(QJSValue inputValue) +{ + if (inputValue.isQObject()) { + auto obj = inputValue.toQObject(); + auto ssObj = qobject_cast(obj); + if (!ssObj) + return QJSValue::NullValue; + + ssObj->setSafety(true); + return m_scriptEngine->newQObject(ssObj); + + } else if (inputValue.isString()) { + auto str = inputValue.toString(); + auto ssObj = new ScriptableSafeString(m_scriptEngine); + ssObj->setContent(markSafe(str)); + return m_scriptEngine->newQObject(ssObj); + } + return QJSValue::NullValue; +} + + +QJSValue ScriptableHelperFunctions::ScriptableFilterExpressionConstructor(QString name, QObject *parserObj) +{ + auto object = new ScriptableFilterExpression(m_scriptEngine); + + auto p = qobject_cast(parserObj); + + object->init(name, p); + + return m_scriptEngine->newQObject(object); +} + +QJSValue ScriptableHelperFunctions::ScriptableNodeConstructor(QJSValue callContext) +{ + QJSValueIterator it(callContext); + it.next(); + QString scriptableNodeName = it.value().toString(); + auto concreteConstructor = m_scriptEngine->globalObject().property(scriptableNodeName); + if (concreteConstructor.isError()) + return concreteConstructor; + + QJSValueList args; + while (it.next()) + args << it.value(); + + auto concreteNode = concreteConstructor.callAsConstructor(args); + if (concreteNode.isError()) + return concreteNode; + + auto renderMethod = concreteNode.property(QStringLiteral("render")); + if (renderMethod.isError()) + return renderMethod; + + auto object = new ScriptableNode(m_scriptEngine); + object->setObjectName(scriptableNodeName); + object->setScriptEngine(m_scriptEngine); + object->init(concreteNode, renderMethod); + return m_scriptEngine->newQObject(object); +} + +QJSValue ScriptableHelperFunctions::ScriptableTemplateConstructor(QString content, QString name, QObject *parent) { - m_scriptEngine = new QScriptEngine(this); + auto templateEngine = m_scriptEngine->property("templateEngine").value(); - qScriptRegisterMetaType(m_scriptEngine, tokenToScriptValue, - tokenFromScriptValue); - qScriptRegisterMetaType(m_scriptEngine, nodeToScriptValue, - nodeFromScriptValue); - // qScriptRegisterMetaType(m_scriptEngine.data(), tokenToScriptValue, - // tokenFromScriptValue); - // qScriptRegisterMetaType(m_scriptEngine.data(), nodeToScriptValue, - // nodeFromScriptValue); + if (!templateEngine) + return QJSValue(); + + auto t = templateEngine->newTemplate(content, name); + + auto object = new ScriptableTemplate(t, parent); + return m_scriptEngine->newQObject(object); +} + +QJSValue ScriptableHelperFunctions::ScriptableVariableConstructor(QString name) +{ + // TODO: Decide what the parent should be; + // It should be the owning scriptableNode. I think I can get that from the + // scriptContext. + + QObject *parent = 0; + auto object = new ScriptableVariable(m_scriptEngine, parent); + object->setContent(name); + + return m_scriptEngine->newQObject(object); +} + + +ScriptableTagLibrary::ScriptableTagLibrary(QObject *parent) + : QObject(parent) + , m_scriptEngine(new QJSEngine(this)) + , m_functions(m_scriptEngine->newQObject(new ScriptableHelperFunctions(m_scriptEngine))) +{ + m_scriptEngine->globalObject().setProperty(QStringLiteral("functions"), m_functions); // Make Node new-able - auto nodeCtor = m_scriptEngine->newFunction(ScriptableNodeConstructor); - auto nodeMetaObject = m_scriptEngine->newQMetaObject( - &ScriptableNode::staticMetaObject, nodeCtor); m_scriptEngine->globalObject().setProperty(QStringLiteral("Node"), - nodeMetaObject); + m_scriptEngine->evaluate( + QStringLiteral( + "(function() { return functions.ScriptableNodeConstructor(Array.prototype.slice.call(arguments)); })"))); // Make Variable new-able - auto variableCtor - = m_scriptEngine->newFunction(ScriptableVariableConstructor); - auto variableMetaObject = m_scriptEngine->newQMetaObject( - &VariableNode::staticMetaObject, variableCtor); m_scriptEngine->globalObject().setProperty(QStringLiteral("Variable"), - variableMetaObject); - + m_functions.property(QStringLiteral("ScriptableVariableConstructor"))); // Make FilterExpression new-able - auto filterExpressionCtor - = m_scriptEngine->newFunction(ScriptableFilterExpressionConstructor); - auto filterExpressionMetaObject = m_scriptEngine->newQMetaObject( - &ScriptableFilterExpression::staticMetaObject, filterExpressionCtor); m_scriptEngine->globalObject().setProperty(QStringLiteral("FilterExpression"), - filterExpressionMetaObject); + m_functions.property(QStringLiteral("ScriptableFilterExpressionConstructor"))); // Make Template new-able - auto templateCtor - = m_scriptEngine->newFunction(ScriptableTemplateConstructor); - auto templateMetaObject = m_scriptEngine->newQMetaObject( - &ScriptableTemplate::staticMetaObject, templateCtor); m_scriptEngine->globalObject().setProperty(QStringLiteral("Template"), - templateMetaObject); + m_functions.property(QStringLiteral("ScriptableTemplateConstructor"))); // Create a global Library object auto libraryObject = m_scriptEngine->newQObject(this); @@ -112,9 +182,8 @@ QStringLiteral("AbstractNodeFactory"), nodeFactoryObject); // Make mark_safe a globally available object. - auto markSafeFunctionObject = m_scriptEngine->newFunction(markSafeFunction); m_scriptEngine->globalObject().setProperty(QStringLiteral("mark_safe"), - markSafeFunctionObject); + m_functions.property(QStringLiteral("markSafeFunction"))); } bool ScriptableTagLibrary::evaluateScript(const QString &name) @@ -132,13 +201,10 @@ scriptFile.close(); - m_scriptEngine->evaluate(fileContent); + QJSValue result = m_scriptEngine->evaluate(fileContent); + if (result.isError()) + throw Grantlee::Exception(TagSyntaxError, result.toString()); - if (m_scriptEngine->hasUncaughtException()) { - throw Grantlee::Exception(TagSyntaxError, - m_scriptEngine->uncaughtExceptionBacktrace().join( - QChar::fromLatin1(' '))); - } return true; } @@ -179,6 +245,8 @@ auto tagName = it.key(); auto factoryObject = m_scriptEngine->globalObject().property(factoryName); + if (factoryObject.isError()) + throw Grantlee::Exception(UnknownFilterError, factoryObject.toString()); auto snf = new ScriptableNodeFactory(); snf->setScriptEngine(m_scriptEngine); @@ -197,16 +265,15 @@ QListIterator it(m_filterNames); while (it.hasNext()) { auto filterObject = m_scriptEngine->globalObject().property(it.next()); - auto filterName - = filterObject.property(QStringLiteral("filterName")).toString(); + if (filterObject.isError()) + throw Grantlee::Exception(TagSyntaxError, filterObject.toString()); + auto filterNameObj = filterObject.property(QStringLiteral("filterName")); + if (filterNameObj.isError()) + throw Grantlee::Exception(TagSyntaxError, filterNameObj.toString()); + auto filterName = filterNameObj.toString(); auto filter = new ScriptableFilter(filterObject, m_scriptEngine); filters.insert(filterName, filter); } - if (m_scriptEngine->hasUncaughtException()) { - throw Grantlee::Exception(TagSyntaxError, - m_scriptEngine->uncaughtExceptionBacktrace().join( - QChar::fromLatin1(' '))); - } return filters; } Index: templates/scriptabletags/scriptabletemplate.h =================================================================== --- templates/scriptabletags/scriptabletemplate.h +++ templates/scriptabletags/scriptabletemplate.h @@ -24,24 +24,17 @@ #include #include -#include - #include "template.h" namespace Grantlee { class Node; } -class QScriptContext; - class ScriptableContext; using namespace Grantlee; -QScriptValue ScriptableTemplateConstructor(QScriptContext *context, - QScriptEngine *engine); - class ScriptableTemplate : public QObject { Q_OBJECT @@ -51,9 +44,9 @@ public Q_SLOTS: QString render(ScriptableContext *c) const; - QObjectList nodeList() const; + QList nodeList() const; - void setNodeList(const QObjectList &list); + void setNodeList(const QList &list); private: Template m_template; Index: templates/scriptabletags/scriptabletemplate.cpp =================================================================== --- templates/scriptabletags/scriptabletemplate.cpp +++ templates/scriptabletags/scriptabletemplate.cpp @@ -20,31 +20,11 @@ #include "scriptabletemplate.h" -#include -#include - #include "context.h" #include "engine.h" #include "node.h" #include "scriptablecontext.h" -QScriptValue ScriptableTemplateConstructor(QScriptContext *context, - QScriptEngine *engine) -{ - auto content = context->argument(0).toString(); - auto name = context->argument(1).toString(); - auto parent = context->argument(2).toQObject(); - auto templateEngine = engine->property("templateEngine").value(); - - if (!templateEngine) - return QScriptValue(); - - auto t = templateEngine->newTemplate(content, name); - - auto object = new ScriptableTemplate(t, parent); - return engine->newQObject(object); -} - ScriptableTemplate::ScriptableTemplate(Grantlee::Template t, QObject *parent) : QObject(parent), m_template(t) { @@ -55,7 +35,7 @@ return m_template->render(c->context()); } -QObjectList ScriptableTemplate::nodeList() const +QList ScriptableTemplate::nodeList() const { auto nodeList = m_template->nodeList(); QObjectList objList; @@ -67,7 +47,7 @@ return objList; } -void ScriptableTemplate::setNodeList(const QObjectList &list) +void ScriptableTemplate::setNodeList(const QList &list) { NodeList nodeList; Index: templates/scriptabletags/scriptablevariable.h =================================================================== --- templates/scriptabletags/scriptablevariable.h +++ templates/scriptabletags/scriptablevariable.h @@ -22,36 +22,31 @@ #define SCRIPTABLE_VARIABLE_H #include -#include +#include #include "variable.h" -class QScriptContext; - class ScriptableContext; using namespace Grantlee; -QScriptValue ScriptableVariableConstructor(QScriptContext *context, - QScriptEngine *engine); - class ScriptableVariable : public QObject { Q_OBJECT public: ScriptableVariable(QObject *parent = 0); - ScriptableVariable(QScriptEngine *engine, QObject *parent = 0); + ScriptableVariable(QJSEngine *engine, QObject *parent = 0); void setContent(const QString &content); public Q_SLOTS: - QVariant resolve(ScriptableContext *c); + QVariant resolve(QObject *c); - bool isTrue(ScriptableContext *c); + bool isTrue(QObject *c); private: Variable m_variable; - QScriptEngine *m_engine; + QJSEngine *m_engine; }; #endif Index: templates/scriptabletags/scriptablevariable.cpp =================================================================== --- templates/scriptabletags/scriptablevariable.cpp +++ templates/scriptabletags/scriptablevariable.cpp @@ -20,35 +20,18 @@ #include "scriptablevariable.h" -#include -#include +#include #include "scriptablecontext.h" #include "scriptablesafestring.h" #include "util.h" -Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptableVariable, QObject *) - -QScriptValue ScriptableVariableConstructor(QScriptContext *context, - QScriptEngine *engine) -{ - // TODO: Decide what the parent should be; - // It should be the owning scriptableNode. I think I can get that from the - // scriptContext. - - QObject *parent = 0; - auto object = new ScriptableVariable(engine, parent); - object->setContent(context->argument(0).toString()); - - return engine->newQObject(object); -} - ScriptableVariable::ScriptableVariable(QObject *parent) : QObject(parent), m_engine(0) { } -ScriptableVariable::ScriptableVariable(QScriptEngine *engine, QObject *parent) +ScriptableVariable::ScriptableVariable(QJSEngine *engine, QObject *parent) : QObject(parent), m_engine(engine) { } @@ -58,9 +41,9 @@ m_variable = Variable(content); } -QVariant ScriptableVariable::resolve(ScriptableContext *c) +QVariant ScriptableVariable::resolve(QObject *c) { - auto var = m_variable.resolve(c->context()); + auto var = m_variable.resolve(qobject_cast(c)->context()); if (Grantlee::isSafeString(var)) { auto ssObj = new ScriptableSafeString(m_engine); @@ -70,7 +53,7 @@ return var; } -bool ScriptableVariable::isTrue(ScriptableContext *c) +bool ScriptableVariable::isTrue(QObject *c) { - return m_variable.isTrue(c->context()); + return m_variable.isTrue(qobject_cast(c)->context()); } Index: templates/tests/CMakeLists.txt =================================================================== --- templates/tests/CMakeLists.txt +++ templates/tests/CMakeLists.txt @@ -99,8 +99,8 @@ add_test(${_testname} ${_testname}_exec ) target_link_libraries(${_testname}_exec Grantlee5::Templates template_test_builtins) - if (Qt5Script_FOUND) - target_compile_definitions(${_testname}_exec PRIVATE HAVE_QTSCRIPT_LIB) + if (Qt5Qml_FOUND) + target_compile_definitions(${_testname}_exec PRIVATE HAVE_QTQML_LIB) endif() set_property(GLOBAL APPEND PROPERTY TEST_COVERAGE "${CMAKE_CURRENT_BINARY_DIR}/${_testname}_exec" ) @@ -119,7 +119,7 @@ # benchmarks ) -if (Qt5Script_FOUND) +if (Qt5Qml_FOUND) grantlee_templates_unit_tests( testscriptabletags ) Index: templates/tests/testloadertags.cpp =================================================================== --- templates/tests/testloadertags.cpp +++ templates/tests/testloadertags.cpp @@ -77,7 +77,7 @@ << QStringLiteral(GRANTLEE_PLUGIN_PATH) << QStringLiteral(":/plugins/") // For testtags.qs ); -#ifdef HAVE_QTSCRIPT_LIB +#ifdef HAVE_QTQML_LIB m_engine->addDefaultLibrary(QStringLiteral("grantlee_scriptabletags")); #endif } @@ -300,7 +300,7 @@ "{% extends 'inheritance15' %}{% block inner %}out{% endblock %}") << dict << QStringLiteral("12out3_") << NoError; -#ifdef HAVE_QTSCRIPT_LIB +#ifdef HAVE_QTQML_LIB // {% load %} tag (parent -- setup for exception04) auto inh17 = QStringLiteral( "{% load testtags %}{% block first %}1234{% endblock %}");