aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/jsextensions/domxml.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/corelib/jsextensions/domxml.cpp')
-rw-r--r--src/lib/corelib/jsextensions/domxml.cpp740
1 files changed, 414 insertions, 326 deletions
diff --git a/src/lib/corelib/jsextensions/domxml.cpp b/src/lib/corelib/jsextensions/domxml.cpp
index 86e1574c6..35cff186b 100644
--- a/src/lib/corelib/jsextensions/domxml.cpp
+++ b/src/lib/corelib/jsextensions/domxml.cpp
@@ -38,428 +38,516 @@
**
****************************************************************************/
+#include "jsextension.h"
+
#include <language/scriptengine.h>
#include <QtCore/qfile.h>
-#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
-#include <QtScript/qscriptengine.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptable.h>
-
#include <QtXml/qdom.h>
namespace qbs {
namespace Internal {
-class XmlDomDocument;
-
-class XmlDomNode: public QObject, public QScriptable
+template<class C> class XmlDomNode : public JsExtension<XmlDomNode<C>>
{
- Q_OBJECT
public:
- static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine);
-
- Q_INVOKABLE bool isElement() const;
- Q_INVOKABLE bool isCDATASection() const;
- Q_INVOKABLE bool isText() const;
-
- Q_INVOKABLE QString attribute(const QString & name, const QString & defValue = QString());
- Q_INVOKABLE void setAttribute(const QString & name, const QString & value);
- Q_INVOKABLE bool hasAttribute(const QString & name) const;
- Q_INVOKABLE QString tagName() const;
- Q_INVOKABLE void setTagName(const QString & name);
-
- Q_INVOKABLE QString text() const;
-
- Q_INVOKABLE QString data() const;
- Q_INVOKABLE void setData(const QString &v) const;
-
- Q_INVOKABLE void clear();
- Q_INVOKABLE bool hasAttributes() const;
- Q_INVOKABLE bool hasChildNodes() const;
- Q_INVOKABLE QScriptValue parentNode() const;
- Q_INVOKABLE QScriptValue firstChild(const QString & tagName = QString());
- Q_INVOKABLE QScriptValue lastChild(const QString & tagName = QString()) const;
- Q_INVOKABLE QScriptValue previousSibling(const QString & tagName = QString()) const;
- Q_INVOKABLE QScriptValue nextSibling(const QString & tagName = QString()) const;
-
- Q_INVOKABLE QScriptValue appendChild(const QScriptValue &newChild);
- Q_INVOKABLE QScriptValue insertBefore(const QScriptValue& newChild, const QScriptValue& refChild);
- Q_INVOKABLE QScriptValue insertAfter(const QScriptValue& newChild, const QScriptValue& refChild);
- Q_INVOKABLE QScriptValue replaceChild(const QScriptValue& newChild, const QScriptValue& oldChild);
- Q_INVOKABLE QScriptValue removeChild(const QScriptValue& oldChild);
-
-protected:
- friend class XmlDomDocument;
- XmlDomNode(const QDomNode &other = QDomNode());
- QDomNode m_domNode;
-};
+ static const char *name();
+ XmlDomNode(const C &value) : m_value(value) {}
+ XmlDomNode(JSContext *, const QString &name);
+ XmlDomNode(JSContext *) {}
-class XmlDomDocument: public XmlDomNode
-{
- Q_OBJECT
-public:
- static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine);
- Q_INVOKABLE QScriptValue documentElement();
- Q_INVOKABLE QScriptValue createElement(const QString & tagName);
- Q_INVOKABLE QScriptValue createCDATASection(const QString & value);
- Q_INVOKABLE QScriptValue createTextNode(const QString & value);
-
- Q_INVOKABLE bool setContent(const QString & content);
- Q_INVOKABLE QString toString(int indent = 1);
+ static JSValue ctor(JSContext *ctx, JSValueConst, JSValueConst,
+ int argc, JSValueConst *argv, int);
+ static void setupMethods(JSContext *ctx, JSValue obj);
- Q_INVOKABLE void save(const QString & filePath, int indent = 1);
- Q_INVOKABLE void load(const QString & filePath);
-
-protected:
- XmlDomDocument(QScriptContext *context, const QString &name = QString());
+ C value() const { return m_value; }
private:
- QDomDocument m_domDocument;
-};
-
-QScriptValue XmlDomDocument::ctor(QScriptContext *context, QScriptEngine *engine)
-{
- XmlDomDocument *xml = nullptr;
- switch (context->argumentCount()) {
- case 0:
- xml = new XmlDomDocument(context);
- break;
- case 1:
- xml = new XmlDomDocument(context, context->argument(0).toString());
- break;
- default:
- return context->throwError(QStringLiteral("DomXml(QString file = QLatin1String(\"\"))"));
- }
- QScriptValue obj = engine->newQObject(xml, QScriptEngine::ScriptOwnership);
- static_cast<ScriptEngine *>(engine)->setUsesIo();
- return obj;
-}
-
-QScriptValue XmlDomDocument::documentElement()
-{
- return engine()->newQObject(new XmlDomNode(m_domDocument.documentElement()), QScriptEngine::ScriptOwnership);
-}
-
-QScriptValue XmlDomDocument::createElement(const QString &tagName)
-{
- return engine()->newQObject(new XmlDomNode(m_domDocument.createElement(tagName)), QScriptEngine::ScriptOwnership);
-}
-
-QScriptValue XmlDomDocument::createCDATASection(const QString &value)
-{
- return engine()->newQObject(new XmlDomNode(m_domDocument.createCDATASection(value)), QScriptEngine::ScriptOwnership);
-}
-
-QScriptValue XmlDomDocument::createTextNode(const QString &value)
-{
- return engine()->newQObject(new XmlDomNode(m_domDocument.createTextNode(value)), QScriptEngine::ScriptOwnership);
-}
-
-bool XmlDomDocument::setContent(const QString &content)
-{
- return m_domDocument.setContent(content);
-}
-
-QString XmlDomDocument::toString(int indent)
-{
- return m_domDocument.toString(indent);
-}
-
-void XmlDomDocument::save(const QString &filePath, int indent)
-{
- QFile f(filePath);
- if (!f.open(QIODevice::WriteOnly)) {
- context()->throwError(QStringLiteral("unable to open '%1'")
- .arg(filePath));
- return;
+#define XML_JS_FWD(name, func, text) DEFINE_JS_FORWARDER_QUAL(XmlDomNode, name, func, text)
+
+ XML_JS_FWD(jsIsElement, &XmlDomNode::isElement, "DomNode.isElement");
+ XML_JS_FWD(jsIsCDATASection, &XmlDomNode::isCDATASection, "DomNode.isCDATASection");
+ XML_JS_FWD(jsIsText, &XmlDomNode::isText, "DomNode.isText");
+ XML_JS_FWD(jsHasAttribute, &XmlDomNode::hasAttribute, "DomNode.hasAttribute");
+ XML_JS_FWD(jsTagName, &XmlDomNode::tagName, "DomNode.tagName");
+ XML_JS_FWD(jsSetTagName, &XmlDomNode::setTagName, "DomNode.setTagName");
+ XML_JS_FWD(jsText, &XmlDomNode::text, "DomNode.text");
+ XML_JS_FWD(jsData, &XmlDomNode::data, "DomNode.data");
+ XML_JS_FWD(jsSetData, &XmlDomNode::setData, "DomNode.setData");
+ XML_JS_FWD(jsClear, &XmlDomNode::clear, "DomNode.clear");
+ XML_JS_FWD(jsHasAttributes, &XmlDomNode::hasAttributes, "DomNode.hasAttributes");
+ XML_JS_FWD(jsHasChildNodes, &XmlDomNode::hasChildNodes, "DomNode.hasChildNodes");
+ XML_JS_FWD(jsSetAttribute, &XmlDomNode::setAttribute, "DomNode.setAttribute");
+ XML_JS_FWD(jsAppendChild, &XmlDomNode::appendChild, "DomNode.appendChild");
+ XML_JS_FWD(jsInsertBefore, &XmlDomNode::insertBefore, "DomNode.insertBefore");
+ XML_JS_FWD(jsInsertAfter, &XmlDomNode::insertAfter, "DomNode.insertAfter");
+ XML_JS_FWD(jsReplaceChild, &XmlDomNode::replaceChild, "DomNode.replaceChild");
+ XML_JS_FWD(jsRemoveChild, &XmlDomNode::removeChild, "DomNode.removeChild");
+
+ static JSValue jsAttribute(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
+ {
+ try {
+ const auto name = JsExtension<XmlDomNode>::template getArgument<QString>
+ (ctx, "DomNode.attribute", argc, argv);
+ QString defaultValue;
+ if (argc > 1)
+ defaultValue = JsExtension<XmlDomNode>::template fromArg<QString>
+ (ctx, "DomNode.attribute", 2, argv[1]);
+ return makeJsString(ctx, JsExtension<XmlDomNode>::fromJsObject
+ (ctx, this_val)->attribute(name, defaultValue));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
}
-
- QByteArray buff(m_domDocument.toByteArray(indent));
- if (buff.size() != f.write(buff))
+ static JSValue jsParentNode(JSContext *ctx, JSValueConst this_val, int, JSValueConst *)
{
- context()->throwError(f.errorString());
- f.close();
- return;
+ return JsExtension<XmlDomNode<QDomNode>>::createObjectDirect(
+ ctx, JsExtension<XmlDomNode>::fromJsObject(ctx, this_val)->parentNode());
}
-
- f.close();
- if (f.error() != QFile::NoError)
- context()->throwError(f.errorString());
-}
-
-void XmlDomDocument::load(const QString &filePath)
-{
- QFile f(filePath);
- if (!f.open(QIODevice::ReadOnly)) {
- context()->throwError(QStringLiteral("unable to open '%1'")
- .arg(filePath));
- return;
+ static JSValue jsFirstChild(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
+ {
+ try {
+ QString tagName;
+ if (argc > 0)
+ tagName = JsExtension<XmlDomNode>::template getArgument<QString>
+ (ctx, "DomNode.firstChild", argc, argv);
+ return JsExtension<XmlDomNode<QDomNode>>::createObjectDirect
+ (ctx, JsExtension<XmlDomNode>::fromJsObject(ctx, this_val)->firstChild(tagName));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
+ }
+ static JSValue jsLastChild(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
+ {
+ try {
+ QString tagName;
+ if (argc > 0)
+ tagName = JsExtension<XmlDomNode>::template getArgument<QString>
+ (ctx, "DomNode.lastChild", argc, argv);
+ return JsExtension<XmlDomNode<QDomNode>>::createObjectDirect
+ (ctx, JsExtension<XmlDomNode>::fromJsObject(ctx, this_val)->lastChild(tagName));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
+ }
+ static JSValue jsPreviousSibling(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+ {
+ try {
+ QString tagName;
+ if (argc > 0)
+ tagName = JsExtension<XmlDomNode>::template getArgument<QString>
+ (ctx, "DomNode.previousSibling", argc, argv);
+ return JsExtension<XmlDomNode<QDomNode>>::createObjectDirect(ctx, JsExtension<XmlDomNode>::fromJsObject
+ (ctx, this_val)->previousSibling(tagName));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
+ }
+ static JSValue jsNextSibling(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+ {
+ try {
+ QString tagName;
+ if (argc > 0)
+ tagName = JsExtension<C>::template getArgument<QString>
+ (ctx, "Xml.DomElement.nextSibling", argc, argv);
+ return JsExtension<XmlDomNode<QDomNode>>::createObjectDirect
+ (ctx, JsExtension<XmlDomNode>::fromJsObject(ctx, this_val)->nextSibling(tagName));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
}
- QString errorMsg;
- if (!m_domDocument.setContent(&f, &errorMsg)) {
- context()->throwError(errorMsg);
- return;
+ // Implemented for QDomDocument only.
+ static JSValue jsDocumentElement(JSContext *ctx, JSValueConst this_val, int, JSValueConst *);
+ static JSValue jsCreateElement(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+ static JSValue jsCreateCDATASection(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+ static JSValue jsCreateTextNode(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+ static JSValue jsSetContent(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
+ static JSValue jsToString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
+ static JSValue jsSave(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
+ static JSValue jsLoad(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
+
+ bool isElement() const { return m_value.isElement(); }
+ bool isCDATASection() const { return m_value.isCDATASection(); }
+ bool isText() const { return m_value.isText(); }
+ QString attribute(const QString &name, const QString &defaultValue)
+ {
+ QDomElement el = m_value.toElement();
+ if (el.isNull())
+ throw QStringLiteral("Node '%1' is not an element node").arg(m_value.nodeName());
+ return el.attribute(name, defaultValue);
+ }
+ void setAttribute(const QString &name, const QString &value)
+ {
+ QDomElement el = m_value.toElement();
+ if (el.isNull())
+ throw QStringLiteral("Node '%1' is not an element node").arg(m_value.nodeName());
+ el.setAttribute(name, value);
+ }
+ bool hasAttribute(const QString &name) const
+ {
+ QDomElement el = m_value.toElement();
+ if (el.isNull())
+ throw QStringLiteral("Node '%1' is not an element node").arg(m_value.nodeName());
+ return el.hasAttribute(name);
+ }
+ QString tagName() const
+ {
+ QDomElement el = m_value.toElement();
+ if (el.isNull())
+ throw QStringLiteral("Node '%1' is not an element node").arg(m_value.nodeName());
+ return el.tagName();
+ }
+ void setTagName(const QString &name)
+ {
+ QDomElement el = m_value.toElement();
+ if (el.isNull())
+ throw QStringLiteral("Node '%1' is not an element node").arg(m_value.nodeName());
+ el.setTagName(name);
}
-}
-XmlDomDocument::XmlDomDocument(QScriptContext *context, const QString &name):m_domDocument(name)
-{
- Q_UNUSED(context)
- m_domNode = m_domDocument;
-}
+ QString text() const
+ {
+ QDomElement el = m_value.toElement();
+ if (el.isNull())
+ throw QStringLiteral("Node '%1' is not an element node").arg(m_value.nodeName());
+ return el.text();
+ }
-QScriptValue XmlDomNode::ctor(QScriptContext *context, QScriptEngine *engine)
-{
- Q_UNUSED(context)
- return engine->newQObject(new XmlDomNode(), QScriptEngine::ScriptOwnership);
-}
+ QString data() const
+ {
+ if (m_value.isText())
+ return m_value.toText().data();
+ if (m_value.isCDATASection())
+ return m_value.toCDATASection().data();
+ if (m_value.isCharacterData())
+ return m_value.toCharacterData().data();
+ throw QStringLiteral("Node '%1' is not a character data node").arg(m_value.nodeName());
+ }
+ void setData(const QString &v) const
+ {
+ if (m_value.isText())
+ return m_value.toText().setData(v);
+ if (m_value.isCDATASection())
+ return m_value.toCDATASection().setData(v);
+ if (m_value.isCharacterData())
+ return m_value.toCharacterData().setData(v);
+ throw QStringLiteral("Node '%1' is not a character data node").arg(m_value.nodeName());
+ }
+ void clear() { m_value.clear(); }
+ bool hasAttributes() const { return m_value.hasAttributes(); }
+ bool hasChildNodes() const { return m_value.hasChildNodes(); }
-bool XmlDomNode::isElement() const
-{
- return m_domNode.isElement();
-}
+ XmlDomNode<QDomNode> *parentNode() const
+ {
+ return new XmlDomNode<QDomNode>(m_value.parentNode());
+ }
+ XmlDomNode<QDomNode> *firstChild(const QString &tagName)
+ {
+ if (tagName.isEmpty())
+ return new XmlDomNode<QDomNode>(m_value.firstChild());
+ return new XmlDomNode<QDomNode>(m_value.firstChildElement(tagName));
+ }
+ XmlDomNode<QDomNode> *lastChild(const QString &tagName) const
+ {
+ if (tagName.isEmpty())
+ return new XmlDomNode<QDomNode>(m_value.lastChild());
+ return new XmlDomNode<QDomNode>(m_value.lastChildElement(tagName));
+ }
+ XmlDomNode<QDomNode> *previousSibling(const QString &tagName) const
+ {
+ if (tagName.isEmpty())
+ return new XmlDomNode<QDomNode>(m_value.previousSibling());
+ return new XmlDomNode<QDomNode>(m_value.previousSiblingElement(tagName));
+ }
+ XmlDomNode<QDomNode> *nextSibling(const QString &tagName) const
+ {
+ if (tagName.isEmpty())
+ return new XmlDomNode<QDomNode>(m_value.nextSibling());
+ return new XmlDomNode<QDomNode>(m_value.nextSiblingElement(tagName));
+ }
+ void appendChild(const XmlDomNode<QDomNode> *newChild)
+ {
+ m_value.appendChild(newChild->value());
+ }
+ void insertBefore(const XmlDomNode<QDomNode> *newChild, const XmlDomNode<QDomNode> *refChild)
+ {
+ m_value.insertBefore(newChild->value(), refChild->value());
+ }
+ void insertAfter(const XmlDomNode<QDomNode> *newChild, const XmlDomNode<QDomNode> *refChild)
+ {
+ m_value.insertAfter(newChild->value(), refChild->value());
+ }
+ void replaceChild(const XmlDomNode<QDomNode> *newChild, const XmlDomNode<QDomNode> *oldChild)
+ {
+ m_value.replaceChild(newChild->value(), oldChild->value());
+ }
+ void removeChild(const XmlDomNode<QDomNode> *oldChild)
+ {
+ m_value.removeChild(oldChild->value());
+ }
-bool XmlDomNode::isCDATASection() const
-{
- return m_domNode.isCDATASection();
-}
+ // Implemented for QDomDocument only.
+ XmlDomNode<QDomNode> *documentElement();
+ XmlDomNode<QDomNode> *createElement(const QString &tagName);
+ XmlDomNode<QDomNode> *createCDATASection(const QString &value);
+ XmlDomNode<QDomNode> *createTextNode(const QString &value);
-bool XmlDomNode::isText() const
-{
- return m_domNode.isText();
-}
+ bool setContent(const QString &content);
+ QString toString(int indent = 1);
-QString XmlDomNode::attribute(const QString &name, const QString &defValue)
-{
- QDomElement el = m_domNode.toElement();
- if (el.isNull()) {
- context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName()));
- return defValue;
- }
- return el.attribute(name, defValue);
-}
+ void save(const QString &filePath, int indent = 1);
+ void load(const QString &filePath);
-void XmlDomNode::setAttribute(const QString &name, const QString &value)
-{
- QDomElement el = m_domNode.toElement();
- if (el.isNull()) {
- context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName()));
- return;
- }
- el.setAttribute(name, value);
-}
+ C m_value;
+};
-bool XmlDomNode::hasAttribute(const QString &name) const
-{
- QDomElement el = m_domNode.toElement();
- if (el.isNull()) {
- context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName()));
- return false;
- }
- return el.hasAttribute(name);
-}
+template<> const char *XmlDomNode<QDomNode>::name() { return "DomNode"; }
+template<> const char *XmlDomNode<QDomDocument>::name() { return "DomDocument"; }
-QString XmlDomNode::tagName() const
+template<> JSValue XmlDomNode<QDomNode>::ctor(JSContext *ctx, JSValue, JSValue, int , JSValue *,
+ int)
{
- QDomElement el = m_domNode.toElement();
- if (el.isNull()) {
- context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName()));
- return {};
- }
- return el.tagName();
+ const JSValue obj = createObject(ctx);
+ const auto se = ScriptEngine::engineForContext(ctx);
+ const DubiousContextList dubiousContexts{
+ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving)
+ };
+ se->checkContext(QStringLiteral("qbs.Xml.DomNode"), dubiousContexts);
+ se->setUsesIo();
+ return obj;
}
-void XmlDomNode::setTagName(const QString &name)
+template<> JSValue XmlDomNode<QDomDocument>::ctor(JSContext *ctx, JSValue, JSValue,
+ int argc, JSValue *argv, int)
{
- QDomElement el = m_domNode.toElement();
- if (el.isNull()) {
- context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName()));
- return;
- }
- el.setTagName(name);
+ try {
+ JSValue obj;
+ if (argc == 0) {
+ obj = createObject(ctx);
+ } else {
+ const auto name = getArgument<QString>(ctx, "XmlDomDocument constructor",
+ argc, argv);
+ obj = createObject(ctx, name);
+ }
+ const auto se = ScriptEngine::engineForContext(ctx);
+ const DubiousContextList dubiousContexts{
+ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving)
+ };
+ se->checkContext(QStringLiteral("qbs.Xml.DomDocument"), dubiousContexts);
+ se->setUsesIo();
+ return obj;
+ } catch (const QString &error) { return throwError(ctx, error); }
}
-QString XmlDomNode::text() const
+template<> XmlDomNode<QDomNode> *XmlDomNode<QDomDocument>::documentElement()
{
- QDomElement el = m_domNode.toElement();
- if (el.isNull()) {
- context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName()));
- return {};
- }
- return el.text();
+ return new XmlDomNode<QDomNode>(m_value.documentElement());
}
-QString XmlDomNode::data() const
+template<> XmlDomNode<QDomNode> *XmlDomNode<QDomDocument>::createElement(const QString &tagName)
{
- if (m_domNode.isText())
- return m_domNode.toText().data();
- if (m_domNode.isCDATASection())
- return m_domNode.toCDATASection().data();
- if (m_domNode.isCharacterData())
- return m_domNode.toCharacterData().data();
- context()->throwError(QStringLiteral("Node '%1' is not a character data node").arg(m_domNode.nodeName()));
- return {};
+ return new XmlDomNode<QDomNode>(m_value.createElement(tagName));
}
-void XmlDomNode::setData(const QString &v) const
+template<> XmlDomNode<QDomNode> *XmlDomNode<QDomDocument>::createCDATASection(const QString &value)
{
- if (m_domNode.isText())
- return m_domNode.toText().setData(v);
- if (m_domNode.isCDATASection())
- return m_domNode.toCDATASection().setData(v);
- if (m_domNode.isCharacterData())
- return m_domNode.toCharacterData().setData(v);
- context()->throwError(QStringLiteral("Node '%1' is not a character data node").arg(m_domNode.nodeName()));
+ return new XmlDomNode<QDomNode>(m_value.createCDATASection(value));
}
-void XmlDomNode::clear()
+template<> XmlDomNode<QDomNode> *XmlDomNode<QDomDocument>::createTextNode(const QString &value)
{
- m_domNode.clear();
+ return new XmlDomNode<QDomNode>(m_value.createTextNode(value));
}
-bool XmlDomNode::hasAttributes() const
+template<> bool XmlDomNode<QDomDocument>::setContent(const QString &content)
{
- return m_domNode.hasAttributes();
+ return static_cast<bool>(m_value.setContent(content));
}
-bool XmlDomNode::hasChildNodes() const
+template<> QString XmlDomNode<QDomDocument>::toString(int indent)
{
- return m_domNode.hasChildNodes();
+ return m_value.toString(indent);
}
-QScriptValue XmlDomNode::parentNode() const
+template<> JSValue XmlDomNode<QDomDocument>::jsDocumentElement(JSContext *ctx, JSValue this_val,
+ int, JSValue *)
{
- return engine()->newQObject(new XmlDomNode(m_domNode.parentNode()), QScriptEngine::ScriptOwnership);
+ return XmlDomNode<QDomNode>::createObjectDirect(
+ ctx, fromJsObject(ctx, this_val)->documentElement());
}
-QScriptValue XmlDomNode::firstChild(const QString &tagName)
+template<> JSValue XmlDomNode<QDomDocument>::jsCreateElement(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- if (tagName.isEmpty())
- return engine()->newQObject(new XmlDomNode(m_domNode.firstChild()), QScriptEngine::ScriptOwnership);
- return engine()->newQObject(new XmlDomNode(m_domNode.firstChildElement(tagName)), QScriptEngine::ScriptOwnership);
+ try {
+ const auto tagName = getArgument<QString>(ctx, "DomDocument.createElement", argc, argv);
+ const JSValue obj = XmlDomNode<QDomNode>::createObjectDirect(
+ ctx, fromJsObject(ctx, this_val)->createElement(tagName));
+ return obj;
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
}
-QScriptValue XmlDomNode::lastChild(const QString &tagName) const
+template<> JSValue XmlDomNode<QDomDocument>::jsCreateCDATASection(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- if (tagName.isEmpty())
- return engine()->newQObject(new XmlDomNode(m_domNode.lastChild()), QScriptEngine::ScriptOwnership);
- return engine()->newQObject(new XmlDomNode(m_domNode.lastChildElement(tagName)), QScriptEngine::ScriptOwnership);
+ try {
+ const auto value = getArgument<QString>(ctx, "DomDocument.createCDATASection", argc, argv);
+ return XmlDomNode<QDomNode>::createObjectDirect(
+ ctx, fromJsObject(ctx, this_val)->createCDATASection(value));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
}
-QScriptValue XmlDomNode::previousSibling(const QString &tagName) const
+template<> JSValue XmlDomNode<QDomDocument>::jsCreateTextNode(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- if (tagName.isEmpty())
- return engine()->newQObject(new XmlDomNode(m_domNode.previousSibling()), QScriptEngine::ScriptOwnership);
- return engine()->newQObject(new XmlDomNode(m_domNode.previousSiblingElement(tagName)), QScriptEngine::ScriptOwnership);
+ try {
+ const auto value = getArgument<QString>(ctx, "DomDocument.createTextNode", argc, argv);
+ return XmlDomNode<QDomNode>::createObjectDirect(
+ ctx, fromJsObject(ctx, this_val)->createTextNode(value));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
}
-QScriptValue XmlDomNode::nextSibling(const QString &tagName) const
+template<> JSValue XmlDomNode<QDomDocument>::jsSetContent(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- if (tagName.isEmpty())
- return engine()->newQObject(new XmlDomNode(m_domNode.nextSibling()), QScriptEngine::ScriptOwnership);
- return engine()->newQObject(new XmlDomNode(m_domNode.nextSiblingElement(tagName)), QScriptEngine::ScriptOwnership);
+ try {
+ const auto content = getArgument<QString>(ctx, "DomDocument.setContent", argc, argv);
+ return JS_NewBool(ctx, fromJsObject(ctx, this_val)->setContent(content));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
+ }
}
-QScriptValue XmlDomNode::appendChild(const QScriptValue &newChild)
+template<> JSValue XmlDomNode<QDomDocument>::jsToString(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- auto newNode = qobject_cast<XmlDomNode*>(newChild.toQObject());
- if (!newNode) {
- context()->throwError(QStringLiteral("First argument is not a XmlDomNode object"));
- return {};
+ try {
+ qint32 indent = 1;
+ if (argc > 0)
+ indent = getArgument<qint32>(ctx, "DomDocument.toString", argc, argv);
+ return makeJsString(ctx, fromJsObject(ctx, this_val)->toString(indent));
+ } catch (const QString &error) {
+ return throwError(ctx, error);
}
- return engine()->newQObject(new XmlDomNode(m_domNode.appendChild(newNode->m_domNode)), QScriptEngine::ScriptOwnership);
}
-QScriptValue XmlDomNode::insertBefore(const QScriptValue &newChild, const QScriptValue &refChild)
+template<> void XmlDomNode<QDomDocument>::save(const QString &filePath, int indent)
{
- auto newNode = qobject_cast<XmlDomNode*>(newChild.toQObject());
- if (!newNode) {
- context()->throwError(QStringLiteral("First argument is not a XmlDomNode object"));
- return {};
- }
+ QFile f(filePath);
+ if (!f.open(QIODevice::WriteOnly))
+ throw QStringLiteral("unable to open '%1'").arg(filePath);
- auto refNode = qobject_cast<XmlDomNode*>(refChild.toQObject());
- if (!refNode) {
- context()->throwError(QStringLiteral("Second argument is not a XmlDomNode object"));
- return {};
- }
+ QByteArray buff(m_value.toByteArray(indent));
+ if (buff.size() != f.write(buff))
+ throw f.errorString();
- return engine()->newQObject(new XmlDomNode(m_domNode.insertBefore(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership);
+ f.close();
+ if (f.error() != QFile::NoError)
+ throw f.errorString();
}
-QScriptValue XmlDomNode::insertAfter(const QScriptValue &newChild, const QScriptValue &refChild)
+template<> JSValue XmlDomNode<QDomDocument>::jsSave(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- auto newNode = qobject_cast<XmlDomNode*>(newChild.toQObject());
- if (!newNode) {
- context()->throwError(QStringLiteral("First argument is not a XmlDomNode object"));
- return {};
- }
-
- auto refNode = qobject_cast<XmlDomNode*>(refChild.toQObject());
- if (!refNode) {
- context()->throwError(QStringLiteral("Second argument is not a XmlDomNode object"));
- return {};
+ try {
+ const auto filePath = getArgument<QString>(ctx, "DomDocument.save", argc, argv);
+ qint32 indent = 1;
+ if (argc > 1)
+ indent = fromArg<qint32>(ctx, "toString", 2, argv[1]);
+ fromJsObject(ctx, this_val)->save(filePath, indent);
+ return JS_UNDEFINED;
+ } catch (const QString &error) {
+ return throwError(ctx, error);
}
-
- return engine()->newQObject(new XmlDomNode(m_domNode.insertAfter(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership);
}
-QScriptValue XmlDomNode::replaceChild(const QScriptValue &newChild, const QScriptValue &oldChild)
+template<> void XmlDomNode<QDomDocument>::load(const QString &filePath)
{
- auto newNode = qobject_cast<XmlDomNode*>(newChild.toQObject());
- if (!newNode) {
- context()->throwError(QStringLiteral("First argument is not a XmlDomNode object"));
- return {};
- }
-
- auto oldNode = qobject_cast<XmlDomNode*>(oldChild.toQObject());
- if (!oldNode) {
- context()->throwError(QStringLiteral("Second argument is not a XmlDomNode object"));
- return {};
- }
+ QFile f(filePath);
+ if (!f.open(QIODevice::ReadOnly))
+ throw QStringLiteral("unable to open '%1'").arg(filePath);
- return engine()->newQObject(new XmlDomNode(m_domNode.replaceChild(newNode->m_domNode, oldNode->m_domNode)), QScriptEngine::ScriptOwnership);
+ QString errorMsg;
+ if (!m_value.setContent(&f, &errorMsg))
+ throw errorMsg;
}
-QScriptValue XmlDomNode::removeChild(const QScriptValue &oldChild)
+template<> JSValue XmlDomNode<QDomDocument>::jsLoad(JSContext *ctx, JSValue this_val,
+ int argc, JSValue *argv)
{
- auto oldNode = qobject_cast<XmlDomNode*>(oldChild.toQObject());
- if (!oldNode) {
- context()->throwError(QStringLiteral("First argument is not a XmlDomNode object"));
- return {};
+ try {
+ const auto filePath = getArgument<QString>(ctx, "DomDocument.load", argc, argv);
+ fromJsObject(ctx, this_val)->load(filePath);
+ return JS_UNDEFINED;
+ } catch (const QString &error) {
+ return throwError(ctx, error);
}
-
- return engine()->newQObject(new XmlDomNode(m_domNode.removeChild(oldNode->m_domNode)), QScriptEngine::ScriptOwnership);
}
-XmlDomNode::XmlDomNode(const QDomNode &other)
-{
- m_domNode = other;
+template<> XmlDomNode<QDomDocument>::XmlDomNode(JSContext *, const QString &name) : m_value(name) {}
+
+template<class C>
+void XmlDomNode<C>::setupMethods(JSContext *ctx, JSValue obj)
+{
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "appendChild", &jsAppendChild, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "attribute", &jsAttribute, 2);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "clear", &jsClear, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "data", &jsData, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "firstChild", &jsFirstChild, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "hasAttribute", &jsHasAttribute, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "hasAttributes", &jsHasAttributes, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "hasChildNodes", &jsHasChildNodes, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "insertAfter", &jsInsertAfter, 2);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "insertBefore", &jsInsertBefore, 2);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "isCDATASection", &jsIsCDATASection, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "isElement", &jsIsElement, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "isText", &jsIsText, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "lastChild", &jsLastChild, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "nextSibling", &jsNextSibling, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "parentNode", &jsParentNode, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "previousSibling", &jsPreviousSibling, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "removeChild", &jsRemoveChild, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "replaceChild", &jsReplaceChild, 2);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "setAttribute", &jsSetAttribute, 2);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "setData", &jsSetData, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "setTagName", &jsSetTagName, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "tagName", &jsTagName, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "text", &jsText, 0);
+ if constexpr (std::is_same_v<C, QDomDocument>) {
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "documentElement", &jsDocumentElement, 0);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "createElement", &jsCreateElement, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "createCDATASection",
+ &jsCreateCDATASection, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "createTextNode", &jsCreateTextNode, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "setContent", &jsSetContent, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "toString", &jsToString, 1);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "save", &jsSave, 2);
+ JsExtension<XmlDomNode>::setupMethod(ctx, obj, "load", &jsLoad, 1);
+ }
}
} // namespace Internal
} // namespace qbs
-void initializeJsExtensionXml(QScriptValue extensionObject)
+void initializeJsExtensionXml(qbs::Internal::ScriptEngine *engine, JSValue extensionObject)
{
using namespace qbs::Internal;
- QScriptEngine *engine = extensionObject.engine();
- QScriptValue docObj = engine->newQMetaObject(&XmlDomDocument::staticMetaObject,
- engine->newFunction(&XmlDomDocument::ctor));
- QScriptValue nodeObj = engine->newQMetaObject(&XmlDomNode::staticMetaObject,
- engine->newFunction(&XmlDomNode::ctor));
- QScriptValue contextObject = engine->newObject();
- contextObject.setProperty(QStringLiteral("DomDocument"), docObj);
- contextObject.setProperty(QStringLiteral("DomElement"), nodeObj);
-
- extensionObject.setProperty(QStringLiteral("Xml"), contextObject);
+ JSValue contextObject = engine->newObject();
+ XmlDomNode<QDomNode>::registerClass(engine, contextObject);
+ XmlDomNode<QDomDocument>::registerClass(engine, contextObject);
+ setJsProperty(engine->context(), extensionObject, QLatin1String("Xml"), contextObject);
}
-
-Q_DECLARE_METATYPE(qbs::Internal::XmlDomDocument *)
-Q_DECLARE_METATYPE(qbs::Internal::XmlDomNode *)
-
-#include "domxml.moc"