From 26183abd9acd44a0382e55cc985795ee7c526aed Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Sun, 25 Aug 2013 12:41:58 +0200 Subject: Updated W3C tests and bug-fixes --- README.md | 99 +++++++++++++++++++--- contrib/ctest/CTestCustom.ctest.in | 32 +++++++ contrib/dom/idl/SCXMLEvent.idl | 2 +- src/bindings/swig/java/JavaDataModel.h | 12 +-- src/bindings/swig/php/uscxmlNativePHP.php | 10 +-- src/uscxml/Factory.cpp | 17 ++-- src/uscxml/Factory.h | 24 ++++-- src/uscxml/Interpreter.cpp | 99 ++++++++++++++-------- src/uscxml/Interpreter.h | 7 +- src/uscxml/Message.cpp | 62 +++++++------- src/uscxml/Message.h | 15 ++-- src/uscxml/URL.cpp | 4 +- src/uscxml/URL.h | 4 +- src/uscxml/interpreter/InterpreterDraft6.cpp | 7 +- .../ecmascript/JavaScriptCore/JSCDataModel.cpp | 82 +++++++++++++----- .../ecmascript/JavaScriptCore/JSCDataModel.h | 6 +- .../JavaScriptCore/dom/JSCSCXMLEvent.cpp | 2 +- .../ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h | 2 +- .../JavaScriptCore/dom/JSCSCXMLEventCustom.cpp | 2 +- .../plugins/datamodel/ecmascript/Storage.cpp | 2 +- .../datamodel/ecmascript/v8/V8DataModel.cpp | 53 ++++++++---- .../plugins/datamodel/ecmascript/v8/V8DataModel.h | 6 +- .../datamodel/ecmascript/v8/dom/V8SCXMLEvent.h | 4 +- .../ecmascript/v8/dom/V8SCXMLEventCustom.cpp | 2 +- src/uscxml/plugins/datamodel/null/NULLDataModel.h | 4 +- .../plugins/datamodel/prolog/swi/SWIDataModel.cpp | 19 +++-- .../plugins/datamodel/prolog/swi/SWIDataModel.h | 4 +- .../plugins/datamodel/xpath/XPathDataModel.cpp | 27 +++--- .../plugins/datamodel/xpath/XPathDataModel.h | 4 +- src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp | 4 +- .../invoker/graphics/openscenegraph/OSGInvoker.cpp | 4 +- src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp | 12 ++- .../plugins/invoker/vxml/VoiceXMLInvoker.cpp | 3 +- src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp | 9 +- .../ioprocessor/basichttp/BasicHTTPIOProcessor.cpp | 10 +++ .../plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp | 1 + test/CMakeLists.txt | 2 + test/samples/uscxml/test-markup-passing.scxml | 54 ++++++++++++ test/samples/uscxml/test-markup.xml | 6 ++ test/samples/uscxml/test-scenegraph.scxml | 6 +- test/samples/w3c/ecma/test159.scxml | 4 +- test/samples/w3c/ecma/test191.scxml | 2 +- test/samples/w3c/ecma/test354.scxml | 52 ++++++++++++ test/samples/w3c/ecma/test415.scxml | 12 +++ test/samples/w3c/ecma/test483.scxml | 27 ++++++ test/samples/w3c/ecma/test513.scxml | 50 +++++++++++ test/samples/w3c/ecma/test528.scxml | 3 +- test/samples/w3c/txml/test159.txml | 2 +- test/samples/w3c/txml/test191.txml | 2 +- test/samples/w3c/txml/test354.txml | 56 ++++++++++++ test/samples/w3c/txml/test415.txml | 15 ++++ test/samples/w3c/txml/test483.txml | 31 +++++++ test/samples/w3c/txml/test513.txml | 54 ++++++++++++ test/samples/w3c/txml/test528.txml | 3 +- test/samples/w3c/xpath/test159.scxml | 2 +- test/samples/w3c/xpath/test191.scxml | 2 +- test/samples/w3c/xpath/test354.scxml | 52 ++++++++++++ test/samples/w3c/xpath/test415.scxml | 12 +++ test/samples/w3c/xpath/test483.scxml | 27 ++++++ test/samples/w3c/xpath/test513.scxml | 50 +++++++++++ test/samples/w3c/xpath/test528.scxml | 3 +- test/src/test-arabica-xpath.cpp | 2 +- test/src/test-datamodel.cpp | 3 +- test/src/test-w3c.cpp | 5 +- 64 files changed, 965 insertions(+), 230 deletions(-) create mode 100644 test/samples/uscxml/test-markup-passing.scxml create mode 100644 test/samples/uscxml/test-markup.xml create mode 100644 test/samples/w3c/ecma/test354.scxml create mode 100644 test/samples/w3c/ecma/test415.scxml create mode 100644 test/samples/w3c/ecma/test483.scxml create mode 100644 test/samples/w3c/ecma/test513.scxml create mode 100644 test/samples/w3c/txml/test354.txml create mode 100644 test/samples/w3c/txml/test415.txml create mode 100644 test/samples/w3c/txml/test483.txml create mode 100644 test/samples/w3c/txml/test513.txml create mode 100644 test/samples/w3c/xpath/test354.scxml create mode 100644 test/samples/w3c/xpath/test415.scxml create mode 100644 test/samples/w3c/xpath/test483.scxml create mode 100644 test/samples/w3c/xpath/test513.scxml diff --git a/README.md b/README.md index 179f4f2..ec7d504 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ # uSCXML ReadMe -uSCXML is a SCXML interpreter written in C/C++. It is mostly feature-complete and -[standards compliant](https://github.com/tklab-tud/uscxml#test-reports) to a large extend. -It runs on Linux, Windows and MacOSX, each 32- as well as 64Bits. -There are still a few rough edges, especially with the plugins and custom extensions. - -The latest release will also compile for iOS using the toolchain files in contrib/cmake/ -it features the (still experimental) JavaScriptCore ecmascript datamodel and no prolog datamodel. I will -work on the Android version as soon as I have some time at my hands. +uSCXML is a SCXML interpreter written in C/C++. It is mostly feature-complete and to a large extend +[standards compliant](https://github.com/tklab-tud/uscxml#test-reports). +It runs on Linux, Windows and MacOSX, each 32- as well as 64Bits as well as iOS. +There are still a few rough edges though, especially with the plugins and custom extensions. * Datamodels - * Full [ECMAScript datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/ecmascript) using Google's v8 and JavaScriptCore (JSC is somewhat experimental) + * Full [ECMAScript datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/ecmascript) using Google's v8 (and JavaScriptCore on MacOSX and iOS) * Full [NULL datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/null) with required In predicate * Early [Prolog datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/prolog/swi) using SWI prolog * Rudimentary support for [XPath datamodel](https://github.com/tklab-tud/uscxml/tree/master/src/uscxml/plugins/datamodel/xpath) @@ -35,13 +31,19 @@ work on the Android version as soon as I have some time at my hands. * We continuously run the [W3C IRP tests](http://www.w3.org/Voice/2013/scxml-irp/) for SCXML. * Have a look at the [result](http://uscxml.tk.informatik.tu-darmstadt.de/cdash/index.php?project=uscxml) for the various platforms. - * The manual tests are [excluded](https://github.com/tklab-tud/uscxml/blob/master/contrib/ctest/CTestCustom.ctest.in). + * The manual and XPath specific tests are [excluded](https://github.com/tklab-tud/uscxml/blob/master/contrib/ctest/CTestCustom.ctest.in). uSCXML still fails the following ecmascript tests: + + + + + + @@ -60,6 +62,18 @@ uSCXML still fails the following ecmascript tests: + + + + + +
Test#StatusDescriptionComment
159Failed"If the processing of an element of executable content causes an error to be raised, the processor MUST NOT process the remaining elements of the block."uSCXML continues processing the rest of the block as if there was no error.
301 Failed "the processor should reject this document because it can't download the script""test that any attempt to change the value of a system variable causes error.execution to be raised" Same issue as above: we allow writing to _event.
+ + 519 + 520 + 531 + 534 + FailedTests contain non-standard ECMAScript.
## License @@ -72,3 +86,68 @@ upon](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md#build-dep We do not yet feature installers. Please download the source and have a look at the [build instructions](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md). + +## Usage + +In order to use the interpreter, you need to #include "uscxml/Interpreter.h" and instantiate +objects of uscxml::Interpreter. + +### Blocking Interpretation with SCXML from URL + Interpreter scxml = Interpreter::fromURL("http://www.example.com/fancy.scxml"); + scxml.start(); // non-blocking + +There are some cases, i.e. with graphical invokers, where the main thread is required in order +to react to UI events. You will have to deligate control flow from the main thread into the interpreter +every now and then: + + interpreter.runOnMainThread(25); + +This will perform a single iteration on the invoked components with a maximum of 25 frames per seconds +or return immediately. You will have to call this method every now and then if you are using e.g. the +scenegraph invoker. + +### Non-Blocking Interpretation with inline SCXML + Interpreter scxml = Interpreter::fromXML(""); + scxml.interpret(); // blocking + +### Callbacks for an Interpreter + +You can register an InterpreterMonitor prior to start in order to receive +control-flow upon various events in the Interpreter. + + class StatusMonitor : public uscxml::InterpreterMonitor { + void onStableConfiguration(Interpreter) {} + void beforeCompletion(Interpreter) {} + void afterCompletion(Interpreter) {} + void beforeMicroStep(Interpreter) {} + void beforeTakingTransitions(Interpreter, const Arabica::XPath::NodeSet&) {} + void beforeEnteringStates(Interpreter, const Arabica::XPath::NodeSet&) {} + void afterEnteringStates(Interpreter) {} + void beforeExitingStates(Interpreter, const Arabica::XPath::NodeSet&) {} + void afterExitingStates(Interpreter) {} + }; + + StatusMonitor statMon; + Interpreter scxml = Interpreter::fromXML(""); + scxml.addMonitor(&statMon); + scxml.start(); + +This will cause the interpreter to invoke the callbacks from the monitor whenever the corresponding +internal phase is reached. + +## Extending uSCXML + +The uSCXML interpreter can be extended by introducing new + + 1. DataModels as embedded scripting languages (e.g. ECMAScript, Prolog and XPath) + 2. Invokers to represent external components that deliver and accept events (e.g. iCal, SceneGraph, DirectoryMonitor) + 3. I/O-Processors to provide communication with external systems (e.g. BasicHTTP, SCXML). + 4. Elements for Executable Content (e.g. <respond>, <fetch>, <postpone>). + +The basic approach to extend the interpreter is the same in all cases: + + 1. Write a class inheriting the abstract base class (e.g. DataModelImpl, InvokerImpl, IOProcessorImpl, ExecutableContentImpl). + 2. Instantiate your class and register it as a prototype at the Factory via one of its static register* methods. + 1. You can register at the global Factory Singleton via Factory::register*(prototypeInstance) + 2. Or provide a new Factory instance to selected interpreters as an in-between. + 3. Write an interpreter using your new functionality. diff --git a/contrib/ctest/CTestCustom.ctest.in b/contrib/ctest/CTestCustom.ctest.in index 098e4e2..e263147 100644 --- a/contrib/ctest/CTestCustom.ctest.in +++ b/contrib/ctest/CTestCustom.ctest.in @@ -7,6 +7,7 @@ # grep -ori 'datamodel="null' . # skip xpath datamodel tests +# these are manual or xpath tests generated by the ecma generator set(CTEST_CUSTOM_TESTS_IGNORE "ecma/test178.scxml" "ecma/test230.scxml" @@ -14,6 +15,37 @@ set(CTEST_CUSTOM_TESTS_IGNORE "ecma/test307.scxml" "ecma/test313.scxml" "ecma/test314.scxml" + "ecma/test415.scxml" + "ecma/test463.scxml" + "ecma/test464.scxml" + "ecma/test465.scxml" + "ecma/test466.scxml" + "ecma/test467.scxml" + "ecma/test468.scxml" + "ecma/test469.scxml" + "ecma/test470.scxml" + "ecma/test473.scxml" + "ecma/test474.scxml" + "ecma/test475.scxml" + "ecma/test476.scxml" + "ecma/test477.scxml" + "ecma/test478.scxml" + "ecma/test479.scxml" + "ecma/test480.scxml" + "ecma/test481.scxml" + "ecma/test482.scxml" + "ecma/test483.scxml" + "ecma/test537.scxml" + "ecma/test539.scxml" + "ecma/test540.scxml" + "ecma/test542.scxml" + "ecma/test543.scxml" + "ecma/test544.scxml" + "ecma/test546.scxml" + "ecma/test547.scxml" + "ecma/test555.scxml" + "ecma/test568.scxml" + ) diff --git a/contrib/dom/idl/SCXMLEvent.idl b/contrib/dom/idl/SCXMLEvent.idl index fbb7661..67f5070 100644 --- a/contrib/dom/idl/SCXMLEvent.idl +++ b/contrib/dom/idl/SCXMLEvent.idl @@ -7,7 +7,7 @@ const unsigned short EXTERNAL = 2; const unsigned short PLATFORM = 3; - [CustomGetter, EmptyAsNull] readonly attribute DOMString eventType; + [CustomGetter, EmptyAsNull] readonly attribute DOMString type; readonly attribute DOMString name; [EmptyAsNull] readonly attribute DOMString origin; [EmptyAsNull] readonly attribute DOMString origintype; diff --git a/src/bindings/swig/java/JavaDataModel.h b/src/bindings/swig/java/JavaDataModel.h index 5d76480..ca503d1 100644 --- a/src/bindings/swig/java/JavaDataModel.h +++ b/src/bindings/swig/java/JavaDataModel.h @@ -62,7 +62,7 @@ public: } virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) { // convert XML back into strings std::string location; @@ -72,9 +72,9 @@ public: std::ostringstream ssAssign; ssAssign << assignElem; std::string tmp; - if (doc) { + if (node) { std::ostringstream ssContent; - ssContent << doc; + ssContent << node; tmp = ssContent.str(); } else { tmp = content; @@ -89,7 +89,7 @@ public: // this is assign the function exposed to java virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) { // convert XML back into strings std::string location; @@ -100,9 +100,9 @@ public: if (dataElem) ssData << dataElem; std::string tmp; - if (doc) { + if (node) { std::ostringstream ssContent; - ssContent << doc; + ssContent << node; tmp = ssContent.str(); } else { tmp = content; diff --git a/src/bindings/swig/php/uscxmlNativePHP.php b/src/bindings/swig/php/uscxmlNativePHP.php index 6e4823a..358975a 100644 --- a/src/bindings/swig/php/uscxmlNativePHP.php +++ b/src/bindings/swig/php/uscxmlNativePHP.php @@ -2,7 +2,7 @@ /* ---------------------------------------------------------------------------- * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.7 + * Version 2.0.9 * * This file is not intended to be easily readable and contains a number of * coding conventions designed to improve portability and efficiency. Do not make @@ -423,14 +423,6 @@ class Event { Event_setDOM($this->_cPtr,$dom); } - static function getFirstDOMElement($self_or_dom) { - return Event_getFirstDOMElement($self_or_dom); - } - - static function getStrippedDOM($self_or_dom) { - return Event_getStrippedDOM($self_or_dom); - } - function getRaw() { return Event_getRaw($this->_cPtr); } diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index bc23e53..1494dff 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -352,7 +352,9 @@ boost::shared_ptr Factory::createInvoker(const std::string& type, I if (_invokerAliases.find(type) != _invokerAliases.end()) { std::string canonicalName = _invokerAliases[type]; if (_invokers.find(canonicalName) != _invokers.end()) { - return _invokers[canonicalName]->create(interpreter); + boost::shared_ptr invoker = _invokers[canonicalName]->create(interpreter); + invoker->setInterpreter(interpreter); + return invoker; } } @@ -372,7 +374,9 @@ boost::shared_ptr Factory::createDataModel(const std::string& typ if (_dataModelAliases.find(type) != _dataModelAliases.end()) { std::string canonicalName = _dataModelAliases[type]; if (_dataModels.find(canonicalName) != _dataModels.end()) { - return _dataModels[canonicalName]->create(interpreter); + boost::shared_ptr dataModel = _dataModels[canonicalName]->create(interpreter); + dataModel->setInterpreter(interpreter); + return dataModel; } } @@ -391,7 +395,9 @@ boost::shared_ptr Factory::createIOProcessor(const std::string& if (_ioProcessorAliases.find(type) != _ioProcessorAliases.end()) { std::string canonicalName = _ioProcessorAliases[type]; if (_ioProcessors.find(canonicalName) != _ioProcessors.end()) { - return _ioProcessors[canonicalName]->create(interpreter); + boost::shared_ptr ioProc = _ioProcessors[canonicalName]->create(interpreter); + ioProc->setInterpreter(interpreter); + return ioProc; } } @@ -399,7 +405,7 @@ boost::shared_ptr Factory::createIOProcessor(const std::string& if (_parentFactory) { return _parentFactory->createIOProcessor(type, interpreter); } else { - LOG(ERROR) << "No " << type << " Datamodel known"; + LOG(ERROR) << "No " << type << " IOProcessor known"; } return boost::shared_ptr(); @@ -409,7 +415,8 @@ boost::shared_ptr Factory::createExecutableContent(const // do we have this type in this factory? std::string actualNameSpace = (nameSpace.length() == 0 ? "http://www.w3.org/2005/07/scxml" : nameSpace); if (_executableContent.find(std::make_pair(localName, actualNameSpace)) != _executableContent.end()) { - return _executableContent[std::make_pair(localName, actualNameSpace)]->create(interpreter); + boost::shared_ptr execContent = _executableContent[std::make_pair(localName, actualNameSpace)]->create(interpreter); + execContent->setInterpreter(interpreter); } // lookup in parent factory diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index 0432f34..b815712 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -52,7 +52,9 @@ public: } virtual std::string getLocalName() = 0; ///< The name of the element. - virtual std::string getNamespace() = 0; ///< The namespace of the element. + virtual std::string getNamespace() { + return "http://www.w3.org/2005/07/scxml"; ///< The namespace of the element. + } virtual void enterElement(const Arabica::DOM::Node& node) = 0; ///< Invoked when entering the element as part of evaluating executable content. virtual void exitElement(const Arabica::DOM::Node& node) = 0; ///< Invoked when exiting the element as part of evaluating executable content. virtual bool processChildren() = 0; ///< Whether or not the interpreter should process this elements children. @@ -283,15 +285,19 @@ public: virtual bool isDeclared(const std::string& expr) = 0; virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) = 0; virtual void assign(const std::string& location, const Data& data) = 0; virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) = 0; virtual void init(const std::string& location, const Data& data) = 0; + virtual void setInterpreter(InterpreterImpl* interpreter) { + _interpreter = interpreter; + } + // we need it public for various static functions InterpreterImpl* _interpreter; }; @@ -358,18 +364,18 @@ public: } virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) { - return _impl->assign(assignElem, doc, content); + return _impl->assign(assignElem, node, content); } virtual void assign(const std::string& location, const Data& data) { return _impl->assign(location, data); } virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) { - return _impl->init(dataElem, doc, content); + return _impl->init(dataElem, node, content); } virtual void init(const std::string& location, const Data& data) { return _impl->init(location, data); @@ -383,6 +389,10 @@ public: return _impl->replaceExpressions(content); } + virtual void setInterpreter(InterpreterImpl* interpreter) { + _impl->setInterpreter(interpreter); + } + protected: boost::shared_ptr _impl; }; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 6b17d94..4015026 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -174,7 +174,7 @@ void InterpreterImpl::setNameSpaceInfo(const std::map if (boost::iequals(uri, "http://www.w3.org/2005/07/scxml")) { _nsURL = uri; if (prefix.size() == 0) { - LOG(INFO) << "Mapped default namespace to 'scxml:'"; +// LOG(INFO) << "Mapped default namespace to 'scxml:'"; _xpathPrefix = "scxml:"; _nsContext.addNamespaceDeclaration(uri, "scxml"); _nsToPrefix[uri] = "scxml"; @@ -203,11 +203,12 @@ void InterpreterImpl::setName(const std::string& name) { InterpreterImpl::~InterpreterImpl() { _running = false; - tthread::lock_guard lock(_mutex); +// tthread::lock_guard lock(_mutex); if (_thread) { // unblock event queue Event event; - _externalQueue.push(event); + event.name = "unblock.and.die"; + receive(event); _thread->join(); delete(_thread); } @@ -327,7 +328,7 @@ void InterpreterImpl::initializeData(const Element& data) { } try { - Arabica::DOM::Document dom; + Arabica::DOM::Node dom; std::string text; processDOMorText(data, dom, text); _dataModel.init(data, dom, text); @@ -401,6 +402,7 @@ void InterpreterImpl::normalize(Arabica::DOM::Element& scxml) { void InterpreterImpl::receiveInternal(const Event& event) { std::cout << _name << " receiveInternal: " << event.name << std::endl; _internalQueue.push_back(event); +// _condVar.notify_all(); } void InterpreterImpl::receive(const Event& event, bool toFront) { @@ -410,6 +412,7 @@ void InterpreterImpl::receive(const Event& event, bool toFront) { } else { _externalQueue.push(event); } + _condVar.notify_all(); } void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node& state) { @@ -448,7 +451,7 @@ void InterpreterImpl::internalDoneSend(const Arabica::DOM::Node& st } void InterpreterImpl::processContentElement(const Arabica::DOM::Node& content, - Arabica::DOM::Document& dom, + Arabica::DOM::Node& dom, std::string& text, std::string& expr) { if (HAS_ATTR(content, "expr")) { @@ -460,16 +463,16 @@ void InterpreterImpl::processContentElement(const Arabica::DOM::Node& node, - Arabica::DOM::Document& dom, +void InterpreterImpl::processDOMorText(const Arabica::DOM::Node& element, + Arabica::DOM::Node& dom, std::string& text) { // do we need to download? - if (HAS_ATTR(node, "src") || - (HAS_ATTR(node, "srcexpr") && _dataModel)) { + if (HAS_ATTR(element, "src") || + (HAS_ATTR(element, "srcexpr") && _dataModel)) { std::stringstream srcContent; - URL sourceURL(HAS_ATTR(node, "srcexpr") ? _dataModel.evalAsString(ATTR(node, "srcexpr")) : ATTR(node, "src")); + URL sourceURL(HAS_ATTR(element, "srcexpr") ? _dataModel.evalAsString(ATTR(element, "srcexpr")) : ATTR(element, "src")); if (!sourceURL.toAbsolute(_baseURI)) { - LOG(ERROR) << LOCALNAME(node) << " element has relative src or srcexpr URI with no baseURI set."; + LOG(ERROR) << LOCALNAME(element) << " element has relative src or srcexpr URI with no baseURI set."; return; } if (_cachedURLs.find(sourceURL.asString()) != _cachedURLs.end() && false) { @@ -477,14 +480,14 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node& no } else { srcContent << sourceURL; if (sourceURL.downloadFailed()) { - LOG(ERROR) << LOCALNAME(node) << " source cannot be downloaded"; + LOG(ERROR) << LOCALNAME(element) << " source cannot be downloaded"; return; } _cachedURLs[sourceURL.asString()] = sourceURL; } if (srcContent.str().length() > 0) { // try to parse as XML - Arabica::SAX2DOM::Parser parser; + NameSpacingParser parser; std::stringstream* ss = new std::stringstream(); (*ss) << srcContent.str(); std::auto_ptr ssPtr(ss); @@ -494,45 +497,68 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node& no // parser.setFeature(Arabica::SAX::FeatureNames().external_general, true); if (parser.parse(inputSource) && parser.getDocument()) { - dom = parser.getDocument(); - //std::cout << dom; - Node content = dom.getDocumentElement(); + Document doc = parser.getDocument(); + dom = doc.getDocumentElement(); +#if 0 + Node content = doc.getDocumentElement(); assert(content.getNodeType() == Node_base::ELEMENT_NODE); - Node container = dom.createElement("container"); + Node container = doc.createElement("container"); dom.replaceChild(container, content); container.appendChild(content); // std::cout << dom << std::endl; +#endif return; } else { + if (parser.errorsReported()) { + LOG(ERROR) << parser.errors(); + } text = srcContent.str(); return; } } } - if (!node.hasChildNodes()) + if (!element.hasChildNodes()) return; - Node child = node.getFirstChild(); - while(child) { - if (child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE) { + /** + * Figure out whether the given element contains text, has one child or many childs + */ + bool hasTextContent = false; + bool hasOneChild = false; + Node theOneChild; + bool hasManyChilds = false; + + Node child = element.getFirstChild(); + while (child) { +// std::cout << child.getNodeType() << std::endl; + if (child.getNodeType() == Node_base::TEXT_NODE || + child.getNodeType() == Node_base::CDATA_SECTION_NODE) { std::string trimmed = child.getNodeValue(); boost::trim(trimmed); - if (trimmed.length() > 0) + if (trimmed.length() > 0) { + hasTextContent = true; + } + } else { + if (hasOneChild) { + hasManyChilds = true; + hasOneChild = false; break; - } - if (child.getNodeType() == Node_base::ELEMENT_NODE) { - break; + } + hasOneChild = true; + theOneChild = child; } child = child.getNextSibling(); } - if (child && child.getNodeType() == Node_base::ELEMENT_NODE) { - DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); - dom = domFactory.createDocument(child.getNamespaceURI(), "", 0); - // we need to import the parent - to support xpath test150 - Node newNode = dom.importNode(child.getParentNode(), true); - dom.appendChild(newNode); - } else if(child && (child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE)) { + + if (hasOneChild) { + // if we have a single child, it will be the content of the dom + dom = theOneChild; + } else if (hasManyChilds) { + // if we have multiple childs + dom = element; + } else if(hasTextContent) { + child = element.getFirstChild(); while(child) { if ((child.getNodeType() == Node_base::TEXT_NODE || child.getNodeType() == Node_base::CDATA_SECTION_NODE)) { text += child.getNodeValue(); @@ -540,7 +566,7 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node& no child = child.getNextSibling(); } } else { - LOG(ERROR) << LOCALNAME(node) << " has neither text nor element children."; + LOG(ERROR) << LOCALNAME(element) << " has neither text nor element children."; } } @@ -1123,7 +1149,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont LOG(ERROR) << "Assigning to undeclared location '" << ATTR(content, "location") << "' not allowed." << std::endl; throw Event("error.execution", Event::PLATFORM); } else { - Document dom; + Node dom; std::string text; processDOMorText(content, dom, text); _dataModel.assign(Element(content), dom, text); @@ -1188,7 +1214,10 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node& cont } } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "send")) { // --- SEND -------------------------- - send(content); + try { + send(content); + } + CATCH_AND_DISTRIBUTE("Error while sending content") } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "cancel")) { // --- CANCEL -------------------------- std::string sendId; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index f8cf823..d2c9025 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -251,6 +251,7 @@ protected: bool _stable; tthread::thread* _thread; tthread::recursive_mutex _mutex; + tthread::condition_variable _condVar; tthread::recursive_mutex _pluginMutex; URL _baseURI; @@ -291,13 +292,13 @@ protected: void executeContent(const Arabica::XPath::NodeSet& content, bool rethrow = false); void processContentElement(const Arabica::DOM::Node& element, - Arabica::DOM::Document& dom, + Arabica::DOM::Node& dom, std::string& text, std::string& expr); void processParamChilds(const Arabica::DOM::Node& element, std::multimap& params); - void processDOMorText(const Arabica::DOM::Node& node, - Arabica::DOM::Document& dom, + void processDOMorText(const Arabica::DOM::Node& element, + Arabica::DOM::Node& dom, std::string& text); void send(const Arabica::DOM::Node& element); diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index ddb8996..f3f8c27 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -110,37 +110,37 @@ Arabica::DOM::Document Data::toDocument() { return document; } -Arabica::DOM::Node Event::getFirstDOMElement() const { - return getFirstDOMElement(dom); -} - -Arabica::DOM::Document Event::getStrippedDOM() const { - return getStrippedDOM(dom); -} - -Arabica::DOM::Node Event::getFirstDOMElement(const Arabica::DOM::Document dom) { - Arabica::DOM::Node data = dom.getDocumentElement().getFirstChild(); - while (data) { - if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) { - std::string trimmed = boost::trim_copy(data.getNodeValue()); - if (trimmed.length() == 0) { - data = data.getNextSibling(); - continue; - } - } - break; - } - return data; -} - -Arabica::DOM::Document Event::getStrippedDOM(const Arabica::DOM::Document dom) { - Arabica::DOM::DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); - Arabica::DOM::Document document = domFactory.createDocument("", "", 0); - if (dom) { - document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(dom), true)); - } - return document; -} +//Arabica::DOM::Node Event::getFirstDOMElement() const { +// return getFirstDOMElement(dom); +//} +// +//Arabica::DOM::Document Event::getStrippedDOM() const { +// return getStrippedDOM(dom); +//} + +//Arabica::DOM::Node Event::getFirstDOMElement(const Arabica::DOM::Document dom) { +// Arabica::DOM::Node data = dom.getDocumentElement().getFirstChild(); +// while (data) { +// if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) { +// std::string trimmed = boost::trim_copy(data.getNodeValue()); +// if (trimmed.length() == 0) { +// data = data.getNextSibling(); +// continue; +// } +// } +// break; +// } +// return data; +//} +// +//Arabica::DOM::Document Event::getStrippedDOM(const Arabica::DOM::Document dom) { +// Arabica::DOM::DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); +// Arabica::DOM::Document document = domFactory.createDocument("", "", 0); +// if (dom) { +// document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(dom), true)); +// } +// return document; +//} Arabica::DOM::Document Event::toDocument() { Arabica::DOM::DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 1e7a7ca..afc536f 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -158,17 +158,18 @@ public: this->origintype = originType; } - Arabica::DOM::Document getDOM() { + Arabica::DOM::Node getDOM() { return dom; } - void setDOM(const Arabica::DOM::Document& dom) { + void setDOM(const Arabica::DOM::Node& dom) { this->dom = dom; } - Arabica::DOM::Node getFirstDOMElement() const; - Arabica::DOM::Document getStrippedDOM() const; - static Arabica::DOM::Node getFirstDOMElement(const Arabica::DOM::Document dom); - static Arabica::DOM::Document getStrippedDOM(const Arabica::DOM::Document dom); +// Arabica::DOM::Node getFirstDOMElement() const; +// Arabica::DOM::Document getStrippedDOM() const; +// +// static Arabica::DOM::Node getFirstDOMElement(const Arabica::DOM::Document dom); +// static Arabica::DOM::Document getStrippedDOM(const Arabica::DOM::Document dom); std::string getRaw() { return raw; @@ -239,7 +240,7 @@ protected: Type eventType; std::string origin; std::string origintype; - Arabica::DOM::Document dom; + Arabica::DOM::Node dom; std::string sendid; bool hideSendId; std::string invokeid; diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp index 4d60999..cefe935d 100644 --- a/src/uscxml/URL.cpp +++ b/src/uscxml/URL.cpp @@ -103,7 +103,7 @@ URLImpl::~URLImpl() { curl_easy_cleanup(_handle); } -URLImpl::operator Data() { +URLImpl::operator Data() const { Data data; data.compound["url"] = Data(asString(), Data::VERBATIM); data.compound["host"] = Data(_uri.host(), Data::VERBATIM); @@ -117,7 +117,7 @@ URLImpl::operator Data() { data.compound["statusMsg"] = Data(_statusMsg, Data::VERBATIM); - std::vector::iterator pathIter = _pathComponents.begin(); + std::vector::const_iterator pathIter = _pathComponents.begin(); while(pathIter != _pathComponents.end()) { data.compound["pathComponent"].array.push_back(Data(*pathIter, Data::VERBATIM)); pathIter++; diff --git a/src/uscxml/URL.h b/src/uscxml/URL.h index 3acd462..16c29c7 100644 --- a/src/uscxml/URL.h +++ b/src/uscxml/URL.h @@ -95,7 +95,7 @@ public: bool downloadFailed() { return _hasFailed; } - operator Data(); + operator Data() const; friend class URLFetcher; @@ -249,7 +249,7 @@ public: friend class URLFetcher; friend std::ostream & operator<<(std::ostream &stream, const URL& p); - operator Data() { + operator Data() const { return _impl->operator Data(); } diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index 881fa8b..e044fcf 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -9,7 +9,6 @@ using namespace Arabica::DOM; // see: http://www.w3.org/TR/scxml/#AlgorithmforSCXMLInterpretation void InterpreterDraft6::interpret() { -// _mutex.lock(); tthread::lock_guard lock(_mutex); if (!_isInitialized) init(); @@ -264,7 +263,11 @@ void InterpreterDraft6::mainEventLoop() { while(_externalQueue.isEmpty() && _thread == NULL) { runOnMainThread(200); } + _mutex.lock(); + while(_externalQueue.isEmpty()) { + _condVar.wait(_mutex); + } _currEvent = _externalQueue.pop(); #if VERBOSE std::cout << "Received externalEvent event " << _currEvent.name << std::endl; @@ -273,8 +276,6 @@ void InterpreterDraft6::mainEventLoop() { if (!_running) goto EXIT_INTERPRETER; - _mutex.lock(); - if (_dataModel && boost::iequals(_currEvent.name, "cancel.invoke." + _sessionId)) break; diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 712799c..c714735 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -3,6 +3,9 @@ #include "JSCDataModel.h" #include "JSCDOM.h" #include "dom/JSCDocument.h" +#include "dom/JSCElement.h" +#include "dom/JSCText.h" +#include "dom/JSCCDATASection.h" #include "dom/JSCSCXMLEvent.h" #include "uscxml/Message.h" @@ -12,6 +15,13 @@ #include #endif +#define TO_JSC_DOMVALUE(type) \ +struct JSC##type::JSC##type##Private* privData = new JSC##type::JSC##type##Private(); \ +privData->dom = _dom; \ +privData->nativeObj = new type(node); \ +JSObjectRef retObj = JSObjectMake(_ctx, JSC##type::getTmpl(), privData);\ +return retObj; + namespace uscxml { using namespace Arabica::XPath; @@ -96,24 +106,24 @@ boost::shared_ptr JSCDataModel::create(InterpreterImpl* interpret JSClassRef jsInvokerClassRef = JSClassCreate(&jsInvokersClassDef); JSObjectRef jsInvoker = JSObjectMake(dm->_ctx, jsInvokerClassRef, dm.get()); JSStringRef invokerName = JSStringCreateWithUTF8CString("_invokers"); - JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), invokerName, jsInvoker, kJSPropertyAttributeNone, NULL); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), invokerName, jsInvoker, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); JSStringRelease(invokerName); JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef); JSObjectRef jsIOProc = JSObjectMake(dm->_ctx, jsIOProcClassRef, dm.get()); JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors"); - JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeNone, NULL); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); JSStringRelease(ioProcName); JSStringRef nameName = JSStringCreateWithUTF8CString("_name"); JSStringRef name = JSStringCreateWithUTF8CString(dm->_interpreter->getName().c_str()); - JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeNone, NULL); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); JSStringRelease(nameName); JSStringRelease(name); JSStringRef sessionIdName = JSStringCreateWithUTF8CString("_sessionid"); JSStringRef sessionId = JSStringCreateWithUTF8CString(dm->_interpreter->getSessionId().c_str()); - JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeNone, NULL); + JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL); JSStringRelease(sessionIdName); JSStringRelease(sessionId); @@ -153,7 +163,7 @@ void JSCDataModel::setEvent(const Event& event) { if (event.dom) { JSStringRef propName = JSStringCreateWithUTF8CString("data"); - JSObjectSetProperty(_ctx, eventObj, propName, getDocumentAsValue(event.dom), 0, &exception); + JSObjectSetProperty(_ctx, eventObj, propName, getNodeAsValue(event.dom), 0, &exception); JSStringRelease(propName); if (exception) handleException(exception); @@ -342,8 +352,19 @@ bool JSCDataModel::validate(const std::string& location, const std::string& sche } uint32_t JSCDataModel::getLength(const std::string& expr) { -// LOG(ERROR) << "I am not sure whether getLength() works :("; - JSValueRef result = evalAsValue("(" + expr + ").length"); + JSValueRef result; + + result = evalAsValue("(" + expr + ").length"); + JSType type = JSValueGetType(_ctx, result); + if (type == kJSTypeNull || type == kJSTypeUndefined) { + Event exceptionEvent; + exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM); + exceptionEvent.name = "error.execution"; + exceptionEvent.eventType = Event::PLATFORM; + + throw(exceptionEvent); + } + JSValueRef exception = NULL; double length = JSValueToNumber(_ctx, result, &exception); if (exception) @@ -424,7 +445,7 @@ JSValueRef JSCDataModel::evalAsValue(const std::string& expr, bool dontThrow) { } void JSCDataModel::assign(const Element& assignElem, - const Document& doc, + const Node& node, const std::string& content) { std::string key; JSValueRef exception = NULL; @@ -436,10 +457,20 @@ void JSCDataModel::assign(const Element& assignElem, if (key.length() == 0) throw Event("error.execution", Event::PLATFORM); + // flags on attribute are ignored? + if (key.compare("_sessionid") == 0) + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_name") == 0) + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_ioprocessors") == 0) + throw Event("error.execution", Event::PLATFORM); + if (key.compare("_invokers") == 0) + throw Event("error.execution", Event::PLATFORM); + if (HAS_ATTR(assignElem, "expr")) { evalAsValue(key + " = " + ATTR(assignElem, "expr")); - } else if (doc) { - JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(key.c_str()), getDocumentAsValue(doc), 0, &exception); + } else if (node) { + JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(key.c_str()), getNodeAsValue(node), 0, &exception); if (exception) handleException(exception); } else if (content.size() > 0) { @@ -455,15 +486,24 @@ void JSCDataModel::assign(const Element& assignElem, } } -JSValueRef JSCDataModel::getDocumentAsValue(const Document& doc) { - - struct JSCDocument::JSCDocumentPrivate* retPrivData = new JSCDocument::JSCDocumentPrivate(); - retPrivData->dom = _dom; - retPrivData->nativeObj = new Document(doc); - - JSObjectRef retObj = JSObjectMake(_ctx, JSCDocument::getTmpl(), retPrivData); - - return retObj; +JSValueRef JSCDataModel::getNodeAsValue(const Node& node) { + switch (node.getNodeType()) { + case Node_base::ELEMENT_NODE: { + TO_JSC_DOMVALUE(Element); + } + case Node_base::TEXT_NODE: { + TO_JSC_DOMVALUE(Text); + } + case Node_base::CDATA_SECTION_NODE: { + TO_JSC_DOMVALUE(CDATASection); + } + case Node_base::DOCUMENT_NODE: { + TO_JSC_DOMVALUE(Document); + } + default: { + TO_JSC_DOMVALUE(Node); + } + } } void JSCDataModel::assign(const std::string& location, const Data& data) { @@ -473,10 +513,10 @@ void JSCDataModel::assign(const std::string& location, const Data& data) { } void JSCDataModel::init(const Element& dataElem, - const Document& doc, + const Node& node, const std::string& content) { try { - assign(dataElem, doc, content); + assign(dataElem, node, content); } catch (Event e) { // test 277 std::string key; diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h index f7360d4..9bb3034 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h @@ -50,12 +50,12 @@ public: virtual bool isDeclared(const std::string& expr); virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void assign(const std::string& location, const Data& data); virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void init(const std::string& location, const Data& data); @@ -77,7 +77,7 @@ protected: static JSValueRef jsInvokerGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); static void jsInvokerListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); - JSValueRef getDocumentAsValue(const Arabica::DOM::Document& doc); + JSValueRef getNodeAsValue(const Arabica::DOM::Node& node); JSValueRef getDataAsValue(const Data& data); Data getValueAsData(const JSValueRef value); JSValueRef evalAsValue(const std::string& expr, bool dontThrow = false); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp index 579012b..de3a93f 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.cpp @@ -7,7 +7,7 @@ namespace DOM { JSClassRef JSCSCXMLEvent::Tmpl; JSStaticValue JSCSCXMLEvent::staticValues[] = { - { "eventType", eventTypeCustomAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, + { "type", typeCustomAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, { "name", nameAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, { "origin", originAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, { "origintype", origintypeAttrGetter, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h index d3a25d5..5ac8ccb 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEvent.h @@ -39,7 +39,7 @@ public: JSC_DESTRUCTOR(JSCSCXMLEventPrivate); - static JSValueRef eventTypeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); + static JSValueRef typeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); static JSValueRef nameAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); static JSValueRef originAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); static JSValueRef origintypeAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp index 0209467..e197796 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCSCXMLEventCustom.cpp @@ -3,7 +3,7 @@ namespace Arabica { namespace DOM { -JSValueRef JSCSCXMLEvent::eventTypeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception) { +JSValueRef JSCSCXMLEvent::typeCustomAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception) { struct JSCSCXMLEventPrivate* privData = (struct JSCSCXMLEventPrivate*)JSObjectGetPrivate(thisObj); JSStringRef stringRef; diff --git a/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp b/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp index 9131784..b5bb474 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/Storage.cpp @@ -5,7 +5,7 @@ namespace uscxml { Storage::Storage(const std::string& filename) { _filename = filename; - std::cout << _filename << std::endl; +// std::cout << _filename << std::endl; std::fstream file; file.open(_filename.c_str(), std::ios_base::in); // read content into data diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 017b2eb..ea112f1 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -4,6 +4,9 @@ #include "V8DOM.h" #include "dom/V8Document.h" #include "dom/V8Node.h" +#include "dom/V8Element.h" +#include "dom/V8Text.h" +#include "dom/V8CDATASection.h" #include "dom/V8SCXMLEvent.h" #include "uscxml/Message.h" @@ -13,6 +16,17 @@ #include #endif +#define TO_V8_DOMVALUE(type) \ +v8::Handle retCtor = V8##type::getTmpl()->GetFunction();\ +v8::Persistent retObj = v8::Persistent::New(retCtor->NewInstance());\ +struct V8##type::V8##type##Private* retPrivData = new V8##type::V8##type##Private();\ +retPrivData->dom = _dom;\ +retPrivData->nativeObj = new type(node);\ +retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));\ +retObj.MakeWeak(0, V8##type::jsDestructor);\ +return retObj; + + namespace uscxml { using namespace Arabica::XPath; @@ -152,7 +166,7 @@ void V8DataModel::setEvent(const Event& event) { eventObj.MakeWeak(0, V8SCXMLEvent::jsDestructor); if (event.dom) { - eventObj->Set(v8::String::New("data"), getDocumentAsValue(event.dom)); + eventObj->Set(v8::String::New("data"), getNodeAsValue(event.dom)); } else if (event.content.length() > 0) { // _event.data is a string or JSON Data json = Data::fromJSON(event.content); @@ -268,18 +282,26 @@ Data V8DataModel::getValueAsData(const v8::Handle& value, std::set V8DataModel::getDocumentAsValue(const Document& doc) { - v8::Handle retCtor = V8Document::getTmpl()->GetFunction(); - v8::Persistent retObj = v8::Persistent::New(retCtor->NewInstance()); - - struct V8Document::V8DocumentPrivate* retPrivData = new V8Document::V8DocumentPrivate(); - retPrivData->dom = _dom; - retPrivData->nativeObj = new Document(doc); +v8::Handle V8DataModel::getNodeAsValue(const Node& node) { - retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); - retObj.MakeWeak(0, V8Document::jsDestructor); + switch (node.getNodeType()) { + case Node_base::ELEMENT_NODE: { + TO_V8_DOMVALUE(Element); + } + case Node_base::TEXT_NODE: { + TO_V8_DOMVALUE(Text); + } + case Node_base::CDATA_SECTION_NODE: { + TO_V8_DOMVALUE(CDATASection); + } + case Node_base::DOCUMENT_NODE: { + TO_V8_DOMVALUE(Document); + } + default: { + TO_V8_DOMVALUE(Node); + } + } - return retObj; } v8::Handle V8DataModel::getDataAsValue(const Data& data) { @@ -459,7 +481,7 @@ double V8DataModel::evalAsNumber(const std::string& expr) { } void V8DataModel::assign(const Element& assignElem, - const Document& doc, + const Node& node, const std::string& content) { v8::Locker locker; v8::HandleScope handleScope; @@ -477,8 +499,8 @@ void V8DataModel::assign(const Element& assignElem, if (HAS_ATTR(assignElem, "expr")) { evalAsValue(key + " = " + ATTR(assignElem, "expr")); - } else if (doc) { - global->Set(v8::String::New(key.c_str()), getDocumentAsValue(doc)); + } else if (node) { + global->Set(v8::String::New(key.c_str()), getNodeAsValue(node)); } else if (content.size() > 0) { try { evalAsValue(key + " = " + content); @@ -502,7 +524,7 @@ void V8DataModel::assign(const std::string& location, } void V8DataModel::init(const Element& dataElem, - const Document& doc, + const Node& doc, const std::string& content) { try { assign(dataElem, doc, content); @@ -536,7 +558,6 @@ void V8DataModel::init(const std::string& location, evalAsValue(location + " = undefined", true); throw e; } - } diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index 9d17093..0dffa27 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -50,13 +50,13 @@ public: virtual void eval(const Arabica::DOM::Element& scriptElem, const std::string& expr); virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void assign(const std::string& location, const Data& data); virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void init(const std::string& location, const Data& data); @@ -87,7 +87,7 @@ protected: v8::Handle evalAsValue(const std::string& expr, bool dontThrow = false); v8::Handle getDataAsValue(const Data& data); - v8::Handle getDocumentAsValue(const Arabica::DOM::Document& doc); + v8::Handle getNodeAsValue(const Arabica::DOM::Node& node); void throwExceptionEvent(const v8::TryCatch& tryCatch); }; diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h index 3c5e6ee..9cc4ad4 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h @@ -41,7 +41,7 @@ public: static bool hasInstance(v8::Handle); - static v8::Handle eventTypeCustomAttrGetter(v8::Local property, const v8::AccessorInfo& info); + static v8::Handle typeCustomAttrGetter(v8::Local property, const v8::AccessorInfo& info); static v8::Handle nameAttrGetter(v8::Local property, const v8::AccessorInfo& info); static v8::Handle originAttrGetter(v8::Local property, const v8::AccessorInfo& info); static v8::Handle origintypeAttrGetter(v8::Local property, const v8::AccessorInfo& info); @@ -63,7 +63,7 @@ public: instance->SetInternalFieldCount(1); - instance->SetAccessor(v8::String::NewSymbol("eventType"), V8SCXMLEvent::eventTypeCustomAttrGetter, 0, + instance->SetAccessor(v8::String::NewSymbol("type"), V8SCXMLEvent::typeCustomAttrGetter, 0, v8::External::New(0), static_cast(v8::DEFAULT), static_cast(v8::None)); instance->SetAccessor(v8::String::NewSymbol("name"), V8SCXMLEvent::nameAttrGetter, 0, v8::External::New(0), static_cast(v8::DEFAULT), static_cast(v8::None)); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp index d02a4cb..a8870cc 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEventCustom.cpp @@ -3,7 +3,7 @@ namespace Arabica { namespace DOM { -v8::Handle V8SCXMLEvent::eventTypeCustomAttrGetter(v8::Local property, const v8::AccessorInfo& info) { +v8::Handle V8SCXMLEvent::typeCustomAttrGetter(v8::Local property, const v8::AccessorInfo& info) { v8::Local self = info.Holder(); V8SCXMLEventPrivate* privData = V8DOM::toClassPtr(self->GetInternalField(0)); diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.h b/src/uscxml/plugins/datamodel/null/NULLDataModel.h index b86c01c..74d170f 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.h +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.h @@ -42,12 +42,12 @@ public: virtual void popContext(); virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) {} virtual void assign(const std::string& location, const Data& data) {} virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content) {} virtual void init(const std::string& location, const Data& data) {} diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index a72fc6c..07cba96 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -223,7 +223,8 @@ void SWIDataModel::setEvent(const Event& event) { if (event.dom) { std::stringstream dataInitStr; std::stringstream xmlDoc; - xmlDoc << event.getFirstDOMElement(); +// xmlDoc << event.getFirstDOMElement(); + xmlDoc << event.dom; domUrl = URL::toLocalFile(xmlDoc.str(), ".pl"); dataInitStr << "load_xml_file('" << domUrl.asLocalFile(".pl") << "', XML), copy_term(XML,DATA), assert(event(data(DATA)))"; PlCall(dataInitStr.str().c_str()); @@ -408,7 +409,7 @@ std::map SWIDataModel::resolveAtoms(PlTerm& term, PlTerm& o } void SWIDataModel::assign(const Element& assignElem, - const Document& doc, + const Node& node, const std::string& content) { SET_PL_CONTEXT std::string expr = content; @@ -435,15 +436,15 @@ void SWIDataModel::assign(const Element& assignElem, URL domUrl; Data json; - if (!doc) + if (!node) json = Data::fromJSON(expr); - if (doc) { + if (node) { std::stringstream dataInitStr; std::stringstream xmlDoc; - Node node = Event::getFirstDOMElement(doc); + Node child = node; while(node) { - xmlDoc << node; - node = node.getNextSibling(); + xmlDoc << child; + child = node.getNextSibling(); } domUrl = URL::toLocalFile(xmlDoc.str(), ".pl"); if (boost::iequals(type, "retract")) @@ -488,9 +489,9 @@ void SWIDataModel::assign(const std::string& location, const Data& data) { } void SWIDataModel::init(const Element& dataElem, - const Document& doc, + const Node& node, const std::string& content) { - assign(dataElem, doc, content); + assign(dataElem, node, content); } void SWIDataModel::init(const std::string& location, const Data& data) { assign(location, data); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index 123e938..0a26643 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -42,12 +42,12 @@ public: virtual void popContext(); virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void assign(const std::string& location, const Data& data); virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void init(const std::string& location, const Data& data); diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index 842c560..cb40890 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -174,7 +174,8 @@ void XPathDataModel::setEvent(const Event& event) { eventDataElem.appendChild(textNode); } if (event.dom) { - Node importedNode = _doc.importNode(event.getFirstDOMElement(), true); +// Node importedNode = _doc.importNode(event.getFirstDOMElement(), true); + Node importedNode = _doc.importNode(event.dom, true); eventDataElem.appendChild(importedNode); } @@ -370,7 +371,7 @@ double XPathDataModel::evalAsNumber(const std::string& expr) { } void XPathDataModel::assign(const Element& assignElem, - const Document& doc, + const Node& node, const std::string& content) { std::string location; if (HAS_ATTR(assignElem, "id")) { @@ -399,9 +400,9 @@ void XPathDataModel::assign(const Element& assignElem, } #endif NodeSet nodeSet; - if (doc) { - if (doc.getDocumentElement()) { - Node data = doc.getDocumentElement().getFirstChild(); + if (node) { + if (node) { + Node data = node; while (data) { // do not add empty text as a node if (data.getNodeType() == Node_base::TEXT_NODE) { @@ -447,7 +448,7 @@ NodeSet XPathDataModel::dataToNodeSet(const Data& data) { } void XPathDataModel::init(const Element& dataElem, - const Document& doc, + const Node& node, const std::string& content) { std::string location; if (HAS_ATTR(dataElem, "id")) { @@ -458,9 +459,9 @@ void XPathDataModel::init(const Element& dataElem, Element container = _doc.createElement("data"); container.setAttribute("id", location); - if (doc) { - if (doc.getDocumentElement()) { - Node data = doc.getDocumentElement().getFirstChild(); + if (node) { + if (node) { + Node data = node; while (data) { Node dataClone = _doc.importNode(data, true); container.appendChild(dataClone); @@ -504,10 +505,10 @@ void XPathDataModel::init(const Element& dataElem, #if 0 nodeSet.push_back(container); #else - Node node = container.getFirstChild(); - while(node) { - nodeSet.push_back(node); - node = node.getNextSibling(); + Node child = container.getFirstChild(); + while(child) { + nodeSet.push_back(child); + child = child.getNextSibling(); } #endif _varResolver.setVariable(location, nodeSet); diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h index 240c62c..62ee439 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h @@ -89,12 +89,12 @@ public: virtual void eval(const Arabica::DOM::Element& scriptElem, const std::string& expr); virtual void assign(const Arabica::DOM::Element& assignElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void assign(const std::string& location, const Data& data); virtual void init(const Arabica::DOM::Element& dataElem, - const Arabica::DOM::Document& doc, + const Arabica::DOM::Node& node, const std::string& content); virtual void init(const std::string& location, const Data& data); diff --git a/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp b/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp index 6403a80..477a788 100644 --- a/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp +++ b/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp @@ -258,8 +258,8 @@ void OpenALInvoker::invoke(const InvokeRequest& req) { throw std::string("openal error create context"); } - std::cout << boost::lexical_cast(_alContext); - std::cout << boost::lexical_cast(_alDevice); +// std::cout << boost::lexical_cast(_alContext); +// std::cout << boost::lexical_cast(_alDevice); // alcMakeContextCurrent(_alContext); // float listener[3] = {0,0,0}; diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp index 06141c3..090f1b3 100644 --- a/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp +++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/OSGInvoker.cpp @@ -49,11 +49,9 @@ void OSGInvoker::invoke(const InvokeRequest& req) { evTarget.addEventListener("DOMNodeRemoved", *this, false); evTarget.addEventListener("DOMAttrModified", *this, false); - Arabica::XPath::NodeSet content = Interpreter::filterChildElements("content", req.dom); - std::set validChilds; validChilds.insert("display"); - processChildren(validChilds, content[0]); + processChildren(validChilds, req.dom); } void OSGInvoker::runOnMainThread() { diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp index c697993..85c4b9c 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp @@ -35,7 +35,7 @@ Data USCXMLInvoker::getDataModelVariables() { } void USCXMLInvoker::send(const SendRequest& req) { - _invokedInterpreter.getImpl()->_externalQueue.push(req); + _invokedInterpreter.receive(req); } void USCXMLInvoker::cancel(const std::string sendId) { @@ -46,7 +46,12 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) { if (req.src.length() > 0) { _invokedInterpreter = Interpreter::fromURI(req.src); } else if (req.dom) { - _invokedInterpreter = Interpreter::fromDOM(req.dom); + Arabica::DOM::DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); + Arabica::DOM::Document dom = domFactory.createDocument(req.dom.getNamespaceURI(), "", 0); + // we need to import the parent - to support xpath test150 + Arabica::DOM::Node newNode = dom.importNode(req.dom, true); + dom.appendChild(newNode); + _invokedInterpreter = Interpreter::fromDOM(dom); } else if (req.content.size() > 0) { _invokedInterpreter = Interpreter::fromXML(req.content); } else { @@ -73,7 +78,8 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) { /// test240 assumes that invoke request params will carry over to the datamodel _invokedInterpreter.getImpl()->setInvokeRequest(req); - _invokedInterpreter.getImpl()->start(); + _invokedInterpreter.start(); +// tthread::this_thread::sleep_for(tthread::chrono::seconds(1)); } else { /// test 530 _parentInterpreter->receive(Event("done.invoke." + _invokeId, Event::PLATFORM)); diff --git a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp index ddca2eb..c0d3329 100644 --- a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp @@ -58,7 +58,8 @@ void VoiceXMLInvoker::send(const SendRequest& req) { // } // } // } - domSS << req.getFirstDOMElement(); +// domSS << req.getFirstDOMElement(); + domSS << req.dom; start.content = domSS.str(); _interpreter->getDataModel().replaceExpressions(start.content); diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp index 059e7f5..acbf085 100644 --- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp @@ -88,7 +88,8 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) { std::string content; std::stringstream ss; if (_invokeReq.dom) { - ss << _invokeReq.getFirstDOMElement(); +// ss << _invokeReq.getFirstDOMElement(); + ss << _invokeReq.dom; content = ss.str(); } else if(_invokeReq.data) { ss << _invokeReq.data; @@ -160,14 +161,16 @@ void XHTMLInvoker::reply(const SendRequest& req, const HTTPServer::Request& long if (req.dom) { std::stringstream ss; - Arabica::DOM::Node content = req.dom.getDocumentElement(); +// Arabica::DOM::Node content = req.dom.getDocumentElement(); + Arabica::DOM::Node content = req.dom; if (content && boost::iequals(content.getLocalName(), "content")) { reply.headers["X-SCXML-Type"] = (HAS_ATTR(content, "type") ? ATTR(content, "type") : "replacechildren"); reply.headers["X-SCXML-XPath"] = (HAS_ATTR(content, "xpath") ? ATTR(content, "xpath") : "/html/body"); if (HAS_ATTR(content, "attr")) reply.headers["X-SCXML-Attr"] = ATTR(content, "attr"); } - ss << req.getFirstDOMElement(); +// ss << req.getFirstDOMElement(); + ss << req.dom; reply.content = ss.str(); reply.headers["Content-Type"] = "application/xml"; } else if (req.data) { diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index 56e2523..90cebc3 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -255,6 +255,16 @@ void BasicHTTPIOProcessor::downloadCompleted(const URL& url) { std::map >::iterator reqIter = _sendRequests.begin(); while(reqIter != _sendRequests.end()) { if (reqIter->second.first == url) { + // test 513 + std::string statusCode = url.getStatusCode(); + if (statusCode.length() > 0) { + std::string statusPrefix = statusCode.substr(0,1); + std::string statusRest = statusCode.substr(1); + Event event; + event.data = url; + event.name = "HTTP." + statusPrefix + "." + statusRest; + returnEvent(event); + } _sendRequests.erase(reqIter); return; } diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp index 98d98e1..ac570c4 100644 --- a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp @@ -158,6 +158,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) { LOG(ERROR) << "Not sure what to make of the target '" << reqCopy.target << "' - raising error" << std::endl; Event error("error.execution", Event::PLATFORM); error.sendid = reqCopy.sendid; + // test 159 still fails _interpreter->receiveInternal(error); } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a78c079..53ec38f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -109,9 +109,11 @@ foreach( W3C_TEST ${W3C_TESTS} ) if (NOT TEST_NAME MATCHES ".*sub.*") if (RUN_W3C_ECMA_TESTS AND TEST_NAME MATCHES "^ecma\\/.*") add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST}) + set_tests_properties(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "TEST FAILED") endif() if (RUN_W3C_XPATH_TESTS AND TEST_NAME MATCHES "^xpath\\/.*") add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST}) + set_tests_properties(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "TEST FAILED") endif() endif() endforeach() diff --git a/test/samples/uscxml/test-markup-passing.scxml b/test/samples/uscxml/test-markup-passing.scxml new file mode 100644 index 0000000..32866b1 --- /dev/null +++ b/test/samples/uscxml/test-markup-passing.scxml @@ -0,0 +1,54 @@ + + + + + + + 1 + 2 + + + + + + + + + + + + + + + 1 + 2 + + + 1 + 2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/uscxml/test-markup.xml b/test/samples/uscxml/test-markup.xml new file mode 100644 index 0000000..81da3d2 --- /dev/null +++ b/test/samples/uscxml/test-markup.xml @@ -0,0 +1,6 @@ + + 1 + 2 + \ No newline at end of file diff --git a/test/samples/uscxml/test-scenegraph.scxml b/test/samples/uscxml/test-scenegraph.scxml index f0d1173..0efcd6d 100644 --- a/test/samples/uscxml/test-scenegraph.scxml +++ b/test/samples/uscxml/test-scenegraph.scxml @@ -23,17 +23,17 @@ - + - + - + diff --git a/test/samples/w3c/ecma/test159.scxml b/test/samples/w3c/ecma/test159.scxml index d144855..d7b7821 100644 --- a/test/samples/w3c/ecma/test159.scxml +++ b/test/samples/w3c/ecma/test159.scxml @@ -6,8 +6,8 @@ The send tag will raise an error so var1 should not be incremented. If it is fa - - + + diff --git a/test/samples/w3c/ecma/test191.scxml b/test/samples/w3c/ecma/test191.scxml index a44856b..6e82274 100644 --- a/test/samples/w3c/ecma/test191.scxml +++ b/test/samples/w3c/ecma/test191.scxml @@ -22,7 +22,7 @@ pass, otherwise we fail. The timer insures that some event is generated and tha - + diff --git a/test/samples/w3c/ecma/test354.scxml b/test/samples/w3c/ecma/test354.scxml new file mode 100644 index 0000000..3a3c33b --- /dev/null +++ b/test/samples/w3c/ecma/test354.scxml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + foo + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/ecma/test415.scxml b/test/samples/w3c/ecma/test415.scxml new file mode 100644 index 0000000..159218b --- /dev/null +++ b/test/samples/w3c/ecma/test415.scxml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/ecma/test483.scxml b/test/samples/w3c/ecma/test483.scxml new file mode 100644 index 0000000..0a1b236 --- /dev/null +++ b/test/samples/w3c/ecma/test483.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/ecma/test513.scxml b/test/samples/w3c/ecma/test513.scxml new file mode 100644 index 0000000..c26d498 --- /dev/null +++ b/test/samples/w3c/ecma/test513.scxml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/ecma/test528.scxml b/test/samples/w3c/ecma/test528.scxml index edeb367..f0e8911 100644 --- a/test/samples/w3c/ecma/test528.scxml +++ b/test/samples/w3c/ecma/test528.scxml @@ -6,8 +6,7 @@ - - + diff --git a/test/samples/w3c/txml/test159.txml b/test/samples/w3c/txml/test159.txml index abf1925..b7245c0 100644 --- a/test/samples/w3c/txml/test159.txml +++ b/test/samples/w3c/txml/test159.txml @@ -11,7 +11,7 @@ The send tag will raise an error so var1 should not be incremented. If it is fa - + diff --git a/test/samples/w3c/txml/test191.txml b/test/samples/w3c/txml/test191.txml index 60b44a9..6f42159 100644 --- a/test/samples/w3c/txml/test191.txml +++ b/test/samples/w3c/txml/test191.txml @@ -25,7 +25,7 @@ pass, otherwise we fail. The timer insures that some event is generated and tha - + diff --git a/test/samples/w3c/txml/test354.txml b/test/samples/w3c/txml/test354.txml new file mode 100644 index 0000000..d9e643a --- /dev/null +++ b/test/samples/w3c/txml/test354.txml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + foo + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/txml/test415.txml b/test/samples/w3c/txml/test415.txml new file mode 100644 index 0000000..5bb3343 --- /dev/null +++ b/test/samples/w3c/txml/test415.txml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/txml/test483.txml b/test/samples/w3c/txml/test483.txml new file mode 100644 index 0000000..7eab75b --- /dev/null +++ b/test/samples/w3c/txml/test483.txml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/txml/test513.txml b/test/samples/w3c/txml/test513.txml new file mode 100644 index 0000000..65dda29 --- /dev/null +++ b/test/samples/w3c/txml/test513.txml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/txml/test528.txml b/test/samples/w3c/txml/test528.txml index 69b7bb2..271bb1c 100644 --- a/test/samples/w3c/txml/test528.txml +++ b/test/samples/w3c/txml/test528.txml @@ -9,8 +9,7 @@ - - + diff --git a/test/samples/w3c/xpath/test159.scxml b/test/samples/w3c/xpath/test159.scxml index 70a325d..1f2af35 100644 --- a/test/samples/w3c/xpath/test159.scxml +++ b/test/samples/w3c/xpath/test159.scxml @@ -7,7 +7,7 @@ The send tag will raise an error so var1 should not be incremented. If it is fa - + diff --git a/test/samples/w3c/xpath/test191.scxml b/test/samples/w3c/xpath/test191.scxml index 25862ac..1910eaf 100644 --- a/test/samples/w3c/xpath/test191.scxml +++ b/test/samples/w3c/xpath/test191.scxml @@ -22,7 +22,7 @@ pass, otherwise we fail. The timer insures that some event is generated and tha - + diff --git a/test/samples/w3c/xpath/test354.scxml b/test/samples/w3c/xpath/test354.scxml new file mode 100644 index 0000000..93d768d --- /dev/null +++ b/test/samples/w3c/xpath/test354.scxml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + foo + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/xpath/test415.scxml b/test/samples/w3c/xpath/test415.scxml new file mode 100644 index 0000000..2da0bef --- /dev/null +++ b/test/samples/w3c/xpath/test415.scxml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/xpath/test483.scxml b/test/samples/w3c/xpath/test483.scxml new file mode 100644 index 0000000..0a1b236 --- /dev/null +++ b/test/samples/w3c/xpath/test483.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/xpath/test513.scxml b/test/samples/w3c/xpath/test513.scxml new file mode 100644 index 0000000..bc29bb4 --- /dev/null +++ b/test/samples/w3c/xpath/test513.scxml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/samples/w3c/xpath/test528.scxml b/test/samples/w3c/xpath/test528.scxml index 7cc88f7..f8f8416 100644 --- a/test/samples/w3c/xpath/test528.scxml +++ b/test/samples/w3c/xpath/test528.scxml @@ -6,8 +6,7 @@ - - + diff --git a/test/src/test-arabica-xpath.cpp b/test/src/test-arabica-xpath.cpp index ced1de3..408cc2b 100644 --- a/test/src/test-arabica-xpath.cpp +++ b/test/src/test-arabica-xpath.cpp @@ -52,7 +52,7 @@ public: virtual Arabica::XPath::XPathValue resolveVariable(const string_type& /* namespace_uri */, const string_type& name) const { using namespace Arabica::XPath; - typename VarMap::const_iterator n = map_.find(name); + VarMap::const_iterator n = map_.find(name); if(n == map_.end()) throw UnboundVariableException(string_adaptor::asStdString(name)); return XPathValue(new StringValue((*n).second)); diff --git a/test/src/test-datamodel.cpp b/test/src/test-datamodel.cpp index b0ed107..773fe7f 100644 --- a/test/src/test-datamodel.cpp +++ b/test/src/test-datamodel.cpp @@ -19,7 +19,8 @@ int main(int argc, char** argv) { WSAStartup(MAKEWORD(2, 2), &wsaData); #endif - DataModel dm(Factory::getInstance()->createDataModel("ecmascript", NULL)); + Interpreter interpreter = Interpreter::fromXML(""); + DataModel dm(Factory::getInstance()->createDataModel("ecmascript", interpreter.getImpl().get())); dm.evalAsString("var foo = 12"); { diff --git a/test/src/test-w3c.cpp b/test/src/test-w3c.cpp index f18b339..1600c27 100644 --- a/test/src/test-w3c.cpp +++ b/test/src/test-w3c.cpp @@ -98,8 +98,11 @@ void printUsageAndExit() { class W3CStatusMonitor : public uscxml::InterpreterMonitor { void beforeCompletion(uscxml::Interpreter interpreter) { Arabica::XPath::NodeSet config = interpreter.getConfiguration(); - if (config.size() == 1 && boost::iequals(ATTR(config[0], "id"), "pass")) + if (config.size() == 1 && boost::iequals(ATTR(config[0], "id"), "pass")) { + std::cout << "TEST SUCCEEDED" << std::endl; exit(EXIT_SUCCESS); + } + std::cout << "TEST FAILED" << std::endl; exit(EXIT_FAILURE); } }; -- cgit v0.12