summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-10-26 01:17:02 +0000
committerandreas <andreas@daaaf23c-2e50-4459-9457-1e69db5a47bf>2014-10-26 01:17:02 +0000
commiteb7211bb8d199b60d1e15cc84e16e08f1e8c0f23 (patch)
tree41b0483045ad266ba41ad54f64b0c36f8b10522d /src/plugins
parent250d6a4dbe61b6798cd090abeabdc0ece8237dd3 (diff)
Fully implemented reading values from MozJs (except for all bugs that are still in it); added generic unit test for java script engine implementations; added suppressions for valgrind (as the mozjs library produced some leaks that can safely be ignored); added a bunch of TODOs
git-svn-id: file:///var/local/svn/basicwriter@79 daaaf23c-2e50-4459-9457-1e69db5a47bf
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/mozjs/MozJsScriptEngine.cpp97
-rw-r--r--src/plugins/mozjs/MozJsScriptEngine.hpp54
2 files changed, 139 insertions, 12 deletions
diff --git a/src/plugins/mozjs/MozJsScriptEngine.cpp b/src/plugins/mozjs/MozJsScriptEngine.cpp
index b7ff002..e3f72b1 100644
--- a/src/plugins/mozjs/MozJsScriptEngine.cpp
+++ b/src/plugins/mozjs/MozJsScriptEngine.cpp
@@ -16,6 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <jsapi.h>
+
#include "MozJsScriptEngine.hpp"
namespace ousia {
@@ -39,6 +41,36 @@ namespace script {
static const uint32_t MOZJS_RT_MEMSIZE = 64L * 1024L * 1024L;
static const uint32_t MOZJS_CTX_STACK_CHUNK_SIZE = 8192;
+/* Class MozJsScriptEngineFunction */
+
+MozJsScriptEngineFunction::MozJsScriptEngineFunction(
+ MozJsScriptEngineScope &scope, JS::Value &fun, JSObject *parent)
+ : scope(scope)
+{
+ this->fun = new JS::RootedValue(scope.cx, fun);
+ this->parent = new JS::RootedObject(scope.cx, parent);
+}
+
+MozJsScriptEngineFunction::~MozJsScriptEngineFunction()
+{
+ delete parent;
+ delete fun;
+}
+
+MozJsScriptEngineFunction *MozJsScriptEngineFunction::clone() const
+{
+ return new MozJsScriptEngineFunction(scope, fun->get(), parent->get());
+}
+
+Variant MozJsScriptEngineFunction::call(const std::vector<Variant> &args) const
+{
+ // TODO: Input parameter
+ JS::Value val;
+ scope.handleErr(JS_CallFunctionValue(scope.cx, parent->get(), fun->get(), 0,
+ nullptr, &val));
+ return scope.valueToVariant(val);
+}
+
/* Class MozJsScriptEngineScope */
/**
@@ -94,8 +126,51 @@ MozJsScriptEngineScope::~MozJsScriptEngineScope()
JS_DestroyContext(cx);
}
-Variant MozJsScriptEngineScope::toVariant(const JS::Value &val)
+Variant MozJsScriptEngineScope::arrayToVariant(JSObject *obj)
{
+ // Retrieve the array length
+ uint32_t len = 0;
+ handleErr(JS_GetArrayLength(cx, obj, &len));
+
+ // Create the result vector and reserve as much memory as needed
+ std::vector<Variant> array;
+ array.reserve(len);
+
+ // Fill the result vector
+ JS::Value arrayVal;
+ for (uint32_t i = 0; i < len; i++) {
+ handleErr(JS_GetElement(cx, obj, i, &arrayVal));
+ array.push_back(valueToVariant(arrayVal, obj));
+ }
+ return Variant{array};
+}
+
+Variant MozJsScriptEngineScope::objectToVariant(JSObject *obj)
+{
+ // Enumerate all object properties, perform error handling
+ JS::AutoIdArray ids(cx, JS_Enumerate(cx, obj));
+ if (!ids) {
+ handleErr();
+ }
+
+ // Iterate over all ids, add them to a map
+ std::map<std::string, Variant> map;
+ JS::Value key;
+ JS::Value val;
+ for (size_t i = 0; i < ids.length(); i++) {
+ handleErr(JS_IdToValue(cx, ids[i], &key));
+ handleErr(JS_GetPropertyById(cx, obj, ids[i], &val));
+ map.insert(std::make_pair<std::string, Variant>(
+ toString(key), valueToVariant(val, obj)));
+ }
+ return Variant{map};
+}
+
+Variant MozJsScriptEngineScope::valueToVariant(JS::Value &val, JSObject *parent)
+{
+ if (val.isNull()) {
+ return Variant::Null;
+ }
if (val.isBoolean()) {
return Variant{val.toBoolean()};
}
@@ -109,6 +184,22 @@ Variant MozJsScriptEngineScope::toVariant(const JS::Value &val)
// TODO: Remove the need for using "c_str"!
return Variant{toString(val.toString()).c_str()};
}
+ if (val.isObject()) {
+ JSObject &obj = val.toObject();
+
+ if (JS_IsArrayObject(cx, &obj)) {
+ return arrayToVariant(&obj);
+ }
+
+ if (JS_ObjectIsFunction(cx, &obj)) {
+ // TODO: Variant of the Variant function constructor which grants
+ // ownership of the pointer
+ MozJsScriptEngineFunction fun(*this, val, parent);
+ return Variant{&fun};
+ }
+
+ return objectToVariant(&obj);
+ }
return Variant::Null;
}
@@ -143,7 +234,7 @@ void MozJsScriptEngineScope::handleErr(bool ok)
}
}
-std::string MozJsScriptEngineScope::toString(const JS::Value &val)
+std::string MozJsScriptEngineScope::toString(JS::Value &val)
{
// If the given value already is a Javascript string, return it directly.
if (val.isString()) {
@@ -178,7 +269,7 @@ Variant MozJsScriptEngineScope::doRun(const std::string &code)
JS::Value rval;
handleErr(JS_EvaluateScript(cx, *global, code.c_str(), code.length(), "", 0,
&rval));
- return toVariant(rval);
+ return valueToVariant(rval);
}
void MozJsScriptEngineScope::doSetVariable(const std::string &name,
diff --git a/src/plugins/mozjs/MozJsScriptEngine.hpp b/src/plugins/mozjs/MozJsScriptEngine.hpp
index 68eee46..f98c871 100644
--- a/src/plugins/mozjs/MozJsScriptEngine.hpp
+++ b/src/plugins/mozjs/MozJsScriptEngine.hpp
@@ -19,26 +19,66 @@
#ifndef _MOZ_JS_SCRIPT_ENGINE_HPP_
#define _MOZ_JS_SCRIPT_ENGINE_HPP_
-#include <jsapi.h>
-
#include <core/script/ScriptEngine.hpp>
+#include <core/script/Function.hpp>
+#include <core/script/Object.hpp>
+
+/* Forward declarations from header jsapi.h */
+
+class JSRuntime;
+class JSContext;
+class JSCompartment;
+class JSString;
+class JSObject;
+
+namespace JS {
+class Value;
+template <typename T>
+class Rooted;
+typedef Rooted<JSObject *> RootedObject;
+typedef Rooted<Value> RootedValue;
+}
namespace ousia {
namespace script {
+class MozJsScriptEngineScope;
+
+class MozJsScriptEngineFunction : public Function {
+private:
+ MozJsScriptEngineScope &scope;
+ JS::RootedValue *fun;
+ JS::RootedObject *parent;
+
+public:
+ MozJsScriptEngineFunction(MozJsScriptEngineScope &scope, JS::Value &fun, JSObject *parent);
+
+ ~MozJsScriptEngineFunction();
+
+ MozJsScriptEngineFunction *clone() const override;
+
+ Variant call(const std::vector<Variant> &args) const override;
+};
+
class MozJsScriptEngineScope : public ScriptEngineScope {
+friend MozJsScriptEngineFunction;
+
private:
JSRuntime *rt;
JSContext *cx;
JSCompartment *oldCompartment;
JS::RootedObject *global;
- void handleErr(bool ok);
+ void handleErr(bool ok = false);
+
+ Variant arrayToVariant(JSObject *obj);
+
+ Variant objectToVariant(JSObject *obj);
- Variant toVariant(const JS::Value &val);
+ Variant valueToVariant(JS::Value &val, JSObject *parent = nullptr);
- std::string toString(const JS::Value &val);
+ std::string toString(JS::Value &val);
std::string toString(JSString *str);
@@ -52,22 +92,18 @@ public:
MozJsScriptEngineScope(JSRuntime *rt);
~MozJsScriptEngineScope() override;
-
};
class MozJsScriptEngine : public ScriptEngine {
-
private:
JSRuntime *rt;
public:
-
MozJsScriptEngine();
~MozJsScriptEngine();
MozJsScriptEngineScope *createScope() override;
-
};
}
}