From 8c84c3550ad13ec19b6340bd8e9633aee91156af Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Fri, 14 Nov 2014 10:41:47 +0100 Subject: Datamode Extensions for V8 --- src/uscxml/Factory.cpp | 4 ++ src/uscxml/plugins/DataModel.h | 3 +- .../ecmascript/JavaScriptCore/JSCDataModel.cpp | 2 +- .../datamodel/ecmascript/v8/V8DataModel.cpp | 63 ++++++++++++++++++++++ .../plugins/datamodel/ecmascript/v8/V8DataModel.h | 4 ++ 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index 0333b85..968aabd 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -652,6 +652,10 @@ boost::shared_ptr Factory::createExecutableContent(const } +void DataModelImpl::addExtension(DataModelExtension* ext) { + ERROR_EXECUTION_THROW("DataModel does not support extensions"); +} + size_t DataModelImpl::replaceExpressions(std::string& content) { std::stringstream ss; size_t replacements = 0; diff --git a/src/uscxml/plugins/DataModel.h b/src/uscxml/plugins/DataModel.h index a210ea1..05f89d5 100644 --- a/src/uscxml/plugins/DataModel.h +++ b/src/uscxml/plugins/DataModel.h @@ -97,8 +97,7 @@ public: _interpreter = interpreter; } - virtual void addExtension(DataModelExtension* ext) {} - + virtual void addExtension(DataModelExtension* ext); virtual std::string andExpressions(std::list) { return ""; } diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index bb77944..3c0b84b 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -112,7 +112,7 @@ void JSCDataModel::addExtension(DataModelExtension* ext) { currScope = JSValueToObject(_ctx, newScope, NULL); } else { JSStringRelease(pathCompJS); - throw "adsf"; + throw "Cannot add datamodel extension in non-object"; } } else { // this is the function! diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 153e2c0..5f18414 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -90,6 +90,69 @@ V8DataModel::~V8DataModel() { delete _dom; } +void V8DataModel::addExtension(DataModelExtension* ext) { + if (_extensions.find(ext) != _extensions.end()) + return; + + ext->dm = this; + _extensions.insert(ext); + + v8::Locker locker; + v8::HandleScope scope; + v8::Context::Scope contextScope(_contexts.front()); + v8::Handle currScope = _contexts.front()->Global(); + + std::list locPath = InterpreterImpl::tokenize(ext->provides(), '.'); + std::list::iterator locIter = locPath.begin(); + while(true) { + std::string pathComp = *locIter; + v8::Local pathCompJS = v8::String::New(locIter->c_str()); + + if (++locIter != locPath.end()) { + // just another intermediate step + if (!currScope->Has(pathCompJS)) { + currScope->Set(pathCompJS, v8::Object::New()); + } + + v8::Local newScope = currScope->Get(pathCompJS); + if (newScope->IsObject()) { + currScope = newScope->ToObject(); + } else { + throw "Cannot add datamodel extension in non-object"; + } + } else { + // this is the function! + currScope->Set(pathCompJS, v8::FunctionTemplate::New(jsExtension, v8::External::New(reinterpret_cast(ext)))->GetFunction(), v8::ReadOnly); + break; + } + } +} + +v8::Handle V8DataModel::jsExtension(const v8::Arguments& args) { + DataModelExtension* extension = static_cast(v8::External::Unwrap(args.Data())); + + v8::Local memberJS; + std::string memberName; + + if (args.Length() > 0 && args[0]->IsString()) { + memberJS = args[0]->ToString(); + memberName = *v8::String::AsciiValue(memberJS); + } + + if (args.Length() > 1) { + // setter + Data data = ((V8DataModel*)(extension->dm))->getValueAsData(args[1]); + extension->setValueOf(memberName, data); + return v8::Undefined(); + } + + if (args.Length() == 1) { + // getter + return ((V8DataModel*)(extension->dm))->getDataAsValue(extension->getValueOf(memberName)); + } + return v8::Undefined(); +} + boost::shared_ptr V8DataModel::create(InterpreterImpl* interpreter) { boost::shared_ptr dm = boost::shared_ptr(new V8DataModel()); dm->_interpreter = interpreter; diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index b114550..9e2ec71 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -96,6 +96,9 @@ public: virtual bool evalAsBool(const std::string& expr); virtual double evalAsNumber(const std::string& expr); + virtual void addExtension(DataModelExtension* ext); + + static v8::Handle jsExtension(const v8::Arguments& args); static v8::Handle jsIn(const v8::Arguments& args); static v8::Handle jsPrint(const v8::Arguments& args); @@ -118,6 +121,7 @@ protected: v8::Handle getNodeAsValue(const Arabica::DOM::Node& node); void throwExceptionEvent(const v8::TryCatch& tryCatch); + std::set _extensions; }; #ifdef BUILD_AS_PLUGINS -- cgit v0.12