diff options
69 files changed, 1510 insertions, 422 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index eb8bf46..92b0369 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,16 +464,17 @@ list (APPEND USCXML_CORE_LIBS ${EVENT_LIBRARY}) if (APPLE OR IOS) find_library(AUDIOTOOLBOX AudioToolbox REQUIRED) list (APPEND USCXML_OPT_LIBS ${AUDIOTOOLBOX}) + + find_library(FOUNDATION_LIBRARY Foundation) + list (APPEND USCXML_OPT_LIBS ${FOUNDATION_LIBRARY}/Foundation) find_library(JSC_LIBRARY JavaScriptCore) if (IOS) find_library(WTF_LIBRARY WTF) - find_library(FOUNDATION_LIBRARY Foundation) find_library(ICU_LIBRARY icucore REQUIRED) list (APPEND USCXML_OPT_LIBS ${JSC_LIBRARY}) list (APPEND USCXML_OPT_LIBS ${WTF_LIBRARY}) list (APPEND USCXML_OPT_LIBS ${ICU_LIBRARY}) - list (APPEND USCXML_OPT_LIBS ${FOUNDATION_LIBRARY}/Foundation) else() list (APPEND USCXML_OPT_LIBS ${JSC_LIBRARY}) endif() diff --git a/apps/uscxml-browser.cpp b/apps/uscxml-browser.cpp index 48c1875..70fb540 100644 --- a/apps/uscxml-browser.cpp +++ b/apps/uscxml-browser.cpp @@ -89,7 +89,7 @@ void customTerminate() { << e.what() << std::endl; } catch (const std::runtime_error &e) { std::cerr << __FUNCTION__ << " caught unhandled exception. what(): " - << e.what() << std::endl; + << e.what() << std::endl; } catch (const uscxml::Event &e) { std::cerr << __FUNCTION__ << " caught unhandled exception. Event: " << e << std::endl; @@ -174,21 +174,22 @@ int main(int argc, char** argv) { // intialize http server on given port HTTPServer::getInstance(port); - LOG(INFO) << "Processing " << argv[optind]; - Interpreter interpreter = Interpreter::fromURI(argv[optind]); - if (interpreter) { - interpreter.setCmdLineOptions(argc, argv); -// interpreter->setCapabilities(Interpreter::CAN_NOTHING); -// interpreter->setCapabilities(Interpreter::CAN_BASIC_HTTP | Interpreter::CAN_GENERIC_HTTP); - - if (verbose) { - VerboseMonitor* vm = new VerboseMonitor(); - interpreter.addMonitor(vm); + while(true) { + LOG(INFO) << "Processing " << argv[optind]; + Interpreter interpreter = Interpreter::fromURI(argv[optind]); + if (interpreter) { + interpreter.setCmdLineOptions(argc, argv); + // interpreter->setCapabilities(Interpreter::CAN_NOTHING); + // interpreter->setCapabilities(Interpreter::CAN_BASIC_HTTP | Interpreter::CAN_GENERIC_HTTP); + + if (verbose) { + VerboseMonitor* vm = new VerboseMonitor(); + interpreter.addMonitor(vm); + } + + interpreter.start(); + while(interpreter.runOnMainThread(25)); } - - interpreter.start(); - while(interpreter.runOnMainThread(25)); } - return EXIT_SUCCESS; }
\ No newline at end of file diff --git a/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm b/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm index cc8debb..87ca6a9 100644 --- a/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm +++ b/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm @@ -209,10 +209,11 @@ END } if ($extensions->{'CustomIndexedGetter'}) { - push(@headerContent, "\n static JSValueRef indexedPropertyCustomGetter(uint32_t, const JSC::AccessorInfo&);"); + push(@headerContent, "\n static bool hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);"); + push(@headerContent, "\n static JSValueRef getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);"); } if ($extensions->{'CustomIndexedSetter'}) { - push(@headerContent, "\n static JSValueRef indexedPropertyCustomSetter(uint32_t, JSC::Local<JSC::Value>, const JSC::AccessorInfo&);"); + push(@headerContent, "\n static JSValueRef setPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);"); } push(@headerContent, "\n"); @@ -229,6 +230,20 @@ END classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; +END + if ($extensions->{'CustomIndexedGetter'}) { + push(@headerContent, " classDef.hasProperty = hasPropertyCustomCallback;\n"); + push(@headerContent, " classDef.getProperty = getPropertyCustomCallback;\n"); + } + if ($extensions->{'CustomIndexedSetter'}) { + push(@headerContent, " classDef.setProperty = setPropertyCustomCallback;\n"); + } + if (@{$interface->parents}) { + my $parent = @{$interface->parents}[0]; + push(@headerContent, " classDef.parentClass = JSC${parent}::getTmpl();\n"); + } + + push(@headerContent, <<END); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); @@ -449,12 +464,12 @@ END my $parameterIndex = 0; my @argList; foreach my $parameter (@{$function->parameters}) { - my $value = "arguments[$parameterIndex]"; my $type = $parameter->type; AddToImplIncludes("JSC".$type.".h") if (IsWrapperType($type)); my ($handle, $deref) = IdlToArgHandle($parameter->type, "local".ucfirst($parameter->name), "arguments[${parameterIndex}]"); push(@implContent, "\n ${handle}"); +# push(@implContent, "\n if (exception)\n return JSValueMakeUndefined(ctx);"); push(@argList, $deref); $parameterIndex++; @@ -666,8 +681,9 @@ sub IdlToArgHandle "JSStringRef stringRef${localName} = JSValueToStringCopy(ctx, ${paramName}, exception);\n" . "\t\tsize_t ${localName}MaxSize = JSStringGetMaximumUTF8CStringSize(stringRef${localName});\n" . "\t\tchar* ${localName}Buffer = new char[${localName}MaxSize];\n" . - "\t\tJSStringGetUTF8CString(stringRef${localName}, ${localName}Buffer, sizeof(${localName}Buffer));\n" . - "\t\tstd::string ${localName}(${localName}Buffer, ${localName}MaxSize);\n" . + "\t\tJSStringGetUTF8CString(stringRef${localName}, ${localName}Buffer, ${localName}MaxSize);\n" . + "\t\tstd::string ${localName}(${localName}Buffer);\n" . + "\t\tJSStringRelease(stringRef${localName});\n" . "\t\tfree(${localName}Buffer);\n", "${localName}") ; } @@ -677,7 +693,7 @@ sub IdlToArgHandle if (IsWrapperType($type)) { my $wrapperType = IdlToWrapperType($type); - return ("${wrapperType}* ${localName} = ((struct JSC${type}::JSC${type}Private*)JSObjectGetPrivate(thisObj))->nativeObj;", "*${localName}"); + return ("${wrapperType}* ${localName} = ((struct JSC${type}::JSC${type}Private*)JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception)))->nativeObj;", "*${localName}"); } print $type."\n"; diff --git a/contrib/java/.classpath b/contrib/java/.classpath new file mode 100644 index 0000000..053c69a --- /dev/null +++ b/contrib/java/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="uscxml"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/contrib/java/.project b/contrib/java/.project new file mode 100644 index 0000000..4c68397 --- /dev/null +++ b/contrib/java/.project @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>uscxml</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> + <linkedResources> + <link> + <name>uscxml</name> + <type>2</type> + <location>/Users/sradomski/Documents/TK/Code/uscxml/build/cli/src/bindings/swig/java</location> + </link> + </linkedResources> +</projectDescription> diff --git a/contrib/java/src/org/uscxml/tests/TestDataModel.java b/contrib/java/src/org/uscxml/tests/TestDataModel.java new file mode 100644 index 0000000..c9d8ae0 --- /dev/null +++ b/contrib/java/src/org/uscxml/tests/TestDataModel.java @@ -0,0 +1,108 @@ +package org.uscxml.tests; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.Factory; +import org.uscxml.Interpreter; +import org.uscxml.JavaDataModel; +import org.uscxml.SWIGTYPE_p_Arabica__DOM__DocumentT_std__string_t; +import org.uscxml.SWIGTYPE_p_Arabica__DOM__ElementT_std__string_t; +import org.uscxml.SWIGTYPE_p_boost__shared_ptrT_uscxml__DataModelImpl_t; +import org.uscxml.SWIGTYPE_p_uscxml__InterpreterImpl; +import org.uscxml.StringSet; + + +public class TestDataModel extends JavaDataModel { + + @Override + public JavaDataModel create(Interpreter interpreter) { + return new JavaDataModel(); + } + + @Override + public StringSet getNames() { + StringSet ss = new StringSet(); + ss.insert("java"); + return ss; + } + + @Override + public boolean validate(String location, String schema) { + return true; + } + + @Override + public void setEvent(Event event) { + /* make sure the fields of event are available as _event to conform + * with the SCXML draft + */ + } + + @Override + public Data getStringAsData(String content) { + Data data = new Data(); + return data; + } + + @Override + public long getLength(String expr) { + return 0; + } + + @Override + public void setForeach(String item, String array, String index, long iteration) { + } + + @Override + public void eval(SWIGTYPE_p_Arabica__DOM__ElementT_std__string_t scriptElem, String expr) { + } + + @Override + public String evalAsString(String expr) { + return ""; + } + + @Override + public boolean evalAsBool(String expr) { + return true; + } + + @Override + public boolean isDeclared(String expr) { + return true; + } + + @Override + public void assign(SWIGTYPE_p_Arabica__DOM__ElementT_std__string_t assignElem, SWIGTYPE_p_Arabica__DOM__DocumentT_std__string_t doc, String content) { + } + + @Override + public void assign(String location, Data data) { + super.assign(location, data); + } + + @Override + public void init(SWIGTYPE_p_Arabica__DOM__ElementT_std__string_t dataElem, SWIGTYPE_p_Arabica__DOM__DocumentT_std__string_t doc, String content) { + super.init(dataElem, doc, content); + } + + @Override + public void init(String location, Data data) { + super.init(location, data); + } + + /** + * @param args + */ + public static void main(String[] args) { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64_d.jnilib"); + + TestDataModel datamodel = new TestDataModel(); + Factory.getInstance().registerDataModel(datamodel); + + Interpreter interpreter = Interpreter.fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/samples/uscxml/test-java-datamodel.scxml"); + while(true) + interpreter.interpret(); + } + +} diff --git a/contrib/java/src/org/uscxml/tests/TestInvoker.java b/contrib/java/src/org/uscxml/tests/TestInvoker.java new file mode 100644 index 0000000..b41bd43 --- /dev/null +++ b/contrib/java/src/org/uscxml/tests/TestInvoker.java @@ -0,0 +1,65 @@ +package org.uscxml.tests; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.Factory; +import org.uscxml.Interpreter; +import org.uscxml.InvokeRequest; +import org.uscxml.JavaInvoker; +import org.uscxml.SendRequest; +import org.uscxml.StringSet; + + +public class TestInvoker extends JavaInvoker { + + @Override + public StringSet getNames() { + StringSet ss = new StringSet(); + ss.insert("java"); + return ss; + } + + @Override + public Data getDataModelVariables() { + Data data = new Data(); + data.getArray().add(new Data("foo", Data.Type.VERBATIM)); + return data; + } + + @Override + public void send(SendRequest req) { + System.out.println("send"); + } + + @Override + public void invoke(InvokeRequest req) { + System.out.println("invoke"); + + System.out.println(Data.toJSON(req.getData())); + System.out.println(req.getXML()); + + Event ev = new Event(); + ev.setName("foo"); + returnEvent(ev); + } + + @Override + public JavaInvoker create(Interpreter interpreter) { + return new TestInvoker(); + } + + /** + * @param args + */ + public static void main(String[] args) { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64_d.jnilib"); + + TestInvoker invoker = new TestInvoker(); + Factory.getInstance().registerInvoker(invoker); + + Interpreter interpreter = Interpreter.fromURI("/Users/sradomski/Documents/TK/Code/uscxml/test/samples/uscxml/test-java-invoker.scxml"); + while(true) + interpreter.interpret(); + } + +} diff --git a/src/bindings/swig/java/JavaDataModel.cpp b/src/bindings/swig/java/JavaDataModel.cpp new file mode 100644 index 0000000..896794b --- /dev/null +++ b/src/bindings/swig/java/JavaDataModel.cpp @@ -0,0 +1,8 @@ +#include "JavaDataModel.h" + +namespace uscxml { + +JavaDataModel::JavaDataModel() {} +JavaDataModel::~JavaDataModel() {} + +}
\ No newline at end of file diff --git a/src/bindings/swig/java/JavaDataModel.h b/src/bindings/swig/java/JavaDataModel.h new file mode 100644 index 0000000..9188cf6 --- /dev/null +++ b/src/bindings/swig/java/JavaDataModel.h @@ -0,0 +1,75 @@ +#ifndef JAVADataModel_H_7U446XJQ +#define JAVADataModel_H_7U446XJQ + +#include "../../../uscxml/Message.h" +#include "../../../uscxml/Factory.h" +#include "../../../uscxml/Interpreter.h" + +namespace uscxml { + +class JavaDataModel : public DataModelImpl { +public: + JavaDataModel(); + virtual ~JavaDataModel(); + + virtual JavaDataModel* create(Interpreter interpreter) { + return new JavaDataModel(); + } + + virtual boost::shared_ptr<DataModelImpl> create(InterpreterImpl* interpreter) { + return boost::shared_ptr<DataModelImpl>(create(interpreter->shared_from_this())); + } + virtual std::set<std::string> getNames() { + return std::set<std::string>(); + }; + + virtual bool validate(const std::string& location, const std::string& schema) { + return true; + } + virtual void setEvent(const Event& event) {} + virtual Data getStringAsData(const std::string& content) { + Data data; + return data; + } + + // foreach + virtual uint32_t getLength(const std::string& expr) { + return 0; + } + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) {} + virtual void pushContext() {} + virtual void popContext() {} + + virtual void eval(const Arabica::DOM::Element<std::string>& scriptElem, + const std::string& expr) {} + + virtual std::string evalAsString(const std::string& expr) { + return ""; + } + virtual bool evalAsBool(const std::string& expr) { + return false; + } + + virtual bool isDeclared(const std::string& expr) { + return false; + } + + virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) {} + virtual void assign(const std::string& location, const Data& data) {} + + virtual void init(const Arabica::DOM::Element<std::string>& dataElem, + const Arabica::DOM::Document<std::string>& doc, + const std::string& content) {} + virtual void init(const std::string& location, const Data& data) {} + + +}; + +} + +#endif /* end of include guard: JAVADataModel_H_7U446XJQ */ diff --git a/src/bindings/swig/java/JavaInvoker.cpp b/src/bindings/swig/java/JavaInvoker.cpp index c10ae6d..e1c6a31 100644 --- a/src/bindings/swig/java/JavaInvoker.cpp +++ b/src/bindings/swig/java/JavaInvoker.cpp @@ -4,5 +4,5 @@ namespace uscxml { JavaInvoker::JavaInvoker() {} JavaInvoker::~JavaInvoker() {} - + }
\ No newline at end of file diff --git a/src/bindings/swig/java/JavaInvoker.h b/src/bindings/swig/java/JavaInvoker.h index 0a13176..e4db759 100644 --- a/src/bindings/swig/java/JavaInvoker.h +++ b/src/bindings/swig/java/JavaInvoker.h @@ -11,23 +11,23 @@ class JavaInvoker : public InvokerImpl { public: JavaInvoker(); virtual ~JavaInvoker(); - + virtual std::set<std::string> getNames() { return std::set<std::string>(); }; - + virtual Data getDataModelVariables() { Data data; return data; } - + virtual void send(const SendRequest& req) {} virtual void invoke(const InvokeRequest& req) {} - + virtual JavaInvoker* create(Interpreter interpreter) { return new JavaInvoker(); } - + virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter) { return boost::shared_ptr<InvokerImpl>(create(interpreter->shared_from_this())); } diff --git a/src/bindings/swig/java/uscxml.i b/src/bindings/swig/java/uscxml.i index af979d0..81ac83e 100644 --- a/src/bindings/swig/java/uscxml.i +++ b/src/bindings/swig/java/uscxml.i @@ -48,10 +48,12 @@ typedef uscxml::SendRequest SendRequest; #include "../../../uscxml/Factory.h" #include "../../../uscxml/Interpreter.h" #include "JavaInvoker.h" +#include "JavaDataModel.h" using namespace uscxml; #include "JavaInvoker.cpp" +#include "JavaDataModel.cpp" %} @@ -64,6 +66,7 @@ using namespace uscxml; %ignore uscxml::Interpreter::getDelayQueue(); %ignore uscxml::JavaInvoker::create(InterpreterImpl*); +%ignore uscxml::JavaDataModel::create(InterpreterImpl*); %template(DataMap) std::map<std::string, uscxml::Data>; %template(DataList) std::list<uscxml::Data>; @@ -71,6 +74,7 @@ using namespace uscxml; %feature("director") uscxml::JavaInvoker; +%feature("director") uscxml::JavaDataModel; //*********************************************** // Parse the header file to generate wrappers @@ -81,4 +85,5 @@ using namespace uscxml; %include "../../../uscxml/Message.h" %include "../../../uscxml/Interpreter.h" %include "JavaInvoker.h" +%include "JavaDataModel.h" diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index 9b6a84a..21e820a 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -129,6 +129,7 @@ Factory::Factory() { } } #else +#if 1 #ifdef UMUNDO_FOUND { UmundoInvoker* invoker = new UmundoInvoker(); @@ -166,7 +167,7 @@ Factory::Factory() { } #endif -#if (defined OPENAL_FOUND && (defined LIBSNDFILE_FOUND || defined AUDIOTOOLBOX_FOUND)) +#if (defined OPENAL_FOUND && (defined LIBSNDFILE_FOUND || defined AUDIOTOOLBOX_FOUND)) { OpenALInvoker* invoker = new OpenALInvoker(); registerInvoker(invoker); @@ -218,12 +219,14 @@ Factory::Factory() { registerIOProcessor(ioProcessor); } #endif +#endif // these are always available { NULLDataModel* dataModel = new NULLDataModel(); registerDataModel(dataModel); } +#if 0 { XHTMLInvoker* invoker = new XHTMLInvoker(); registerInvoker(invoker); @@ -274,6 +277,7 @@ Factory::Factory() { } #endif +#endif } Factory::~Factory() { diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index b6266e2..b529f57 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -46,8 +46,12 @@ std::map<std::string, boost::weak_ptr<InterpreterImpl> > Interpreter::_instances tthread::recursive_mutex Interpreter::_instanceMutex; boost::uuids::random_generator InterpreterImpl::uuidGen; -const std::string InterpreterImpl::getUUID() { - return boost::lexical_cast<std::string>(uuidGen()); + +std::string InterpreterImpl::getUUID() { + boost::uuids::uuid uuid = uuidGen(); + std::ostringstream os; + os << uuid; + return os.str(); } InterpreterImpl::InterpreterImpl() { @@ -131,6 +135,16 @@ Interpreter Interpreter::fromURI(const std::string& uri) { Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source) { tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex); + + std::map<std::string, boost::weak_ptr<InterpreterImpl> >::iterator instIter = _instances.begin(); + while(instIter != _instances.end()) { + if (!instIter->second.lock()) { + _instances.erase(instIter++); + } else { + instIter++; + } + } + boost::shared_ptr<InterpreterDraft6> interpreterImpl = boost::shared_ptr<InterpreterDraft6>(new InterpreterDraft6); Interpreter interpreter; NameSpacingParser parser; @@ -186,9 +200,9 @@ void InterpreterImpl::setName(const std::string& name) { } InterpreterImpl::~InterpreterImpl() { + _running = false; tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (_thread) { - _running = false; // unblock event queue Event event; _externalQueue.push(event); @@ -197,6 +211,7 @@ InterpreterImpl::~InterpreterImpl() { } if (_sendQueue) delete _sendQueue; + // if (_httpServlet) // delete _httpServlet; } @@ -709,12 +724,12 @@ void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) { return; } - if (sendReq.dom) { - std::stringstream ss; - ss << sendReq.dom; - sendReq.xml = ss.str(); - _dataModel.replaceExpressions(sendReq.xml); - } + if (sendReq.dom) { + std::stringstream ss; + ss << sendReq.dom; + sendReq.xml = ss.str(); + _dataModel.replaceExpressions(sendReq.xml); + } assert(_sendIds.find(sendReq.sendid) == _sendIds.end()); _sendIds[sendReq.sendid] = std::make_pair(this, sendReq); @@ -1132,17 +1147,22 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont } std::stringstream srcContent; - if (_cachedURLs.find(scriptUrl.asString()) != _cachedURLs.end() && false) { - srcContent << _cachedURLs[scriptUrl.asString()]; - } else { - srcContent << scriptUrl; - if (scriptUrl.downloadFailed()) { - LOG(ERROR) << "script element source cannot be downloaded"; + try { + if (_cachedURLs.find(scriptUrl.asString()) != _cachedURLs.end() && false) { + srcContent << _cachedURLs[scriptUrl.asString()]; + } else { + srcContent << scriptUrl; + if (scriptUrl.downloadFailed()) { + LOG(ERROR) << "script element source cannot be downloaded"; + } + _cachedURLs[scriptUrl.asString()] = scriptUrl; } - _cachedURLs[scriptUrl.asString()] = scriptUrl; + } catch (Event exception) { + // script failed to download + receive(exception); + return; } - try { _dataModel.eval((Element<std::string>)content, srcContent.str()); } @@ -1437,7 +1457,7 @@ Arabica::XPath::NodeSet<std::string> InterpreterImpl::getInitialStates(Arabica:: NodeSet<std::string> InterpreterImpl::getTargetStates(const Arabica::DOM::Node<std::string>& transition) { NodeSet<std::string> targetStates; - assert(boost::iequals(LOCALNAME(transition), "transition")); + assert(boost::ends_with(TAGNAME(transition), "transition")); // if we are called with a state, process all its transitions if (isState(transition) || (transition.getNodeType() == Node_base::ELEMENT_NODE && boost::iequals(_xmlNSPrefix + "initial", TAGNAME(transition)))) { diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index d0da78f..f7ce708 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -236,7 +236,7 @@ public: static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagName, const Arabica::XPath::NodeSet<std::string>& nodeSet); Arabica::DOM::Node<std::string> findLCCA(const Arabica::XPath::NodeSet<std::string>& states); Arabica::XPath::NodeSet<std::string> getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2); - static const std::string getUUID(); + static std::string getUUID(); protected: InterpreterImpl(); @@ -595,7 +595,7 @@ public: Arabica::XPath::NodeSet<std::string> getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { return _impl->getProperAncestors(s1, s2); } - static const std::string getUUID() { + static std::string getUUID() { return InterpreterImpl::getUUID(); } diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp index 2e82b69..266b4be 100644 --- a/src/uscxml/Message.cpp +++ b/src/uscxml/Message.cpp @@ -568,7 +568,7 @@ std::string Data::toJSON(const Data& data) { seperator = ", "; arrayIter++; } - os << std::endl << indent << "]"; + os << "]"; } else if (data.atom.size() > 0) { if (data.type == Data::VERBATIM) { os << "\"" << data.atom << "\""; diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp index 65cd5ee..a58818a 100644 --- a/src/uscxml/URL.cpp +++ b/src/uscxml/URL.cpp @@ -3,6 +3,7 @@ #include "uscxml/config.h" #include <fstream> +#include <boost/lexical_cast.hpp> #include <stdio.h> /* defines FILENAME_MAX */ #ifdef _WIN32 @@ -72,16 +73,21 @@ URLImpl::operator Data() { data.compound["path"] = Data(_uri.path(), Data::VERBATIM); data.compound["port"] = Data(_uri.port()); data.compound["isAbsolute"] = Data(_uri.is_absolute() ? "true" : "false"); + if (_statusCode.length() > 0) + data.compound["statusCode"] = Data(_statusCode, Data::VERBATIM); + if (_statusMsg.length() > 0) + data.compound["statusMsg"] = Data(_statusMsg, Data::VERBATIM); + std::vector<std::string>::iterator pathIter = _pathComponents.begin(); while(pathIter != _pathComponents.end()) { data.compound["pathComponent"].array.push_back(Data(*pathIter, Data::VERBATIM)); pathIter++; } - + return data; } - + CURL* URLImpl::getCurlHandle() { if (_handle == NULL) { _handle = curl_easy_init(); @@ -93,7 +99,7 @@ CURL* URLImpl::getCurlHandle() { size_t URLImpl::writeHandler(void *ptr, size_t size, size_t nmemb, void *userdata) { URLImpl* url = (URLImpl*)userdata; - url->_inContent.write((char*)ptr, size * nmemb); + url->_rawInContent.write((char*)ptr, size * nmemb); monIter_t monIter = url->_monitors.begin(); while(monIter != url->_monitors.end()) { @@ -106,7 +112,7 @@ size_t URLImpl::writeHandler(void *ptr, size_t size, size_t nmemb, void *userdat size_t URLImpl::headerHandler(void *ptr, size_t size, size_t nmemb, void *userdata) { URLImpl* url = (URLImpl*)userdata; - url->_inHeader.write((char*)ptr, size * nmemb); + url->_rawInHeader.write((char*)ptr, size * nmemb); monIter_t monIter = url->_monitors.begin(); while(monIter != url->_monitors.end()) { @@ -119,10 +125,13 @@ size_t URLImpl::headerHandler(void *ptr, size_t size, size_t nmemb, void *userda void URLImpl::downloadStarted() { // LOG(INFO) << "Starting download of " << asString() << std::endl; - _inContent.str(""); - _inContent.clear(); - _inHeader.str(""); - _inHeader.clear(); + _rawInContent.str(""); + _rawInContent.clear(); + _rawInHeader.str(""); + _rawInHeader.clear(); + + _statusMsg = ""; + _statusCode = ""; monIter_t monIter = _monitors.begin(); while(monIter != _monitors.end()) { @@ -134,7 +143,32 @@ void URLImpl::downloadStarted() { void URLImpl::downloadCompleted() { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); -// LOG(INFO) << "Finished downloading " << asString() << " with " << _inContent.str().size() << " bytes"; + if (boost::iequals(scheme(), "http")) { + // process header fields + std::string line; + while (std::getline(_rawInHeader, line)) { + size_t colon = line.find_first_of(":"); + size_t newline = line.find_first_of("\r\n"); + if (newline == std::string::npos) + newline = line.size(); + + if (colon == std::string::npos) { + _statusMsg = line.substr(0, newline); + if (_statusMsg.length() >= 11) + _statusCode = _statusMsg.substr(9, 3); + } else { + std::string key = line.substr(0, colon); + size_t firstChar = line.find_first_not_of(": ", colon, 2); + if (firstChar == std::string::npos) { + // nothing but spaces? + _inHeaders[line.substr(0, newline)] = ""; + } else { + std::string value = line.substr(firstChar, newline - firstChar); + _inHeaders[key] = value; + } + } + } + } _hasFailed = false; _isDownloaded = true; @@ -152,6 +186,7 @@ void URLImpl::downloadFailed(CURLcode errorCode) { LOG(ERROR) << "Downloading " << asString() << " failed: " << curl_easy_strerror(errorCode); + _error = curl_easy_strerror(errorCode); _hasFailed = true; _isDownloaded = false; _condVar.notify_all(); @@ -164,40 +199,32 @@ void URLImpl::downloadFailed(CURLcode errorCode) { } -const std::map<std::string, std::string> URLImpl::getInHeaderFields() { - if (!_isDownloaded) { - download(true); +const std::string URLImpl::getInHeaderField(const std::string& key) { + std::map<std::string, std::string> headerFields = getInHeaderFields(); + if (headerFields.find(key) != headerFields.end()) { + return headerFields[key]; } + return ""; +} - std::map<std::string, std::string> headerFields; - std::string line; - while (std::getline(_inHeader, line)) { - size_t colon = line.find_first_of(":"); - size_t newline = line.find_first_of("\r\n"); - if (newline == std::string::npos) - newline = line.size(); - - if (colon == std::string::npos) { - if (headerFields.size() == 0) { - // put http status in a key that can never occur otherwise - headerFields["status:"] = line.substr(0, newline); - } else { - headerFields[line.substr(0, newline)] = line.substr(0, newline); // this should never happen - } - } else { - std::string key = line.substr(0, colon); - size_t firstChar = line.find_first_not_of(": ", colon, 2); - if (firstChar == std::string::npos) { - // nothing but spaces? - headerFields[line.substr(0, newline)] = ""; - } else { - std::string value = line.substr(firstChar, newline - firstChar); - headerFields[key] = value; - } - } - } +const std::string URLImpl::getStatusCode() { + if (!_isDownloaded) + download(true); + return _statusCode; +} - return headerFields; +const std::string URLImpl::getStatusMessage() { + if (!_isDownloaded) + download(true); + return _statusMsg; +} + + +const std::map<std::string, std::string> URLImpl::getInHeaderFields() { + if (!_isDownloaded) + download(true); + + return _inHeaders; } void URLImpl::setRequestType(const std::string& requestType) { @@ -212,7 +239,7 @@ const std::string URLImpl::getInContent(bool forceReload) { if (!_isDownloaded) { download(true); } - return _inContent.str(); + return _rawInContent.str(); } const void URLImpl::download(bool blocking) { @@ -228,6 +255,22 @@ const void URLImpl::download(bool blocking) { while(!_isDownloaded && !_hasFailed) { _condVar.wait(_mutex); // wait for notification } + if (_hasFailed) { + Event exception; + exception.name = "error.communication"; + exception.data = URL(shared_from_this()); + if (_error.length() > 0) + exception.data.compound["reason"] = Data(_error, Data::VERBATIM); + throw exception; + } + if (boost::iequals(scheme(), "http")) { + if (_statusCode.size() > 0 && boost::lexical_cast<int>(_statusCode) > 400) { + Event exception; + exception.name = "error.communication"; + exception.data = URL(shared_from_this()); + throw exception; + } + } } } @@ -503,13 +546,17 @@ void URLFetcher::perform() { CURLMsg *msg; /* for picking up messages with the transfer status */ int msgsLeft; /* how many messages are left */ int stillRunning; + CURLMcode err; { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); if (_handlesToURLs.empty()) { _condVar.wait(_mutex); } - curl_multi_perform(_multiHandle, &stillRunning); + err = curl_multi_perform(_multiHandle, &stillRunning); + if (err != CURLM_OK) { + LOG(WARNING) << "curl_multi_perform: " << curl_multi_strerror(err); + } } do { @@ -530,21 +577,28 @@ void URLFetcher::perform() { { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - curl_multi_timeout(_multiHandle, &curlTimeOut); + err = curl_multi_timeout(_multiHandle, &curlTimeOut); + if (err != CURLM_OK) { + LOG(WARNING) << "curl_multi_timeout: " << curl_multi_strerror(err); + } } if(curlTimeOut >= 0) { timeout.tv_sec = curlTimeOut / 1000; - if(timeout.tv_sec > 1) + if(timeout.tv_sec > 1) { timeout.tv_sec = 1; - else + } else { timeout.tv_usec = (curlTimeOut % 1000) * 1000; + } } /* get file descriptors from the transfers */ { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - curl_multi_fdset(_multiHandle, &fdread, &fdwrite, &fdexcep, &maxfd); + err = curl_multi_fdset(_multiHandle, &fdread, &fdwrite, &fdexcep, &maxfd); + if (err != CURLM_OK) { + LOG(WARNING) << "curl_multi_fdset: " << curl_multi_strerror(err); + } } rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); @@ -556,9 +610,12 @@ void URLFetcher::perform() { case 0: /* timeout */ default: { /* action */ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - curl_multi_perform(_multiHandle, &stillRunning); + err = curl_multi_perform(_multiHandle, &stillRunning); + if (err != CURLM_OK) { + LOG(WARNING) << "curl_multi_perform: " << curl_multi_strerror(err); + } + break; } - break; } { @@ -568,11 +625,13 @@ void URLFetcher::perform() { switch (msg->data.result) { case CURLM_OK: _handlesToURLs[msg->easy_handle].downloadCompleted(); - curl_multi_remove_handle(_multiHandle, msg->easy_handle); + err = curl_multi_remove_handle(_multiHandle, msg->easy_handle); + if (err != CURLM_OK) { + LOG(WARNING) << "curl_multi_remove_handle: " << curl_multi_strerror(err); + } + _handlesToURLs.erase(msg->easy_handle); break; - default: - LOG(ERROR) << "Unhandled curl status"; case CURLM_BAD_HANDLE: case CURLM_BAD_EASY_HANDLE: case CURLE_FILE_COULDNT_READ_FILE: @@ -582,9 +641,15 @@ void URLFetcher::perform() { case CURLM_UNKNOWN_OPTION: case CURLM_LAST: _handlesToURLs[msg->easy_handle].downloadFailed(msg->data.result); - curl_multi_remove_handle(_multiHandle, msg->easy_handle); + err = curl_multi_remove_handle(_multiHandle, msg->easy_handle); + if (err != CURLM_OK) { + LOG(WARNING) << "curl_multi_remove_handle: " << curl_multi_strerror(err); + } + _handlesToURLs.erase(msg->easy_handle); break; + default: + LOG(ERROR) << "Unhandled curl status"; } } else { LOG(ERROR) << "Curl reports info on unfinished download?!"; diff --git a/src/uscxml/URL.h b/src/uscxml/URL.h index 646ea3f..b6d8a86 100644 --- a/src/uscxml/URL.h +++ b/src/uscxml/URL.h @@ -80,6 +80,11 @@ public: void setRequestType(const std::string& requestType); const std::map<std::string, std::string> getInHeaderFields(); + const std::string getInHeaderField(const std::string& key); + const std::string getStatusCode(); + const std::string getStatusMessage(); + + const std::string getInContent(bool forceReload = false); const void download(bool blocking = false); @@ -105,8 +110,12 @@ protected: std::string _requestType; CURL* _handle; - std::stringstream _inContent; - std::stringstream _inHeader; + std::stringstream _rawInContent; + std::stringstream _rawInHeader; + + std::string _statusCode; + std::string _statusMsg; + std::map<std::string, std::string> _inHeaders; Arabica::io::URI _uri; std::vector<std::string> _pathComponents; @@ -115,6 +124,7 @@ protected: bool _hasFailed; std::string _localFile; + std::string _error; tthread::condition_variable _condVar; tthread::recursive_mutex _mutex; @@ -151,6 +161,16 @@ public: const std::map<std::string, std::string> getInHeaderFields() const { return _impl->getInHeaderFields(); } + const std::string getInHeaderField(const std::string& key) const { + return _impl->getInHeaderField(key); + } + const std::string getStatusCode() const { + return _impl->getStatusCode(); + } + const std::string getStatusMessage() const { + return _impl->getStatusMessage(); + } + const std::string getInContent() const { return _impl->getInContent(); } @@ -230,7 +250,7 @@ public: operator Data() { return _impl->operator Data(); } - + protected: void downloadStarted() { return _impl->downloadStarted(); diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp index 950c7c6..14028fa 100644 --- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp +++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp @@ -73,6 +73,8 @@ void DelayedEventQueue::stop() { if (_isStarted) { _isStarted = false; event_base_loopbreak(_eventLoop); + } + if (_thread) { _thread->join(); delete _thread; } diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp index 0291ab1..0c82f8b 100644 --- a/src/uscxml/interpreter/InterpreterDraft6.cpp +++ b/src/uscxml/interpreter/InterpreterDraft6.cpp @@ -157,6 +157,10 @@ void InterpreterDraft6::mainEventLoop() { (*monIter)->beforeMicroStep(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeMicroStep on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + _mutex.unlock(); + goto EXIT_INTERPRETER; } catch (...) { LOG(ERROR) << "An exception occured when calling beforeMicroStep on monitors"; } @@ -185,6 +189,10 @@ void InterpreterDraft6::mainEventLoop() { (*monIter)->beforeTakingTransitions(shared_from_this(), enabledTransitions); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeTakingTransitions on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + _mutex.unlock(); + goto EXIT_INTERPRETER; } catch (...) { LOG(ERROR) << "An exception occured when calling beforeTakingTransitions on monitors"; } @@ -217,6 +225,10 @@ void InterpreterDraft6::mainEventLoop() { (*monIter)->onStableConfiguration(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling onStableConfiguration on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + _mutex.unlock(); + goto EXIT_INTERPRETER; } catch (...) { LOG(ERROR) << "An exception occured when calling onStableConfiguration on monitors"; } @@ -279,8 +291,9 @@ void InterpreterDraft6::mainEventLoop() { if (boost::iequals(autoForward, "true")) { try { // do not autoforward to invokers that send to #_parent from the SCXML IO Processor! - if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor")) - _invokers[invokeId].send(_currEvent); + // Yes do so, see test229! + // if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor")) + _invokers[invokeId].send(_currEvent); } catch(...) { LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId; } @@ -302,6 +315,9 @@ EXIT_INTERPRETER: (*monIter)->beforeCompletion(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeCompletion on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + exitInterpreter(); } catch (...) { LOG(ERROR) << "An exception occured when calling beforeCompletion on monitors"; } @@ -323,6 +339,9 @@ EXIT_INTERPRETER: (*monIter)->afterCompletion(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling afterCompletion on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + exitInterpreter(); } catch (...) { LOG(ERROR) << "An exception occured when calling afterCompletion on monitors"; } @@ -610,6 +629,7 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e if (!isTargetless(t)) { Node<std::string> ancestor; Node<std::string> source = getSourceState(t); +// std::cout << t << std::endl << TAGNAME(t) << std::endl; NodeSet<std::string> tStates = getTargetStates(t); bool isInternal = (HAS_ATTR(t, "type") && boost::iequals(ATTR(t, "type"), "internal")); // external is default bool allDescendants = true; @@ -670,6 +690,9 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e (*monIter)->beforeExitingStates(shared_from_this(), statesToExit); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeExitingStates on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + exitInterpreter(); } catch (...) { LOG(ERROR) << "An exception occured when calling beforeExitingStates on monitors"; } @@ -731,6 +754,9 @@ void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& e (*monIter)->afterExitingStates(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling afterExitingStates on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + exitInterpreter(); } catch (...) { LOG(ERROR) << "An exception occured when calling afterExitingStates on monitors"; } @@ -856,6 +882,9 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& (*monIter)->beforeEnteringStates(shared_from_this(), statesToEnter); } catch (Event e) { LOG(ERROR) << "Syntax error when calling beforeEnteringStates on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + exitInterpreter(); } catch (...) { LOG(ERROR) << "An exception occured when calling beforeEnteringStates on monitors"; } @@ -924,6 +953,9 @@ void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& (*monIter)->afterEnteringStates(shared_from_this()); } catch (Event e) { LOG(ERROR) << "Syntax error when calling afterEnteringStates on monitors: " << std::endl << e << std::endl; + } catch (boost::bad_weak_ptr e) { + LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; + return; } catch (...) { LOG(ERROR) << "An exception occured when calling afterEnteringStates on monitors"; } diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 33746a5..2c877b2 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -370,6 +370,14 @@ void JSCDataModel::setForeach(const std::string& item, } bool JSCDataModel::isDeclared(const std::string& expr) { + JSStringRef scriptJS = JSStringCreateWithUTF8CString(expr.c_str()); + JSValueRef exception = NULL; + JSValueRef result = JSEvaluateScript(_ctx, scriptJS, NULL, NULL, 0, &exception); + JSStringRelease(scriptJS); + + if (exception || JSValueIsNull(_ctx, result)) { + return false; + } return true; } diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.cpp index 6ceb642..3f967dd 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.cpp @@ -53,8 +53,9 @@ bool JSCAttr::valueAttrSetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef JSStringRef stringReflocalValue = JSValueToStringCopy(ctx, value, exception); size_t localValueMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalValue); char* localValueBuffer = new char[localValueMaxSize]; - JSStringGetUTF8CString(stringReflocalValue, localValueBuffer, sizeof(localValueBuffer)); - std::string localValue(localValueBuffer, localValueMaxSize); + JSStringGetUTF8CString(stringReflocalValue, localValueBuffer, localValueMaxSize); + std::string localValue(localValueBuffer); + JSStringRelease(stringReflocalValue); free(localValueBuffer); privData->nativeObj->setValue(localValue); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.h index 5efc53a..01628a6 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCAttr.h @@ -57,6 +57,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCDATASection.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCDATASection.h index a4d86f2..9fe225b 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCDATASection.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCDATASection.h @@ -52,6 +52,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCText::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.cpp index c7ce20a..f64b4c9 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.cpp @@ -38,8 +38,9 @@ bool JSCCharacterData::dataAttrSetter(JSContextRef ctx, JSObjectRef thisObj, JSS JSStringRef stringReflocalData = JSValueToStringCopy(ctx, value, exception); size_t localDataMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalData); char* localDataBuffer = new char[localDataMaxSize]; - JSStringGetUTF8CString(stringReflocalData, localDataBuffer, sizeof(localDataBuffer)); - std::string localData(localDataBuffer, localDataMaxSize); + JSStringGetUTF8CString(stringReflocalData, localDataBuffer, localDataMaxSize); + std::string localData(localDataBuffer); + JSStringRelease(stringReflocalData); free(localDataBuffer); privData->nativeObj->setData(localData); @@ -90,8 +91,9 @@ JSValueRef JSCCharacterData::appendDataCallback(JSContextRef ctx, JSObjectRef fu JSStringRef stringReflocalArg = JSValueToStringCopy(ctx, arguments[0], exception); size_t localArgMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalArg); char* localArgBuffer = new char[localArgMaxSize]; - JSStringGetUTF8CString(stringReflocalArg, localArgBuffer, sizeof(localArgBuffer)); - std::string localArg(localArgBuffer, localArgMaxSize); + JSStringGetUTF8CString(stringReflocalArg, localArgBuffer, localArgMaxSize); + std::string localArg(localArgBuffer); + JSStringRelease(stringReflocalArg); free(localArgBuffer); @@ -117,8 +119,9 @@ JSValueRef JSCCharacterData::insertDataCallback(JSContextRef ctx, JSObjectRef fu JSStringRef stringReflocalArg = JSValueToStringCopy(ctx, arguments[1], exception); size_t localArgMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalArg); char* localArgBuffer = new char[localArgMaxSize]; - JSStringGetUTF8CString(stringReflocalArg, localArgBuffer, sizeof(localArgBuffer)); - std::string localArg(localArgBuffer, localArgMaxSize); + JSStringGetUTF8CString(stringReflocalArg, localArgBuffer, localArgMaxSize); + std::string localArg(localArgBuffer); + JSStringRelease(stringReflocalArg); free(localArgBuffer); @@ -166,8 +169,9 @@ JSValueRef JSCCharacterData::replaceDataCallback(JSContextRef ctx, JSObjectRef f JSStringRef stringReflocalArg = JSValueToStringCopy(ctx, arguments[2], exception); size_t localArgMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalArg); char* localArgBuffer = new char[localArgMaxSize]; - JSStringGetUTF8CString(stringReflocalArg, localArgBuffer, sizeof(localArgBuffer)); - std::string localArg(localArgBuffer, localArgMaxSize); + JSStringGetUTF8CString(stringReflocalArg, localArgBuffer, localArgMaxSize); + std::string localArg(localArgBuffer); + JSStringRelease(stringReflocalArg); free(localArgBuffer); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.h index 2620468..0bdca74 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCCharacterData.h @@ -60,6 +60,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCComment.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCComment.h index c1678ea..7c4e96f 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCComment.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCComment.h @@ -52,6 +52,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCCharacterData::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOM.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOM.h index e2b8a4d..bffeab8 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOM.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOM.h @@ -3,11 +3,21 @@ #include "uscxml/Interpreter.h" #include <JavaScriptCore/JavaScriptCore.h> +#include <XPath/XPath.hpp> #define JSC_DESTRUCTOR(type) \ static void jsDestructor(JSObjectRef object) { \ + type* thing = static_cast<type*>(JSObjectGetPrivate(object)); \ + if (thing) {\ + delete thing->nativeObj; \ + delete thing; \ + JSObjectSetPrivate(object, NULL);\ + }\ +} + +#define JSC_DESTRUCTOR_KEEP_WRAPPED(type) \ +static void jsDestructor(JSObjectRef object) { \ type* thing = static_cast<type*>(JSObjectGetPrivate(object)); \ -delete thing->nativeObj; \ delete thing; \ } diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOMImplementation.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOMImplementation.cpp index 66c9666..72d4beb 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOMImplementation.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOMImplementation.cpp @@ -33,15 +33,17 @@ JSValueRef JSCDOMImplementation::hasFeatureCallback(JSContextRef ctx, JSObjectRe JSStringRef stringReflocalFeature = JSValueToStringCopy(ctx, arguments[0], exception); size_t localFeatureMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalFeature); char* localFeatureBuffer = new char[localFeatureMaxSize]; - JSStringGetUTF8CString(stringReflocalFeature, localFeatureBuffer, sizeof(localFeatureBuffer)); - std::string localFeature(localFeatureBuffer, localFeatureMaxSize); + JSStringGetUTF8CString(stringReflocalFeature, localFeatureBuffer, localFeatureMaxSize); + std::string localFeature(localFeatureBuffer); + JSStringRelease(stringReflocalFeature); free(localFeatureBuffer); JSStringRef stringReflocalVersion = JSValueToStringCopy(ctx, arguments[1], exception); size_t localVersionMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalVersion); char* localVersionBuffer = new char[localVersionMaxSize]; - JSStringGetUTF8CString(stringReflocalVersion, localVersionBuffer, sizeof(localVersionBuffer)); - std::string localVersion(localVersionBuffer, localVersionMaxSize); + JSStringGetUTF8CString(stringReflocalVersion, localVersionBuffer, localVersionMaxSize); + std::string localVersion(localVersionBuffer); + JSStringRelease(stringReflocalVersion); free(localVersionBuffer); @@ -66,22 +68,25 @@ JSValueRef JSCDOMImplementation::createDocumentTypeCallback(JSContextRef ctx, JS JSStringRef stringReflocalQualifiedName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localQualifiedNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalQualifiedName); char* localQualifiedNameBuffer = new char[localQualifiedNameMaxSize]; - JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, sizeof(localQualifiedNameBuffer)); - std::string localQualifiedName(localQualifiedNameBuffer, localQualifiedNameMaxSize); + JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, localQualifiedNameMaxSize); + std::string localQualifiedName(localQualifiedNameBuffer); + JSStringRelease(stringReflocalQualifiedName); free(localQualifiedNameBuffer); JSStringRef stringReflocalPublicId = JSValueToStringCopy(ctx, arguments[1], exception); size_t localPublicIdMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalPublicId); char* localPublicIdBuffer = new char[localPublicIdMaxSize]; - JSStringGetUTF8CString(stringReflocalPublicId, localPublicIdBuffer, sizeof(localPublicIdBuffer)); - std::string localPublicId(localPublicIdBuffer, localPublicIdMaxSize); + JSStringGetUTF8CString(stringReflocalPublicId, localPublicIdBuffer, localPublicIdMaxSize); + std::string localPublicId(localPublicIdBuffer); + JSStringRelease(stringReflocalPublicId); free(localPublicIdBuffer); JSStringRef stringReflocalSystemId = JSValueToStringCopy(ctx, arguments[2], exception); size_t localSystemIdMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalSystemId); char* localSystemIdBuffer = new char[localSystemIdMaxSize]; - JSStringGetUTF8CString(stringReflocalSystemId, localSystemIdBuffer, sizeof(localSystemIdBuffer)); - std::string localSystemId(localSystemIdBuffer, localSystemIdMaxSize); + JSStringGetUTF8CString(stringReflocalSystemId, localSystemIdBuffer, localSystemIdMaxSize); + std::string localSystemId(localSystemIdBuffer); + JSStringRelease(stringReflocalSystemId); free(localSystemIdBuffer); @@ -113,18 +118,20 @@ JSValueRef JSCDOMImplementation::createDocumentCallback(JSContextRef ctx, JSObje JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalQualifiedName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localQualifiedNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalQualifiedName); char* localQualifiedNameBuffer = new char[localQualifiedNameMaxSize]; - JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, sizeof(localQualifiedNameBuffer)); - std::string localQualifiedName(localQualifiedNameBuffer, localQualifiedNameMaxSize); + JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, localQualifiedNameMaxSize); + std::string localQualifiedName(localQualifiedNameBuffer); + JSStringRelease(stringReflocalQualifiedName); free(localQualifiedNameBuffer); - Arabica::DOM::DocumentType<std::string>* localDoctype = ((struct JSCDocumentType::JSCDocumentTypePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::DocumentType<std::string>* localDoctype = ((struct JSCDocumentType::JSCDocumentTypePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[2], exception)))->nativeObj; Arabica::DOM::Document<std::string>* retVal = new Arabica::DOM::Document<std::string>(privData->nativeObj->createDocument(localNamespaceURI, localQualifiedName, *localDoctype)); JSClassRef retClass = JSCDocument::getTmpl(); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.cpp index ed12bb0..4fae6c9 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.cpp @@ -109,8 +109,9 @@ JSValueRef JSCDocument::createElementCallback(JSContextRef ctx, JSObjectRef func JSStringRef stringReflocalTagName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localTagNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalTagName); char* localTagNameBuffer = new char[localTagNameMaxSize]; - JSStringGetUTF8CString(stringReflocalTagName, localTagNameBuffer, sizeof(localTagNameBuffer)); - std::string localTagName(localTagNameBuffer, localTagNameMaxSize); + JSStringGetUTF8CString(stringReflocalTagName, localTagNameBuffer, localTagNameMaxSize); + std::string localTagName(localTagNameBuffer); + JSStringRelease(stringReflocalTagName); free(localTagNameBuffer); @@ -160,8 +161,9 @@ JSValueRef JSCDocument::createTextNodeCallback(JSContextRef ctx, JSObjectRef fun JSStringRef stringReflocalData = JSValueToStringCopy(ctx, arguments[0], exception); size_t localDataMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalData); char* localDataBuffer = new char[localDataMaxSize]; - JSStringGetUTF8CString(stringReflocalData, localDataBuffer, sizeof(localDataBuffer)); - std::string localData(localDataBuffer, localDataMaxSize); + JSStringGetUTF8CString(stringReflocalData, localDataBuffer, localDataMaxSize); + std::string localData(localDataBuffer); + JSStringRelease(stringReflocalData); free(localDataBuffer); @@ -193,8 +195,9 @@ JSValueRef JSCDocument::createCommentCallback(JSContextRef ctx, JSObjectRef func JSStringRef stringReflocalData = JSValueToStringCopy(ctx, arguments[0], exception); size_t localDataMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalData); char* localDataBuffer = new char[localDataMaxSize]; - JSStringGetUTF8CString(stringReflocalData, localDataBuffer, sizeof(localDataBuffer)); - std::string localData(localDataBuffer, localDataMaxSize); + JSStringGetUTF8CString(stringReflocalData, localDataBuffer, localDataMaxSize); + std::string localData(localDataBuffer); + JSStringRelease(stringReflocalData); free(localDataBuffer); @@ -226,8 +229,9 @@ JSValueRef JSCDocument::createCDATASectionCallback(JSContextRef ctx, JSObjectRef JSStringRef stringReflocalData = JSValueToStringCopy(ctx, arguments[0], exception); size_t localDataMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalData); char* localDataBuffer = new char[localDataMaxSize]; - JSStringGetUTF8CString(stringReflocalData, localDataBuffer, sizeof(localDataBuffer)); - std::string localData(localDataBuffer, localDataMaxSize); + JSStringGetUTF8CString(stringReflocalData, localDataBuffer, localDataMaxSize); + std::string localData(localDataBuffer); + JSStringRelease(stringReflocalData); free(localDataBuffer); @@ -259,15 +263,17 @@ JSValueRef JSCDocument::createProcessingInstructionCallback(JSContextRef ctx, JS JSStringRef stringReflocalTarget = JSValueToStringCopy(ctx, arguments[0], exception); size_t localTargetMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalTarget); char* localTargetBuffer = new char[localTargetMaxSize]; - JSStringGetUTF8CString(stringReflocalTarget, localTargetBuffer, sizeof(localTargetBuffer)); - std::string localTarget(localTargetBuffer, localTargetMaxSize); + JSStringGetUTF8CString(stringReflocalTarget, localTargetBuffer, localTargetMaxSize); + std::string localTarget(localTargetBuffer); + JSStringRelease(stringReflocalTarget); free(localTargetBuffer); JSStringRef stringReflocalData = JSValueToStringCopy(ctx, arguments[1], exception); size_t localDataMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalData); char* localDataBuffer = new char[localDataMaxSize]; - JSStringGetUTF8CString(stringReflocalData, localDataBuffer, sizeof(localDataBuffer)); - std::string localData(localDataBuffer, localDataMaxSize); + JSStringGetUTF8CString(stringReflocalData, localDataBuffer, localDataMaxSize); + std::string localData(localDataBuffer); + JSStringRelease(stringReflocalData); free(localDataBuffer); @@ -299,8 +305,9 @@ JSValueRef JSCDocument::createAttributeCallback(JSContextRef ctx, JSObjectRef fu JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -332,8 +339,9 @@ JSValueRef JSCDocument::createEntityReferenceCallback(JSContextRef ctx, JSObject JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -365,8 +373,9 @@ JSValueRef JSCDocument::getElementsByTagNameCallback(JSContextRef ctx, JSObjectR JSStringRef stringReflocalTagname = JSValueToStringCopy(ctx, arguments[0], exception); size_t localTagnameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalTagname); char* localTagnameBuffer = new char[localTagnameMaxSize]; - JSStringGetUTF8CString(stringReflocalTagname, localTagnameBuffer, sizeof(localTagnameBuffer)); - std::string localTagname(localTagnameBuffer, localTagnameMaxSize); + JSStringGetUTF8CString(stringReflocalTagname, localTagnameBuffer, localTagnameMaxSize); + std::string localTagname(localTagnameBuffer); + JSStringRelease(stringReflocalTagname); free(localTagnameBuffer); @@ -395,7 +404,7 @@ JSValueRef JSCDocument::importNodeCallback(JSContextRef ctx, JSObjectRef functio struct JSCDocumentPrivate* privData = (struct JSCDocumentPrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localImportedNode = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localImportedNode = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; bool localDeep = JSValueToBoolean(ctx, arguments[1]); Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->importNode(*localImportedNode, localDeep)); @@ -426,15 +435,17 @@ JSValueRef JSCDocument::createElementNSCallback(JSContextRef ctx, JSObjectRef fu JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalQualifiedName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localQualifiedNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalQualifiedName); char* localQualifiedNameBuffer = new char[localQualifiedNameMaxSize]; - JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, sizeof(localQualifiedNameBuffer)); - std::string localQualifiedName(localQualifiedNameBuffer, localQualifiedNameMaxSize); + JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, localQualifiedNameMaxSize); + std::string localQualifiedName(localQualifiedNameBuffer); + JSStringRelease(stringReflocalQualifiedName); free(localQualifiedNameBuffer); @@ -466,15 +477,17 @@ JSValueRef JSCDocument::createAttributeNSCallback(JSContextRef ctx, JSObjectRef JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalQualifiedName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localQualifiedNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalQualifiedName); char* localQualifiedNameBuffer = new char[localQualifiedNameMaxSize]; - JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, sizeof(localQualifiedNameBuffer)); - std::string localQualifiedName(localQualifiedNameBuffer, localQualifiedNameMaxSize); + JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, localQualifiedNameMaxSize); + std::string localQualifiedName(localQualifiedNameBuffer); + JSStringRelease(stringReflocalQualifiedName); free(localQualifiedNameBuffer); @@ -506,15 +519,17 @@ JSValueRef JSCDocument::getElementsByTagNameNSCallback(JSContextRef ctx, JSObjec JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); @@ -546,8 +561,9 @@ JSValueRef JSCDocument::getElementByIdCallback(JSContextRef ctx, JSObjectRef fun JSStringRef stringReflocalElementId = JSValueToStringCopy(ctx, arguments[0], exception); size_t localElementIdMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalElementId); char* localElementIdBuffer = new char[localElementIdMaxSize]; - JSStringGetUTF8CString(stringReflocalElementId, localElementIdBuffer, sizeof(localElementIdBuffer)); - std::string localElementId(localElementIdBuffer, localElementIdMaxSize); + JSStringGetUTF8CString(stringReflocalElementId, localElementIdBuffer, localElementIdMaxSize); + std::string localElementId(localElementIdBuffer); + JSStringRelease(stringReflocalElementId); free(localElementIdBuffer); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.h index 3446cc2..6657f3b 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocument.h @@ -70,6 +70,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentCustom.cpp index 23cc0f9..c6fdce1 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentCustom.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentCustom.cpp @@ -1,11 +1,76 @@ #include "JSCDocument.h" #include "JSCXPathResult.h" +#include "JSCNode.h" +#include <XPath/XPath.hpp> namespace Arabica { namespace DOM { -JSValueRef JSCDocument::evaluateCustomCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj, size_t argumentCount, const JSValueRef* arguments, JSValueRef* exception) { +JSValueRef JSCDocument::evaluateCustomCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef* arguments, JSValueRef* exception) { + struct JSCDocumentPrivate* privData = (struct JSCDocumentPrivate*)JSObjectGetPrivate(object); + + if (!privData->dom || !privData->dom->xpath) return JSValueMakeUndefined(ctx); + if (argumentCount < 1) { + std::string errorMsg = "Wrong number of arguments in evaluate"; + JSStringRef string = JSStringCreateWithUTF8CString(errorMsg.c_str()); + JSValueRef exceptionString = JSValueMakeString(ctx, string); + JSStringRelease(string); + *exception = JSValueToObject(ctx, exceptionString, NULL); + return JSValueMakeUndefined(ctx); + } + + // make sure first argument is a string + if (!JSValueIsString(ctx, arguments[0])) { + std::string errorMsg = "Expected xpath expression as first argument"; + JSStringRef string = JSStringCreateWithUTF8CString(errorMsg.c_str()); + JSValueRef exceptionString = JSValueMakeString(ctx, string); + JSStringRelease(string); + *exception = JSValueToObject(ctx, exceptionString, NULL); + return JSValueMakeUndefined(ctx); + } + + JSStringRef stringReflocalXPath = JSValueToStringCopy(ctx, arguments[0], NULL); + size_t localXPathMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalXPath); + char* localXPathBuffer = new char[localXPathMaxSize]; + JSStringGetUTF8CString(stringReflocalXPath, localXPathBuffer, localXPathMaxSize); + std::string localXPath(localXPathBuffer); + JSStringRelease(stringReflocalXPath); + free(localXPathBuffer); + + JSClassRef arbaicaRetClass = JSCXPathResult::getTmpl(); + + XPath::XPathValue<std::string>* retVal; + + try { + if (argumentCount > 1) { + // make sure second argument is a node + if (!JSValueIsObject(ctx, arguments[1])) { + std::string errorMsg = "Second argument is not of type node"; + JSStringRef string = JSStringCreateWithUTF8CString(errorMsg.c_str()); + JSValueRef exceptionString = JSValueMakeString(ctx, string); + JSStringRelease(string); + *exception = JSValueToObject(ctx, exceptionString, NULL); + return JSValueMakeUndefined(ctx); + } + + Arabica::DOM::Node<std::string>* localContextNode = (Arabica::DOM::Node<std::string>*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[1], NULL)); + retVal = new XPath::XPathValue<std::string>(privData->dom->xpath->evaluate(localXPath, *localContextNode)); + } else { + retVal = new XPath::XPathValue<std::string>(privData->dom->xpath->evaluate(localXPath, *privData->nativeObj)); + } + } catch (std::runtime_error e) { + std::cout << e.what() << std::endl; + return JSValueMakeUndefined(ctx); + } + + struct JSCXPathResult::JSCXPathResultPrivate* retPrivData = new JSCXPathResult::JSCXPathResultPrivate(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; + + JSObjectRef arbaicaRetObj = JSObjectMake(ctx, arbaicaRetClass, retPrivData); + return arbaicaRetObj; + #if 0 if (args.Length() < 1) throw V8Exception("Wrong number of arguments in evaluate"); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentFragment.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentFragment.h index 1d8a9c9..3a9d8d6 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentFragment.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentFragment.h @@ -52,6 +52,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentType.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentType.h index 6f839a2..3dc46f4 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentType.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDocumentType.h @@ -58,6 +58,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.cpp index ce77091..e0b403f 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.cpp @@ -57,8 +57,9 @@ JSValueRef JSCElement::getAttributeCallback(JSContextRef ctx, JSObjectRef functi JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -85,15 +86,17 @@ JSValueRef JSCElement::setAttributeCallback(JSContextRef ctx, JSObjectRef functi JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); JSStringRef stringReflocalValue = JSValueToStringCopy(ctx, arguments[1], exception); size_t localValueMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalValue); char* localValueBuffer = new char[localValueMaxSize]; - JSStringGetUTF8CString(stringReflocalValue, localValueBuffer, sizeof(localValueBuffer)); - std::string localValue(localValueBuffer, localValueMaxSize); + JSStringGetUTF8CString(stringReflocalValue, localValueBuffer, localValueMaxSize); + std::string localValue(localValueBuffer); + JSStringRelease(stringReflocalValue); free(localValueBuffer); @@ -118,8 +121,9 @@ JSValueRef JSCElement::removeAttributeCallback(JSContextRef ctx, JSObjectRef fun JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -144,8 +148,9 @@ JSValueRef JSCElement::getAttributeNodeCallback(JSContextRef ctx, JSObjectRef fu JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -174,7 +179,7 @@ JSValueRef JSCElement::setAttributeNodeCallback(JSContextRef ctx, JSObjectRef fu struct JSCElementPrivate* privData = (struct JSCElementPrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Attr<std::string>* localNewAttr = ((struct JSCAttr::JSCAttrPrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Attr<std::string>* localNewAttr = ((struct JSCAttr::JSCAttrPrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Attr<std::string>* retVal = new Arabica::DOM::Attr<std::string>(privData->nativeObj->setAttributeNode(*localNewAttr)); JSClassRef retClass = JSCAttr::getTmpl(); @@ -201,7 +206,7 @@ JSValueRef JSCElement::removeAttributeNodeCallback(JSContextRef ctx, JSObjectRef struct JSCElementPrivate* privData = (struct JSCElementPrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Attr<std::string>* localOldAttr = ((struct JSCAttr::JSCAttrPrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Attr<std::string>* localOldAttr = ((struct JSCAttr::JSCAttrPrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Attr<std::string>* retVal = new Arabica::DOM::Attr<std::string>(privData->nativeObj->removeAttributeNode(*localOldAttr)); JSClassRef retClass = JSCAttr::getTmpl(); @@ -231,8 +236,9 @@ JSValueRef JSCElement::getElementsByTagNameCallback(JSContextRef ctx, JSObjectRe JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -264,15 +270,17 @@ JSValueRef JSCElement::getAttributeNSCallback(JSContextRef ctx, JSObjectRef func JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); @@ -299,22 +307,25 @@ JSValueRef JSCElement::setAttributeNSCallback(JSContextRef ctx, JSObjectRef func JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalQualifiedName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localQualifiedNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalQualifiedName); char* localQualifiedNameBuffer = new char[localQualifiedNameMaxSize]; - JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, sizeof(localQualifiedNameBuffer)); - std::string localQualifiedName(localQualifiedNameBuffer, localQualifiedNameMaxSize); + JSStringGetUTF8CString(stringReflocalQualifiedName, localQualifiedNameBuffer, localQualifiedNameMaxSize); + std::string localQualifiedName(localQualifiedNameBuffer); + JSStringRelease(stringReflocalQualifiedName); free(localQualifiedNameBuffer); JSStringRef stringReflocalValue = JSValueToStringCopy(ctx, arguments[2], exception); size_t localValueMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalValue); char* localValueBuffer = new char[localValueMaxSize]; - JSStringGetUTF8CString(stringReflocalValue, localValueBuffer, sizeof(localValueBuffer)); - std::string localValue(localValueBuffer, localValueMaxSize); + JSStringGetUTF8CString(stringReflocalValue, localValueBuffer, localValueMaxSize); + std::string localValue(localValueBuffer); + JSStringRelease(stringReflocalValue); free(localValueBuffer); @@ -339,15 +350,17 @@ JSValueRef JSCElement::removeAttributeNSCallback(JSContextRef ctx, JSObjectRef f JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); @@ -372,15 +385,17 @@ JSValueRef JSCElement::getAttributeNodeNSCallback(JSContextRef ctx, JSObjectRef JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); @@ -409,7 +424,7 @@ JSValueRef JSCElement::setAttributeNodeNSCallback(JSContextRef ctx, JSObjectRef struct JSCElementPrivate* privData = (struct JSCElementPrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Attr<std::string>* localNewAttr = ((struct JSCAttr::JSCAttrPrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Attr<std::string>* localNewAttr = ((struct JSCAttr::JSCAttrPrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Attr<std::string>* retVal = new Arabica::DOM::Attr<std::string>(privData->nativeObj->setAttributeNodeNS(*localNewAttr)); JSClassRef retClass = JSCAttr::getTmpl(); @@ -439,15 +454,17 @@ JSValueRef JSCElement::getElementsByTagNameNSCallback(JSContextRef ctx, JSObject JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); @@ -479,8 +496,9 @@ JSValueRef JSCElement::hasAttributeCallback(JSContextRef ctx, JSObjectRef functi JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -505,15 +523,17 @@ JSValueRef JSCElement::hasAttributeNSCallback(JSContextRef ctx, JSObjectRef func JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.h index 42dc2ac..9520a8b 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCElement.h @@ -68,6 +68,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntity.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntity.h index e16cc1f..69f54a3 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntity.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntity.h @@ -55,6 +55,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntityReference.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntityReference.h index d8e4803..428274f 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntityReference.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCEntityReference.h @@ -52,6 +52,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNamedNodeMap.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNamedNodeMap.cpp index aeb0913..c72b27b 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNamedNodeMap.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNamedNodeMap.cpp @@ -44,8 +44,9 @@ JSValueRef JSCNamedNodeMap::getNamedItemCallback(JSContextRef ctx, JSObjectRef f JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -74,7 +75,7 @@ JSValueRef JSCNamedNodeMap::setNamedItemCallback(JSContextRef ctx, JSObjectRef f struct JSCNamedNodeMapPrivate* privData = (struct JSCNamedNodeMapPrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localArg = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localArg = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->setNamedItem(*localArg)); JSClassRef retClass = JSCNode::getTmpl(); @@ -104,8 +105,9 @@ JSValueRef JSCNamedNodeMap::removeNamedItemCallback(JSContextRef ctx, JSObjectRe JSStringRef stringReflocalName = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalName); char* localNameBuffer = new char[localNameMaxSize]; - JSStringGetUTF8CString(stringReflocalName, localNameBuffer, sizeof(localNameBuffer)); - std::string localName(localNameBuffer, localNameMaxSize); + JSStringGetUTF8CString(stringReflocalName, localNameBuffer, localNameMaxSize); + std::string localName(localNameBuffer); + JSStringRelease(stringReflocalName); free(localNameBuffer); @@ -164,15 +166,17 @@ JSValueRef JSCNamedNodeMap::getNamedItemNSCallback(JSContextRef ctx, JSObjectRef JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); @@ -201,7 +205,7 @@ JSValueRef JSCNamedNodeMap::setNamedItemNSCallback(JSContextRef ctx, JSObjectRef struct JSCNamedNodeMapPrivate* privData = (struct JSCNamedNodeMapPrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localArg = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localArg = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->setNamedItemNS(*localArg)); JSClassRef retClass = JSCNode::getTmpl(); @@ -231,15 +235,17 @@ JSValueRef JSCNamedNodeMap::removeNamedItemNSCallback(JSContextRef ctx, JSObject JSStringRef stringReflocalNamespaceURI = JSValueToStringCopy(ctx, arguments[0], exception); size_t localNamespaceURIMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNamespaceURI); char* localNamespaceURIBuffer = new char[localNamespaceURIMaxSize]; - JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, sizeof(localNamespaceURIBuffer)); - std::string localNamespaceURI(localNamespaceURIBuffer, localNamespaceURIMaxSize); + JSStringGetUTF8CString(stringReflocalNamespaceURI, localNamespaceURIBuffer, localNamespaceURIMaxSize); + std::string localNamespaceURI(localNamespaceURIBuffer); + JSStringRelease(stringReflocalNamespaceURI); free(localNamespaceURIBuffer); JSStringRef stringReflocalLocalName = JSValueToStringCopy(ctx, arguments[1], exception); size_t localLocalNameMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalLocalName); char* localLocalNameBuffer = new char[localLocalNameMaxSize]; - JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, sizeof(localLocalNameBuffer)); - std::string localLocalName(localLocalNameBuffer, localLocalNameMaxSize); + JSStringGetUTF8CString(stringReflocalLocalName, localLocalNameBuffer, localLocalNameMaxSize); + std::string localLocalName(localLocalNameBuffer); + JSStringRelease(stringReflocalLocalName); free(localLocalNameBuffer); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNode.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNode.cpp index 0e84442..22d048c 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNode.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNode.cpp @@ -77,8 +77,9 @@ bool JSCNode::nodeValueAttrSetter(JSContextRef ctx, JSObjectRef thisObj, JSStrin JSStringRef stringReflocalNodeValue = JSValueToStringCopy(ctx, value, exception); size_t localNodeValueMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalNodeValue); char* localNodeValueBuffer = new char[localNodeValueMaxSize]; - JSStringGetUTF8CString(stringReflocalNodeValue, localNodeValueBuffer, sizeof(localNodeValueBuffer)); - std::string localNodeValue(localNodeValueBuffer, localNodeValueMaxSize); + JSStringGetUTF8CString(stringReflocalNodeValue, localNodeValueBuffer, localNodeValueMaxSize); + std::string localNodeValue(localNodeValueBuffer); + JSStringRelease(stringReflocalNodeValue); free(localNodeValueBuffer); privData->nativeObj->setNodeValue(localNodeValue); @@ -237,8 +238,9 @@ bool JSCNode::prefixAttrSetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRe JSStringRef stringReflocalPrefix = JSValueToStringCopy(ctx, value, exception); size_t localPrefixMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalPrefix); char* localPrefixBuffer = new char[localPrefixMaxSize]; - JSStringGetUTF8CString(stringReflocalPrefix, localPrefixBuffer, sizeof(localPrefixBuffer)); - std::string localPrefix(localPrefixBuffer, localPrefixMaxSize); + JSStringGetUTF8CString(stringReflocalPrefix, localPrefixBuffer, localPrefixMaxSize); + std::string localPrefix(localPrefixBuffer); + JSStringRelease(stringReflocalPrefix); free(localPrefixBuffer); privData->nativeObj->setPrefix(localPrefix); @@ -314,8 +316,8 @@ JSValueRef JSCNode::insertBeforeCallback(JSContextRef ctx, JSObjectRef function, struct JSCNodePrivate* privData = (struct JSCNodePrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localNewChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; - Arabica::DOM::Node<std::string>* localRefChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localNewChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; + Arabica::DOM::Node<std::string>* localRefChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[1], exception)))->nativeObj; Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->insertBefore(*localNewChild, *localRefChild)); JSClassRef retClass = JSCNode::getTmpl(); @@ -342,8 +344,8 @@ JSValueRef JSCNode::replaceChildCallback(JSContextRef ctx, JSObjectRef function, struct JSCNodePrivate* privData = (struct JSCNodePrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localNewChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; - Arabica::DOM::Node<std::string>* localOldChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localNewChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; + Arabica::DOM::Node<std::string>* localOldChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[1], exception)))->nativeObj; Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->replaceChild(*localNewChild, *localOldChild)); JSClassRef retClass = JSCNode::getTmpl(); @@ -370,7 +372,7 @@ JSValueRef JSCNode::removeChildCallback(JSContextRef ctx, JSObjectRef function, struct JSCNodePrivate* privData = (struct JSCNodePrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localOldChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localOldChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->removeChild(*localOldChild)); JSClassRef retClass = JSCNode::getTmpl(); @@ -397,7 +399,7 @@ JSValueRef JSCNode::appendChildCallback(JSContextRef ctx, JSObjectRef function, struct JSCNodePrivate* privData = (struct JSCNodePrivate*)JSObjectGetPrivate(thisObj); - Arabica::DOM::Node<std::string>* localNewChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(thisObj))->nativeObj; + Arabica::DOM::Node<std::string>* localNewChild = ((struct JSCNode::JSCNodePrivate*)JSObjectGetPrivate(JSValueToObject(ctx, arguments[0], exception)))->nativeObj; Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->appendChild(*localNewChild)); JSClassRef retClass = JSCNode::getTmpl(); @@ -476,15 +478,17 @@ JSValueRef JSCNode::isSupportedCallback(JSContextRef ctx, JSObjectRef function, JSStringRef stringReflocalFeature = JSValueToStringCopy(ctx, arguments[0], exception); size_t localFeatureMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalFeature); char* localFeatureBuffer = new char[localFeatureMaxSize]; - JSStringGetUTF8CString(stringReflocalFeature, localFeatureBuffer, sizeof(localFeatureBuffer)); - std::string localFeature(localFeatureBuffer, localFeatureMaxSize); + JSStringGetUTF8CString(stringReflocalFeature, localFeatureBuffer, localFeatureMaxSize); + std::string localFeature(localFeatureBuffer); + JSStringRelease(stringReflocalFeature); free(localFeatureBuffer); JSStringRef stringReflocalVersion = JSValueToStringCopy(ctx, arguments[1], exception); size_t localVersionMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalVersion); char* localVersionBuffer = new char[localVersionMaxSize]; - JSStringGetUTF8CString(stringReflocalVersion, localVersionBuffer, sizeof(localVersionBuffer)); - std::string localVersion(localVersionBuffer, localVersionMaxSize); + JSStringGetUTF8CString(stringReflocalVersion, localVersionBuffer, localVersionMaxSize); + std::string localVersion(localVersionBuffer); + JSStringRelease(stringReflocalVersion); free(localVersionBuffer); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeList.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeList.h index 4a1ba11..fca81b8 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeList.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeList.h @@ -41,6 +41,8 @@ public: static JSValueRef itemCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj, size_t argumentCount, const JSValueRef* arguments, JSValueRef* exception); static JSValueRef lengthAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); + static bool hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + static JSValueRef getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); static JSStaticValue staticValues[]; @@ -53,6 +55,8 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.hasProperty = hasPropertyCustomCallback; + classDef.getProperty = getPropertyCustomCallback; Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeListCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeListCustom.cpp index 788c8ec..adb366e 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeListCustom.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeListCustom.cpp @@ -5,6 +5,77 @@ namespace Arabica { namespace DOM { +bool JSCNodeList::hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { + size_t propMaxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char* propBuffer = new char[propMaxSize]; + JSStringGetUTF8CString(propertyName, propBuffer, propMaxSize); + std::string propName(propBuffer); + free(propBuffer); + + std::string base = "0123456789"; + if (propName.find_first_not_of(base) != std::string::npos) { + return false; + } + + int index = boost::lexical_cast<int>(propName); + struct JSCNodeListPrivate* privData = (struct JSCNodeListPrivate*)JSObjectGetPrivate(object); + + if (privData->nativeObj->getLength() < index) { + return false; + } + + return true; +} + +JSValueRef JSCNodeList::getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { + size_t propMaxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char* propBuffer = new char[propMaxSize]; + JSStringGetUTF8CString(propertyName, propBuffer, propMaxSize); + std::string propName(propBuffer); + free(propBuffer); + + std::string base = "0123456789"; + if (propName.find_first_not_of(base) != std::string::npos) { + return JSValueMakeUndefined(ctx); + } + + int index = boost::lexical_cast<int>(propName); + struct JSCNodeListPrivate* privData = (struct JSCNodeListPrivate*)JSObjectGetPrivate(object); + if (privData->nativeObj->getLength() < index) { + return JSValueMakeUndefined(ctx); + } + + switch(privData->nativeObj->item(index).getNodeType()) { + case Node_base::ELEMENT_NODE: { + Arabica::DOM::Element<std::string>* retVal = new Arabica::DOM::Element<std::string>(privData->nativeObj->item(index)); + JSClassRef retClass = JSCElement::getTmpl(); + + struct JSCElement::JSCElementPrivate* retPrivData = new JSCElement::JSCElementPrivate(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; + + JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); + + return retObj; + break; + } + default: { + Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>(privData->nativeObj->item(index)); + JSClassRef retClass = JSCNode::getTmpl(); + + struct JSCNode::JSCNodePrivate* retPrivData = new JSCNode::JSCNodePrivate(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; + + JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); + + return retObj; + } + } + + return JSValueMakeUndefined(ctx); +} + #if 0 v8::Handle<v8::Value> V8NodeList::indexedPropertyCustomGetter(uint32_t index, const v8::AccessorInfo &info) { v8::Local<v8::Object> self = info.Holder(); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSet.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSet.h index 42b4f29..b38d04e 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSet.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSet.h @@ -42,6 +42,8 @@ public: static JSValueRef sizeAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); static JSValueRef emptyAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception); + static bool hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + static JSValueRef getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); static JSStaticValue staticValues[]; @@ -54,6 +56,8 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.hasProperty = hasPropertyCustomCallback; + classDef.getProperty = getPropertyCustomCallback; Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSetCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSetCustom.cpp index 1591310..98f563e 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSetCustom.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNodeSetCustom.cpp @@ -5,50 +5,77 @@ namespace Arabica { namespace DOM { -#if 0 -v8::Handle<v8::Value> V8NodeSet::indexedPropertyCustomGetter(uint32_t index, const v8::AccessorInfo &info) { - v8::Local<v8::Object> self = info.Holder(); - V8NodeSetPrivate* privData = V8DOM::toClassPtr<V8NodeSetPrivate >(self->GetInternalField(0)); - if (privData->nativeObj->size() >= index) { - switch((*privData->nativeObj)[index].getNodeType()) { - case Node_base::ELEMENT_NODE: { - Arabica::DOM::Element<std::string>* retVal = new Arabica::DOM::Element<std::string>((*privData->nativeObj)[index]); +bool JSCNodeSet::hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { + size_t propMaxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char* propBuffer = new char[propMaxSize]; + JSStringGetUTF8CString(propertyName, propBuffer, propMaxSize); + std::string propName(propBuffer); + free(propBuffer); - v8::Handle<v8::Function> retCtor = V8Element::getTmpl()->GetFunction(); - v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + std::string base = "0123456789"; + if (propName.find_first_not_of(base) != std::string::npos) { + return false; + } + + int index = boost::lexical_cast<int>(propName); + struct JSCNodeSetPrivate* privData = (struct JSCNodeSetPrivate*)JSObjectGetPrivate(object); + + if (privData->nativeObj->size() < index) { + return false; + } + + return true; +} - struct V8Element::V8ElementPrivate* retPrivData = new V8Element::V8ElementPrivate(); - retPrivData->dom = privData->dom; - retPrivData->nativeObj = retVal; +JSValueRef JSCNodeSet::getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { + size_t propMaxSize = JSStringGetMaximumUTF8CStringSize(propertyName); + char* propBuffer = new char[propMaxSize]; + JSStringGetUTF8CString(propertyName, propBuffer, propMaxSize); + std::string propName(propBuffer); + free(propBuffer); - retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + std::string base = "0123456789"; + if (propName.find_first_not_of(base) != std::string::npos) { + return JSValueMakeUndefined(ctx); + } - retObj.MakeWeak(0, V8Element::jsDestructor); - return retObj; - } - default: { - Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>((*privData->nativeObj)[index]); + int index = boost::lexical_cast<int>(propName); + struct JSCNodeSetPrivate* privData = (struct JSCNodeSetPrivate*)JSObjectGetPrivate(object); + if (privData->nativeObj->size() < index) { + return JSValueMakeUndefined(ctx); + } - v8::Handle<v8::Function> retCtor = V8Node::getTmpl()->GetFunction(); - v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + switch((*privData->nativeObj)[index].getNodeType()) { + case Node_base::ELEMENT_NODE: { + Arabica::DOM::Element<std::string>* retVal = new Arabica::DOM::Element<std::string>((*privData->nativeObj)[index]); + JSClassRef retClass = JSCElement::getTmpl(); - struct V8Node::V8NodePrivate* retPrivData = new V8Node::V8NodePrivate(); - retPrivData->dom = privData->dom; - retPrivData->nativeObj = retVal; + struct JSCElement::JSCElementPrivate* retPrivData = new JSCElement::JSCElementPrivate(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; - retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); - retObj.MakeWeak(0, V8Node::jsDestructor); - return retObj; - } - } + return retObj; + break; } + default: { + Arabica::DOM::Node<std::string>* retVal = new Arabica::DOM::Node<std::string>((*privData->nativeObj)[index]); + JSClassRef retClass = JSCNode::getTmpl(); + + struct JSCNode::JSCNodePrivate* retPrivData = new JSCNode::JSCNodePrivate(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; - return v8::Undefined(); + JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); + + return retObj; + } + } + return JSValueMakeUndefined(ctx); } -#endif } }
\ No newline at end of file diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNotation.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNotation.h index ed793ed..bb84c50 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNotation.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCNotation.h @@ -54,6 +54,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.cpp index d60c39b..9ea0220 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.cpp @@ -43,8 +43,9 @@ bool JSCProcessingInstruction::dataAttrSetter(JSContextRef ctx, JSObjectRef this JSStringRef stringReflocalData = JSValueToStringCopy(ctx, value, exception); size_t localDataMaxSize = JSStringGetMaximumUTF8CStringSize(stringReflocalData); char* localDataBuffer = new char[localDataMaxSize]; - JSStringGetUTF8CString(stringReflocalData, localDataBuffer, sizeof(localDataBuffer)); - std::string localData(localDataBuffer, localDataMaxSize); + JSStringGetUTF8CString(stringReflocalData, localDataBuffer, localDataMaxSize); + std::string localData(localDataBuffer); + JSStringRelease(stringReflocalData); free(localDataBuffer); privData->nativeObj->setData(localData); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.h index fdf7bc5..fc8c44b 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCProcessingInstruction.h @@ -55,6 +55,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCNode::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCText.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCText.h index a6fdbbd..786df27 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCText.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCText.h @@ -53,6 +53,7 @@ public: classDef.staticValues = staticValues; classDef.staticFunctions = staticFunctions; classDef.finalize = jsDestructor; + classDef.parentClass = JSCCharacterData::getTmpl(); Tmpl = JSClassCreate(&classDef); JSClassRetain(Tmpl); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DocumentCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DocumentCustom.cpp index be9b05c..1e0b700 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DocumentCustom.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8DocumentCustom.cpp @@ -17,11 +17,16 @@ v8::Handle<v8::Value> V8Document::evaluateCustomCallback(const v8::Arguments& ar v8::String::AsciiValue localExpression(args[0]); XPath::XPathValue<std::string>* retVal; - if (args.Length() > 1) { - Arabica::DOM::Node<std::string>* localContextNode = V8DOM::toClassPtr<Arabica::DOM::Node<std::string> >(args[1]->ToObject()->GetInternalField(0)); - retVal = new XPath::XPathValue<std::string>(privData->dom->xpath->evaluate(*localExpression, *localContextNode)); - } else { - retVal = new XPath::XPathValue<std::string>(privData->dom->xpath->evaluate(*localExpression, *privData->nativeObj)); + try { + if (args.Length() > 1) { + Arabica::DOM::Node<std::string>* localContextNode = V8DOM::toClassPtr<Arabica::DOM::Node<std::string> >(args[1]->ToObject()->GetInternalField(0)); + retVal = new XPath::XPathValue<std::string>(privData->dom->xpath->evaluate(*localExpression, *localContextNode)); + } else { + retVal = new XPath::XPathValue<std::string>(privData->dom->xpath->evaluate(*localExpression, *privData->nativeObj)); + } + } catch (std::runtime_error e) { + std::cout << e.what() << std::endl; + return v8::Undefined(); } v8::Handle<v8::Function> retCtor = V8XPathResult::getTmpl()->GetFunction(); diff --git a/src/uscxml/plugins/invoker/audio/AudioToolbox.h b/src/uscxml/plugins/invoker/audio/AudioToolbox.h index 3e04d8f..6ad7390 100644 --- a/src/uscxml/plugins/invoker/audio/AudioToolbox.h +++ b/src/uscxml/plugins/invoker/audio/AudioToolbox.h @@ -5,7 +5,7 @@ #include <AudioToolbox/AudioToolbox.h> namespace uscxml { - + class AudioToolbox : public PCMConverter { public: AudioToolbox(const std::string filename); @@ -20,7 +20,7 @@ protected: ExtAudioFileRef _afId; AudioStreamBasicDescription _outputFormat; AudioStreamBasicDescription _inputFormat; - + ALenum formatToALEnum(AudioStreamBasicDescription); bool alEnumToFormat(AudioStreamBasicDescription&, ALenum); }; diff --git a/src/uscxml/plugins/invoker/audio/LibSoundFile.cpp b/src/uscxml/plugins/invoker/audio/LibSoundFile.cpp index 1340140..26d3328 100644 --- a/src/uscxml/plugins/invoker/audio/LibSoundFile.cpp +++ b/src/uscxml/plugins/invoker/audio/LibSoundFile.cpp @@ -7,39 +7,39 @@ LibSoundFile::LibSoundFile(const std::string filename) : PCMConverter() { _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_16, 1, 44100); _format.sampleRate = _handle.samplerate(); _format.alFormat = AL_FORMAT_MONO16; - + } LibSoundFile::~LibSoundFile() { - + } void LibSoundFile::seek(unsigned int pos) { - _handle.seek(pos, 0); + _handle.seek(pos, 0); } int LibSoundFile::read(char* buffer, unsigned int size) { - return _handle.readRaw(buffer, size); + return _handle.readRaw(buffer, size); } - + void LibSoundFile::setOutFormat(const PCMFormat& format) { _format = format; switch (_format.alFormat) { - case AL_FORMAT_MONO8: - _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_S8, 1, _format.sampleRate); - break; - case AL_FORMAT_MONO16: - _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_16, 1, _format.sampleRate); - break; - case AL_FORMAT_STEREO8: - _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_S8, 2, _format.sampleRate); - break; - case AL_FORMAT_STEREO16: - _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_16, 2, _format.sampleRate); - break; - - default: - break; + case AL_FORMAT_MONO8: + _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_S8, 1, _format.sampleRate); + break; + case AL_FORMAT_MONO16: + _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_16, 1, _format.sampleRate); + break; + case AL_FORMAT_STEREO8: + _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_S8, 2, _format.sampleRate); + break; + case AL_FORMAT_STEREO16: + _handle = SndfileHandle(_filename, SFM_READ, SF_FORMAT_PCM_16, 2, _format.sampleRate); + break; + + default: + break; } } diff --git a/src/uscxml/plugins/invoker/audio/LibSoundFile.h b/src/uscxml/plugins/invoker/audio/LibSoundFile.h index 5491609..0d740f6 100644 --- a/src/uscxml/plugins/invoker/audio/LibSoundFile.h +++ b/src/uscxml/plugins/invoker/audio/LibSoundFile.h @@ -5,14 +5,14 @@ #include <sndfile.hh> namespace uscxml { - + class LibSoundFile : public PCMConverter { public: LibSoundFile(const std::string filename); virtual ~LibSoundFile(); void seek(unsigned int pos); int read(char* buffer, unsigned int size); - + virtual void setOutFormat(const PCMFormat& format); virtual PCMFormat getInFormat(); diff --git a/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp b/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp index cf9d15a..6b52c8c 100644 --- a/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp +++ b/src/uscxml/plugins/invoker/audio/OpenALInvoker.cpp @@ -1,6 +1,6 @@ -// see http://stackoverflow.com/questions/6563810/m-pi-works-with-math-h-but-not-with-cmath-in-visual-studio
-#define _USE_MATH_DEFINES
-#include <cmath>
+// see http://stackoverflow.com/questions/6563810/m-pi-works-with-math-h-but-not-with-cmath-in-visual-studio +#define _USE_MATH_DEFINES +#include <cmath> #include "OpenALInvoker.h" #include <uscxml/config.h> @@ -20,13 +20,12 @@ bool connect(pluma::Host& host) { return true; } #endif -
-// see http://stackoverflow.com/questions/1904635/warning-c4003-and-errors-c2589-and-c2059-on-x-stdnumeric-limitsintmax
+ +// see http://stackoverflow.com/questions/1904635/warning-c4003-and-errors-c2589-and-c2059-on-x-stdnumeric-limitsintmax #undef max OpenALInvoker::OpenALInvoker() { _isStarted = false; - _isRunning = false; _alContext = NULL; _alDevice = NULL; _thread = NULL; @@ -34,13 +33,14 @@ OpenALInvoker::OpenALInvoker() { OpenALInvoker::~OpenALInvoker() { if (_thread) { - _isRunning = false; + _isStarted = false; + _sourcesAvailable.notify_all(); _thread->join(); delete(_thread); } if (_alContext) { - alcCloseDevice(alcGetContextsDevice(_alContext)); - alcDestroyContext(_alContext); +// alcCloseDevice(alcGetContextsDevice(_alContext)); +// alcDestroyContext(_alContext); } }; @@ -57,15 +57,15 @@ Data OpenALInvoker::getDataModelVariables() { void OpenALInvoker::send(const SendRequest& req) { tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); - + if (!_isStarted) start(); - + if (boost::iequals(req.name, "play")) { if (req.params.find("src") == req.params.end()) { LOG(ERROR) << "Sent event play with no src URL"; } - + URL srcURL = req.params.find("src")->second; if (!srcURL.toAbsolute(_interpreter->getBaseURI())) { LOG(ERROR) << "src URL " << req.params.find("src")->second << " is relative with no base URI set for interpreter"; @@ -87,12 +87,12 @@ void OpenALInvoker::send(const SendRequest& req) { _sources.erase(req.sendid); return; } - + // force mono format to ensure actual spatial audio PCMFormat format = _sources[req.sendid]->transform->getInFormat(); format.alFormat = AL_FORMAT_MONO16; _sources[req.sendid]->transform->setOutFormat(format); - + try { _sources[req.sendid]->player = new OpenALPlayer(_alContext, NULL, format.alFormat, format.sampleRate); } catch (std::exception ex) { @@ -108,10 +108,9 @@ void OpenALInvoker::send(const SendRequest& req) { returnErrorExecution(ex.what()); } - _sourcesAvailable.notify_all(); } - + if (boost::iequals(req.name, "move.source")) { std::string sourceId; if (req.params.find("source") == req.params.end()) { @@ -119,12 +118,12 @@ void OpenALInvoker::send(const SendRequest& req) { return; } sourceId = req.params.find("source")->second; - + if (_sources.find(sourceId) == _sources.end()) { LOG(WARNING) << "Given source '" << sourceId << "' not active or not existing"; return; } - + getPosFromParams(req.params, _sources[sourceId]->pos); try { _sources[sourceId]->player->setPosition(_sources[sourceId]->pos); @@ -145,12 +144,16 @@ void OpenALInvoker::fillBuffers(void* userdata) { // do nothing until we have at least one source int waitMs = std::numeric_limits<int>::max(); INST->_mutex.lock(); - while (INST->_sources.size() == 0) { + while (INST->_sources.size() == 0 && INST->_isStarted) { INST->_sourcesAvailable.wait(INST->_mutex); } + + if (!INST->_isStarted) + return; + // here we are with at least one source and a locked mutex assert(INST->_sources.size() > 0); - + std::map<std::string, OpenALSource*>::iterator srcIter = INST->_sources.begin(); while(srcIter != INST->_sources.end()) { OpenALSource* src = srcIter->second; @@ -195,7 +198,7 @@ void OpenALInvoker::fillBuffers(void* userdata) { } } } - + // there are unwritten samples in the buffer if (src->read != src->written) { try { @@ -211,15 +214,16 @@ void OpenALInvoker::fillBuffers(void* userdata) { assert(src->finished); } } - + waitMs = (wait < waitMs ? wait : waitMs); srcIter++; } - + // std::cout << "W" << waitMs << "."; - + INST->_mutex.unlock(); - tthread::this_thread::sleep_for(tthread::chrono::milliseconds(waitMs)); + if (waitMs < std::numeric_limits<int>::max()) + tthread::this_thread::sleep_for(tthread::chrono::milliseconds(waitMs)); } } @@ -233,14 +237,17 @@ void OpenALInvoker::invoke(const InvokeRequest& req) { if (_alDevice == NULL) { throw std::string("__FILE__ __LINE__ openal error opening device"); } - + // create new context with device _alContext = alcCreateContext (_alDevice, NULL); if (_alContext == NULL) { alcCloseDevice (_alDevice); throw std::string("openal error create context"); } - + + std::cout << boost::lexical_cast<std::string>(_alContext); + std::cout << boost::lexical_cast<std::string>(_alDevice); + // alcMakeContextCurrent(_alContext); // float listener[3] = {0,0,0}; // alListenerfv(AL_POSITION, listener); @@ -257,7 +264,7 @@ void OpenALInvoker::invoke(const InvokeRequest& req) { start(); } - + void OpenALInvoker::notifyOfEnd(OpenALSource* src) { Event ev; ev.name = "audio.end"; @@ -284,7 +291,7 @@ void OpenALInvoker::getPosFromParams(const std::multimap<std::string, std::strin } catch (boost::bad_lexical_cast& e) { LOG(ERROR) << "Cannot interpret x, y or z as float value in params: " << e.what(); } - + try { // right is an alias for x if (params.find("right") != params.end()) @@ -298,7 +305,7 @@ void OpenALInvoker::getPosFromParams(const std::multimap<std::string, std::strin } catch (boost::bad_lexical_cast& e) { LOG(ERROR) << "Cannot interpret right, height or front as float value in params: " << e.what(); } - + // do we have a position on a circle? try { if (params.find("circle") != params.end()) { @@ -307,24 +314,24 @@ void OpenALInvoker::getPosFromParams(const std::multimap<std::string, std::strin position[2] = -1 * sinf(rad); // z axis increases to front position[0] *= 150; position[2] *= 150; - + } } catch (boost::bad_lexical_cast& e) { LOG(ERROR) << "Cannot interpret circle as float value in params: " << e.what(); } - + // position[0] = position[0] / _maxPos[0]; // position[1] = position[1] / _maxPos[1]; // position[2] = position[2] / _maxPos[2]; // std::cout << _pos[0] << ":" << _pos[1] << ":" << _pos[2] << std::endl; - + } float OpenALInvoker::posToRadian(const std::string& pos) { - + std::string trimmedPos = boost::trim_copy(pos); float rad = 0; - + if (trimmedPos.size() > 3 && boost::iequals("deg", trimmedPos.substr(trimmedPos.length() - 3, 3))) { rad = boost::lexical_cast<float>(trimmedPos.substr(0, trimmedPos.size() - 3)); rad = fmodf(rad, 360); // into range [0-360] diff --git a/src/uscxml/plugins/invoker/audio/OpenALInvoker.h b/src/uscxml/plugins/invoker/audio/OpenALInvoker.h index c0ed842..086bfe8 100644 --- a/src/uscxml/plugins/invoker/audio/OpenALInvoker.h +++ b/src/uscxml/plugins/invoker/audio/OpenALInvoker.h @@ -24,7 +24,7 @@ class OpenALSource { public: OpenALSource(); ~OpenALSource(); - + OpenALPlayer* player; char buffer[ALPLAY_AUDIO_BUFFER_SIZE]; bool loop; @@ -35,7 +35,7 @@ public: URL file; PCMConverter* transform; }; - + class OpenALInvoker : public InvokerImpl { public: OpenALInvoker(); @@ -49,7 +49,7 @@ public: names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#openal"); return names; } - + virtual Data getDataModelVariables(); virtual void send(const SendRequest& req); virtual void cancel(const std::string sendId); @@ -59,20 +59,20 @@ protected: std::map<std::string, OpenALSource*> _sources; ALCcontext* _alContext; ALCdevice* _alDevice; - + tthread::recursive_mutex _mutex; tthread::thread* _thread; tthread::condition_variable _sourcesAvailable; bool _isStarted; bool _isRunning; - + static void fillBuffers(void* userdata); void start(); void notifyOfEnd(OpenALSource*); void notifyOfLoop(OpenALSource*); - + float posToRadian(const std::string& pos); void getPosFromParams(const std::multimap<std::string, std::string>& params, float* position); diff --git a/src/uscxml/plugins/invoker/audio/OpenALPlayer.cpp b/src/uscxml/plugins/invoker/audio/OpenALPlayer.cpp index 4266f79..a5f90b8 100644 --- a/src/uscxml/plugins/invoker/audio/OpenALPlayer.cpp +++ b/src/uscxml/plugins/invoker/audio/OpenALPlayer.cpp @@ -17,11 +17,11 @@ OpenALPlayer::OpenALPlayer(ALCcontext* context, OpenALPlayerCallback* audioCallb _nrBuffers = 0; _thread = NULL; _alId = 0; - + _position[0] = _position[1] = _position[2] = 0; _velocity[0] = _velocity[1] = _velocity[2] = 0; _direction[0] = _direction[1] = _direction[2] = 0; - + tthread::lock_guard<tthread::recursive_mutex> lock(_alMutex); if (context == NULL) { // this is in essence alutInit() from freealut. @@ -143,7 +143,7 @@ void OpenALPlayer::init() { // get available buffer ids tthread::lock_guard<tthread::recursive_mutex> lock(_alMutex); - + if (!alcMakeContextCurrent (_context)) { throw std::runtime_error("openal error make context current"); } @@ -153,7 +153,7 @@ void OpenALPlayer::init() { // get new source id from openAL alGenSources(1, &_alId); - + checkOpenALError(__LINE__); if (!alIsSource(_alId)) { throw std::runtime_error("openal source id not valid"); @@ -254,7 +254,7 @@ int OpenALPlayer::write(char* buffer, int size, int* repollAt, bool blocking) { if (!alcMakeContextCurrent (_context)) { throw std::runtime_error("openal error make context current"); } - + // try to enqueue the given buffer data for (;;) { // do we have an empty buffer in the OpenAL queue? @@ -264,7 +264,7 @@ int OpenALPlayer::write(char* buffer, int size, int* repollAt, bool blocking) { // if (!isPlaying()) // std::cout << "-"; - + if (processed > 0) { // std::cout << "P" << processed; ALuint bufferId = 0; @@ -308,7 +308,7 @@ int OpenALPlayer::write(char* buffer, int size, int* repollAt, bool blocking) { // there was a free buffer, repoll immediately to try to write more if (repollAt) *repollAt = 0; - + break; } else { // std::cout << "X"; @@ -330,7 +330,7 @@ int OpenALPlayer::write(char* buffer, int size, int* repollAt, bool blocking) { checkOpenALError(__LINE__); _isStarted = true; } - + return size; } diff --git a/src/uscxml/plugins/invoker/audio/PCMConverter.h b/src/uscxml/plugins/invoker/audio/PCMConverter.h index 6036af2..df367f8 100644 --- a/src/uscxml/plugins/invoker/audio/PCMConverter.h +++ b/src/uscxml/plugins/invoker/audio/PCMConverter.h @@ -18,7 +18,7 @@ public: virtual ~PCMConverter() {} virtual void seek(unsigned int pos) = 0; virtual int read(char* buffer, unsigned int size) = 0; - + virtual void setOutFormat(const PCMFormat& format) = 0; virtual PCMFormat getInFormat() = 0; protected: diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp index 5900cc8..0f6b776 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp @@ -28,13 +28,18 @@ DirMonInvoker::DirMonInvoker() : _reportExisting(true), _reportHidden(false), _recurse(false), - _thread(NULL) { + _thread(NULL), + _watcher(NULL) { } DirMonInvoker::~DirMonInvoker() { _isRunning = false; - if (_thread) + if (_thread) { _thread->join(); + delete _thread; + } + if (_watcher) + delete(_watcher); }; boost::shared_ptr<InvokerImpl> DirMonInvoker::create(InterpreterImpl* interpreter) { @@ -218,6 +223,15 @@ void DirMonInvoker::handleChanges(DirectoryWatch::Action action, const std::stri returnEvent(event); } +DirectoryWatch::~DirectoryWatch() { + std::map<std::string, DirectoryWatch*>::iterator dirIter = _knownDirs.begin(); + while(dirIter != _knownDirs.end()) { + delete(dirIter->second); + dirIter++; + } + +} + void DirectoryWatch::reportAsDeleted() { std::map<std::string, struct stat>::iterator fileIter = _knownEntries.begin(); while(fileIter != _knownEntries.end()) { diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h index 611106b..59eee81 100644 --- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h +++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h @@ -1,6 +1,7 @@ #ifndef DIRMONINVOKER_H_W09J90F0 #define DIRMONINVOKER_H_W09J90F0 +#include <uscxml/config.h> #include <uscxml/Interpreter.h> #include <map> #include <sys/stat.h> @@ -23,6 +24,7 @@ public: }; DirectoryWatch(const std::string& dir, bool recurse = false) : _dir(dir), _recurse(recurse), _lastChecked(0) {} + ~DirectoryWatch(); void addMonitor(DirectoryWatchMonitor* monitor) { _monitors.insert(monitor); @@ -33,6 +35,24 @@ public: void updateEntries(bool reportAsExisting = false); void reportAsDeleted(); + std::map<std::string, struct stat> getAllEntries() { + std::map<std::string, struct stat> entries; + entries.insert(_knownEntries.begin(), _knownEntries.end()); + + std::map<std::string, DirectoryWatch*>::iterator dirIter = _knownDirs.begin(); + while(dirIter != _knownDirs.end()) { + std::map<std::string, struct stat> dirEntries = dirIter->second->getAllEntries(); + std::map<std::string, struct stat>::iterator dirEntryIter = dirEntries.begin(); + while(dirEntryIter != dirEntries.end()) { + entries[dirIter->first + PATH_SEPERATOR + dirEntryIter->first] = dirEntryIter->second; + dirEntryIter++; + } + dirIter++; + } + + return entries; + } + protected: DirectoryWatch(const std::string& dir, const std::string& relDir) : _dir(dir), _relDir(relDir), _recurse(true), _lastChecked(0) {} diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp index bbfdabd..a70be38 100644 --- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp +++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp @@ -21,14 +21,14 @@ UmundoInvoker::UmundoInvoker() : _pub(NULL), _sub(NULL) { UmundoInvoker::~UmundoInvoker() { if (_node) { - if (_sub) { - _node->removeSubscriber(*_sub); - delete _sub; - } - if (_pub) { - _node->removePublisher(*_pub); - delete _pub; - } +// if (_sub) { +// _node->removeSubscriber(*_sub); +// delete _sub; +// } +// if (_pub) { +// _node->removePublisher(*_pub); +// delete _pub; +// } } }; diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index b2a6824..a612ee6 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -80,8 +80,14 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { while(std::getline(ss, term, '&')) { size_t split = term.find_first_of("="); if (split != std::string::npos) { - std::string key = evhttp_decode_uri(term.substr(0, split).c_str()); - std::string value = evhttp_decode_uri(term.substr(split + 1).c_str()); + + char* keyCStr = evhttp_decode_uri(term.substr(0, split).c_str()); + char* valueCStr = evhttp_decode_uri(term.substr(split + 1).c_str()); + std::string key = keyCStr; + std::string value = valueCStr; + free(keyCStr); + free(valueCStr); + if (boost::iequals(key, "_scxmleventname")) { reqEvent.name = value; } else if (boost::iequals(key, "content")) { @@ -92,22 +98,30 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { } } else { // this is most likely wrong - reqEvent.content = evhttp_decode_uri(term.c_str()); + char* contentCStr = evhttp_decode_uri(term.c_str()); + reqEvent.content = contentCStr; + free(contentCStr); } } } else { if (reqEvent.data.compound["header"].compound.find("_scxmleventstruct") != reqEvent.data.compound["header"].compound.end()) { // TODO: this looses all other information - reqEvent = Event::fromXML(evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventstruct"].atom.c_str())); + char* scxmlStructCStr = evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventstruct"].atom.c_str()); + reqEvent = Event::fromXML(scxmlStructCStr); + free(scxmlStructCStr); scxmlStructFound = true; } if (reqEvent.data.compound["header"].compound.find("_scxmleventname") != reqEvent.data.compound["header"].compound.end()) { - reqEvent.name = evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventname"].atom.c_str()); + char* evNameCStr = evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventname"].atom.c_str()); + reqEvent.name = evNameCStr; + free(evNameCStr); } } std::map<std::string, Data>::iterator headerIter = reqEvent.data.compound["header"].compound.begin(); while(headerIter != reqEvent.data.compound["header"].compound.end()) { - reqEvent.data.compound[headerIter->first] = Data(evhttp_decode_uri(headerIter->second.atom.c_str()), Data::VERBATIM); + char* headerCStr = evhttp_decode_uri(headerIter->second.atom.c_str()); + reqEvent.data.compound[headerIter->first] = Data(headerCStr, Data::VERBATIM); + free(headerCStr); headerIter++; } @@ -162,8 +176,12 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { // event name if (req.name.size() > 0) { - kvps << kvpSeperator << evhttp_encode_uri("_scxmleventname") << "=" << evhttp_encode_uri(req.name.c_str()); + char* eventNameCStr = evhttp_encode_uri("_scxmleventname"); + char* eventValueCStr = evhttp_encode_uri(req.name.c_str()); + kvps << kvpSeperator << eventNameCStr << "=" << eventValueCStr; kvpSeperator = "&"; + free(eventNameCStr); + free(eventValueCStr); // targetURL.addOutHeader("_scxmleventname", evhttp_encode_uri(req.name.c_str())); } @@ -171,7 +189,11 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { if (req.namelist.size() > 0) { std::map<std::string, std::string>::const_iterator namelistIter = req.namelist.begin(); while (namelistIter != req.namelist.end()) { - kvps << kvpSeperator << evhttp_encode_uri(namelistIter->first.c_str()) << "=" << evhttp_encode_uri(namelistIter->second.c_str()); + char* keyCStr = evhttp_encode_uri(namelistIter->first.c_str()); + char* valueCStr = evhttp_encode_uri(namelistIter->second.c_str()); + kvps << kvpSeperator << keyCStr << "=" << valueCStr; + free(keyCStr); + free(valueCStr); kvpSeperator = "&"; // targetURL.addOutHeader(namelistIter->first, namelistIter->second); namelistIter++; @@ -182,7 +204,11 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { if (req.params.size() > 0) { std::multimap<std::string, std::string>::const_iterator paramIter = req.params.begin(); while (paramIter != req.params.end()) { - kvps << kvpSeperator << evhttp_encode_uri(paramIter->first.c_str()) << "=" << evhttp_encode_uri(paramIter->second.c_str()); + char* keyCStr = evhttp_encode_uri(paramIter->first.c_str()); + char* valueCStr = evhttp_encode_uri(paramIter->second.c_str()); + kvps << kvpSeperator << keyCStr << "=" << valueCStr; + free(keyCStr); + free(valueCStr); kvpSeperator = "&"; // targetURL.addOutHeader(paramIter->first, paramIter->second); paramIter++; @@ -192,13 +218,21 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { // content if (req.content.size() > 0) { - kvps << kvpSeperator << evhttp_encode_uri("content") << "=" << evhttp_encode_uri(req.content.c_str()); + char* keyCStr = evhttp_encode_uri("content"); + char* valueCStr = evhttp_encode_uri(req.content.c_str()); + kvps << kvpSeperator << keyCStr << "=" << valueCStr; + free(keyCStr); + free(valueCStr); kvpSeperator = "&"; } if (req.dom) { std::stringstream xmlStream; xmlStream << req.dom; - kvps << kvpSeperator << evhttp_encode_uri("content") << "=" << evhttp_encode_uri(xmlStream.str().c_str()); + char* keyCStr = evhttp_encode_uri("content"); + char* valueCStr = evhttp_encode_uri(xmlStream.str().c_str()); + kvps << kvpSeperator << keyCStr << "=" << valueCStr; + free(keyCStr); + free(valueCStr); kvpSeperator = "&"; } targetURL.setOutContent(kvps.str()); diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp index 288bfb7..98d98e1 100644 --- a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp @@ -138,6 +138,9 @@ void SCXMLIOProcessor::send(const SendRequest& req) { tthread::lock_guard<tthread::recursive_mutex> lock(_interpreter->_mutex); try { _interpreter->_invokers[invokeId].send(reqCopy); + } catch(Event e) { + // Is this the right thing to do? + _interpreter->receive(e); } catch(...) { LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId; } diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index f4b1a57..e37d8cc 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -38,6 +38,7 @@ HTTPServer::HTTPServer(unsigned short port) { _port = port; _base = event_base_new(); _http = evhttp_new(_base); + _thread = NULL; evhttp_set_allowed_methods(_http, EVHTTP_REQ_GET | @@ -63,6 +64,9 @@ HTTPServer::HTTPServer(unsigned short port) { } HTTPServer::~HTTPServer() { + _isRunning = false; + _thread->join(); + delete _thread; } HTTPServer* HTTPServer::_instance = NULL; @@ -229,7 +233,9 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD std::string contentType = request.data.compound["header"].compound["Content-Type"].atom; if (false) { } else if (boost::iequals(contentType, "application/x-www-form-urlencoded")) { - request.data.compound["content"].atom = evhttp_decode_uri(request.data.compound["content"].atom.c_str()); + char* contentCStr = evhttp_decode_uri(request.data.compound["content"].atom.c_str()); + request.data.compound["content"].atom = contentCStr; + free(contentCStr); } else if (boost::iequals(contentType, "application/json")) { request.data.compound["content"] = Data::fromJSON(request.data.compound["content"].atom); } @@ -346,7 +352,7 @@ bool HTTPServer::registerServlet(const std::string& path, HTTPServlet* servlet) INSTANCE->_servlets[suffixedPath] = servlet; - LOG(INFO) << "HTTP Servlet listening at: " << servletURL.str() << std::endl; +// LOG(INFO) << "HTTP Servlet listening at: " << servletURL.str() << std::endl; // register callback evhttp_set_cb(INSTANCE->_http, ("/" + suffixedPath).c_str(), HTTPServer::httpRecvReqCallback, servlet); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 983e179..a78c079 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,11 @@ target_link_libraries(test-eventdelay uscxml) add_test(test-eventdelay ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-eventdelay) set_target_properties(test-eventdelay PROPERTIES FOLDER "Tests") +add_executable(test-stress src/test-stress.cpp) +target_link_libraries(test-stress uscxml) +add_test(test-stress ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-stress ${CMAKE_SOURCE_DIR}/test/samples/w3c) +set_target_properties(test-stress PROPERTIES FOLDER "Tests") + if (OFF) add_executable(test-dirmon src/test-dirmon.cpp) target_link_libraries(test-dirmon uscxml) diff --git a/test/samples/uscxml/test-communication.scxml b/test/samples/uscxml/test-communication.scxml index 4811a3f..2cba08e 100644 --- a/test/samples/uscxml/test-communication.scxml +++ b/test/samples/uscxml/test-communication.scxml @@ -1,6 +1,7 @@ <scxml datamodel="ecmascript" initial="start" binding="late" name="foo"> - <state id="start"> - + <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> + + <state id="start"> <!-- Setup datamodel, print environment and send ourself an event to transition to next state --> <datamodel> @@ -24,6 +25,9 @@ This is some content you got there dude! </send> </onentry> <transition event="transitionToNext" target="step1" cond="_event.data.bar == 'this is the bar data'" /> + <transition event="*" target="final"> + <log label="FAIL!" expr="dump(_event)" /> + </transition> </state> <state id="step1"> <onentry> diff --git a/test/samples/uscxml/test-java-invoker.scxml b/test/samples/uscxml/test-java-invoker.scxml index 97d66c8..a226913 100644 --- a/test/samples/uscxml/test-java-invoker.scxml +++ b/test/samples/uscxml/test-java-invoker.scxml @@ -7,16 +7,17 @@ <script>dump(_event);</script> </finalize> <content> - <foo></foo> - </content> - + </content> </invoke> <transition event="*" target="invokeJSON" /> </state> <state id="invokeJSON"> <invoke type="java"> <content> - <foo></foo> + { + "foo": "bar", + "baz": 12 + } </content> <finalize> <script>dump(_event);</script> diff --git a/test/samples/uscxml/test-openal.scxml b/test/samples/uscxml/test-openal.scxml index 9a1dec0..b17e34b 100644 --- a/test/samples/uscxml/test-openal.scxml +++ b/test/samples/uscxml/test-openal.scxml @@ -1,55 +1,125 @@ <scxml datamodel="ecmascript" name="spatial.audio.test"> <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> <script> - var bubblesDeg = 0; - var electricDeg = 90; + var audioPos = 0; + var audioURL = "http://uscxml.tk.informatik.tu-darmstadt.de/audio"; </script> - <state id="click.continuously"> - <invoke type="openal" id="audio.id1" /> + <state id="audiotests"> + <invoke type="openal" id="audio" /> <state id="ready"> <onentry> - <send event="spatial-audio.play" delay="1ms" /> + <send event="start" delay="10ms" /> <log expr="'Ready'" /> </onentry> - <transition target="play" event="spatial-audio.play" /> - </state> - <parallel id="play"> - <state id="bubbles"> - <onentry> - <send target="#_audio.id1" event="play" id="bubbles"> - <param name="src" expr="'http://www.talkingwav.com/various/applause.wav'" /> - </send> - </onentry> - </state> - <state id="electric"> - <onentry> - <send target="#_audio.id1" event="play" id="electric"> - <param name="src" expr="'http://www.talkingwav.com/various/aaaaagh.wav'" /> + <transition target="wav" event="spatial-audio.play" /> + <parallel id="start"> + <state id="move.audio"> + <send target="#_audio" event="move.source"> </send> - </onentry> - </state> - <state id="rotate"> - <state id="rotateinner"> - <onentry> - <send event="rotate" delay="1000ms" /> - <send target="#_audio.id1" event="move.source"> - <param name="source" expr="'bubbles'" /> - <param name="circle" expr="bubblesDeg + 'deg'" /> - </send> - <send target="#_audio.id1" event="move.source"> - <param name="source" expr="'electric'" /> - <param name="circle" expr="electricDeg + 'deg'" /> - </send> - <script> - bubblesDeg += 10; - electricDeg += 20; - </script> - </onentry> - <transition event="rotate" type="internal" target="rotateinner" /> </state> - </state> - </parallel> + <state id="play.audio"> + <state id="wav"> + <state id="11025-8bit-wav"> + <onentry> + <log expr="'11025-8bit-wav'" /> + <send target="#_audio" event="play" delay="10ms"><param name="src" expr="audioURL + '/wav/11025-8bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="22050-8bit-wav" /> + </state> + <state id="22050-8bit-wav"> + <onentry> + <log expr="'22050-8bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/22050-8bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="44100-8bit-wav" /> + </state> + <state id="44100-8bit-wav"> + <onentry> + <log expr="'44100-8bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/44100-8bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="11025-16bit-wav" /> + </state> + <state id="11025-16bit-wav"> + <onentry> + <log expr="'11025-16bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/11025-16bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="22050-16bit-wav" /> + </state> + <state id="22050-16bit-wav"> + <onentry> + <log expr="'22050-16bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/22050-16bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="44100-16bit-wav" /> + </state> + <state id="44100-16bit-wav"> + <onentry> + <log expr="'44100-16bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/44100-16bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="11025-24bit-wav" /> + </state> + <state id="11025-24bit-wav"> + <onentry> + <log expr="'11025-24bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/11025-24bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="22050-24bit-wav" /> + </state> + <state id="22050-24bit-wav"> + <onentry> + <log expr="'22050-24bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/22050-24bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="44100-24bit-wav" /> + </state> + <state id="44100-24bit-wav"> + <onentry> + <log expr="'44100-24bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/44100-24bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="11025-32bit-wav" /> + </state> + <state id="11025-32bit-wav"> + <onentry> + <log expr="'11025-32bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/11025-32bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="22050-32bit-wav" /> + </state> + <state id="22050-32bit-wav"> + <onentry> + <log expr="'22050-32bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/22050-32bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="44100-32bit-wav" /> + </state> + <state id="44100-32bit-wav"> + <onentry> + <log expr="'44100-32bit-wav'" /> + <send target="#_audio" event="play"><param name="src" expr="audioURL + '/wav/44100-32bit-mono.wav'" /></send> + </onentry> + <transition event="audio.end" target="final" /> + </state> + </state> + <state id="caf"> + </state> + <state id="flac"> + </state> + <state id="mp3"> + </state> + <state id="ogg"> + </state> + <state id="aiff"> + </state> + </state> + </parallel> + </state> + <transition event="error.*" target="final"> + <log expr="dump(_event);" /> + </transition> </state> - <final id="final" /> </scxml>
\ No newline at end of file diff --git a/test/samples/uscxml/test-simplest.scxml b/test/samples/uscxml/test-simplest.scxml new file mode 100644 index 0000000..8e90e38 --- /dev/null +++ b/test/samples/uscxml/test-simplest.scxml @@ -0,0 +1,3 @@ +<scxml> + <final id="foo" /> +</scxml>
\ No newline at end of file diff --git a/test/src/test-stress.cpp b/test/src/test-stress.cpp new file mode 100644 index 0000000..50b5f34 --- /dev/null +++ b/test/src/test-stress.cpp @@ -0,0 +1,183 @@ +#include "uscxml/config.h" +#include "uscxml/Interpreter.h" +#include <glog/logging.h> + +#include "uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h" + +#ifdef HAS_SIGNAL_H +#include <signal.h> +#endif + +#ifdef HAS_EXECINFO_H +#include <execinfo.h> +#endif + +#ifdef HAS_DLFCN_H +#include <dlfcn.h> +#endif + +#ifdef _WIN32 +#include "XGetopt.h" +#endif + +#ifdef HAS_EXECINFO_H +void printBacktrace(void** array, int size) { + char** messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) { + std::cerr << "\t" << messages[i] << std::endl; + } + std::cerr << std::endl; + free(messages); +} + +int startedAt; +int lastTransitionAt; + +#ifdef HAS_DLFCN_H +// see https://gist.github.com/nkuln/2020860 +typedef void (*cxa_throw_type)(void *, void *, void (*) (void *)); +cxa_throw_type orig_cxa_throw = 0; + +void load_orig_throw_code() { + orig_cxa_throw = (cxa_throw_type) dlsym(RTLD_NEXT, "__cxa_throw"); +} + +extern "C" +void __cxa_throw (void *thrown_exception, void *pvtinfo, void (*dest)(void *)) { + std::cerr << __FUNCTION__ << " will throw exception from " << std::endl; + if (orig_cxa_throw == 0) + load_orig_throw_code(); + + void *array[50]; + size_t size = backtrace(array, 50); + printBacktrace(array, size); + orig_cxa_throw(thrown_exception, pvtinfo, dest); +} +#endif +#endif + + +// see http://stackoverflow.com/questions/2443135/how-do-i-find-where-an-exception-was-thrown-in-c +void customTerminate() { + static bool tried_throw = false; + try { + // try once to re-throw currently active exception + if (!tried_throw) { + throw; + tried_throw = true; + } else { + tried_throw = false; + }; + } catch (const std::exception &e) { + std::cerr << __FUNCTION__ << " caught unhandled exception. what(): " + << e.what() << std::endl; + } catch (const uscxml::Event &e) { + std::cerr << __FUNCTION__ << " caught unhandled exception. Event: " + << e << std::endl; + } catch (...) { + std::cerr << __FUNCTION__ << " caught unknown/unhandled exception." + << std::endl; + } + +#ifdef HAS_EXECINFO_H + void * array[50]; + int size = backtrace(array, 50); + + printBacktrace(array, size); +#endif + abort(); +} + +void printUsageAndExit() { + printf("test-stress version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n"); + printf("Usage\n"); + printf("\ttest-stress"); +#ifdef BUILD_AS_PLUGINS + printf(" [-p pluginPath]"); +#endif + printf(" <PATH>\n"); + printf("\n"); + exit(1); +} + +class StatusMonitor : public uscxml::InterpreterMonitor { + void beforeTakingTransitions(uscxml::Interpreter interpreter, const Arabica::XPath::NodeSet<std::string>& transitions) { + lastTransitionAt = time(NULL); + } + +}; + +int main(int argc, char** argv) { + using namespace uscxml; + + std::set_terminate(customTerminate); + +#if defined(HAS_SIGNAL_H) && !defined(WIN32) + signal(SIGPIPE, SIG_IGN); +#endif + + if (argc < 2) { + printUsageAndExit(); + } + + google::InitGoogleLogging(argv[0]); + google::LogToStderr(); + +#ifndef _WIN32 + opterr = 0; +#endif + int option; + while ((option = getopt(argc, argv, "vl:p:")) != -1) { + switch(option) { + case 'l': + google::InitGoogleLogging(optarg); + break; + case 'p': + uscxml::Factory::pluginPath = optarg; + break; + case '?': + break; + default: + printUsageAndExit(); + break; + } + } + + DirectoryWatch* watcher = new DirectoryWatch(argv[optind], true); + watcher->updateEntries(true); + std::map<std::string, struct stat> entries = watcher->getAllEntries(); + + StatusMonitor vm; + + std::map<std::string, struct stat>::iterator entryIter = entries.begin(); + while(entryIter != entries.end()) { + if (!boost::ends_with(entryIter->first, ".scxml")) { + entryIter++; + continue; + } + + startedAt = time(NULL); + lastTransitionAt = time(NULL); + + LOG(INFO) << "Processing " << entryIter->first; + Interpreter interpreter = Interpreter::fromURI(std::string(argv[optind]) + PATH_SEPERATOR + entryIter->first); + if (interpreter) { + interpreter.setCmdLineOptions(argc, argv); + + interpreter.addMonitor(&vm); + + interpreter.start(); + int now = time(NULL); + while(now - startedAt < 20 && now - lastTransitionAt < 2) { + // let the interpreter run for a bit + tthread::this_thread::sleep_for(tthread::chrono::seconds(1)); + now = time(NULL); + } + + } + entryIter++; + } + + delete watcher; + return EXIT_SUCCESS; +}
\ No newline at end of file diff --git a/test/src/test-url.cpp b/test/src/test-url.cpp index 69f9014..e0f8343 100644 --- a/test/src/test-url.cpp +++ b/test/src/test-url.cpp @@ -51,6 +51,25 @@ int main(int argc, char** argv) { std::string exeName = argv[0];
exeName = exeName.substr(exeName.find_last_of("\\/") + 1);
+ {
+ try {
+ URL url("http://asdfasdfasdfasdf.wgferg");
+ url.download(true);
+ assert(false);
+ } catch (Event e) {
+ }
+ }
+
+ {
+ try {
+ URL url("http://uscxml.tk.informatik.tu-darmstadt.de/foobarfoo.html");
+ url.download(true);
+ assert(false);
+ } catch (Event e) {
+ std::cout << e << std::endl;
+ }
+ }
+
#if 0
{
Interpreter interpreter = Interpreter::fromURI("/Users/sradomski/Desktop/application_small.scxml");
|