summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/script/ScriptEngine.hpp8
-rw-r--r--src/core/script/Variant.hpp21
-rw-r--r--src/plugins/mozjs/MozJsScriptEngine.cpp97
-rw-r--r--src/plugins/mozjs/MozJsScriptEngine.hpp54
4 files changed, 161 insertions, 19 deletions
diff --git a/src/core/script/ScriptEngine.hpp b/src/core/script/ScriptEngine.hpp
index 2341beb..6c048aa 100644
--- a/src/core/script/ScriptEngine.hpp
+++ b/src/core/script/ScriptEngine.hpp
@@ -27,6 +27,14 @@
#include "Variant.hpp"
+// TODO: Provide more Exception classes than ScriptEngineException -- one for
+// internal errors, one for script errors
+
+// TODO: Allow reporting multiple exceptions (e.g. to report all syntax errors
+// at once)
+
+// TODO: Add API that allow pre-compilation of scripts
+
namespace ousia {
namespace script {
diff --git a/src/core/script/Variant.hpp b/src/core/script/Variant.hpp
index 465793f..8cb0e8f 100644
--- a/src/core/script/Variant.hpp
+++ b/src/core/script/Variant.hpp
@@ -26,6 +26,12 @@
#include <string>
#include <vector>
+// TODO: Replace VariantType::number with VariantType::double
+// TODO: Convert VariantType::integer to int32_t
+// TODO: Use std::unique_ptr for *Function
+// TODO: Move semantic in complex constructors
+// TODO: Delete default constructors/assignment operators in pretty much everything
+
namespace ousia {
namespace script {
@@ -124,6 +130,9 @@ private:
};
public:
+
+ using Int = int32_t;
+
/**
* Copy constructor of the Variant class.
*
@@ -182,7 +191,8 @@ public:
Variant(const std::vector<Variant> &a);
/**
- * Constructor for map values. The given map is copied and managed by the new
+ * Constructor for map values. The given map is copied and managed by the
+ *new
* Variant instance.
*
* @param m is a reference to the map.
@@ -190,7 +200,8 @@ public:
Variant(const std::map<std::string, Variant> &m);
/**
- * Constructor for function values. The given pointer to the function object is cloned and managed by the new Variant instance.
+ * Constructor for function values. The given pointer to the function object
+ *is cloned and managed by the new Variant instance.
*
* @param f is a reference to the function.
*/
@@ -224,10 +235,7 @@ public:
*
* @return the current type of the Variant.
*/
- VariantType getType() const
- {
- return type;
- }
+ VariantType getType() const { return type; }
bool getBooleanValue() const;
int64_t getIntegerValue() const;
@@ -253,7 +261,6 @@ public:
*/
friend std::ostream &operator<<(std::ostream &os, const Variant &v);
};
-
}
}
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;
-
};
}
}