-
Notifications
You must be signed in to change notification settings - Fork 3
Example: DynamicObject
DynamicObject
implements a truly dynamic object instance which you can expose to JavaScript. The properties of the object do not need to be known in advance. For example:
alert(msg.text);
If the msg
object was a libjsapi
DynamicObject
then the reference to the text
field would be routed to the GetCallback
supplied in the object Create() call. In the get call you can return any value you like to SpiderMonkey including undefined
, null
or the classic "hello world".
Because the fields are not known in advance DynamicObject
exposes an EnumeratorCallback
parameter which you should implement if you expect your JavaScript code to enumerate your objects with a for (prop in obj)
.
The following example demonstrates field values being resolved by a std::unordered_map
, any fields not found return undefined
as you would expect from a real JavaScript object.
#include <iostream>
#include <vector>
#include <unordered_map>
#include "libjsapi.h"
int main() {
std::unordered_map<std::string, std::string> data = {
{ "hello", "world" }, { "lorem", "ipsum" },
{ "foo", "bar" } };
rs::jsapi::Context cx;
// create a dynamic object which returns a string from the map
rs::jsapi::Value obj(cx);
rs::jsapi::DynamicObject::Create(cx,
[&](const char* name, rs::jsapi::Value& value) {
auto result = data.find(name);
if (result != data.cend()) {
value = result->second;
} else {
value.setUndefined();
}
},
nullptr,
nullptr,
nullptr,
obj);
// create a function which returns the value of the field 'n'
// on the passed object
cx.Evaluate("var myfunc=function(o, n){return o[n];};");
rs::jsapi::FunctionArguments args(cx);
args.Append(obj);
args.Append("hello");
// invoke the function and get the value of the field 'hello'
rs::jsapi::Value result(cx);
cx.Call("myfunc", args, result);
std::cout << result << std::endl;
// invoke the function and get the value of the field 'lorem'
args[1] = rs::jsapi::Value(cx, "lorem");
cx.Call("myfunc", args, result);
std::cout << result << std::endl;
// invoke the function and get the value of the field 'foo'
args[1] = rs::jsapi::Value(cx, "foo");
cx.Call("myfunc", args, result);
std::cout << result << std::endl;
// invoke the function and get the value of the field 'xyz'
args[1] = rs::jsapi::Value(cx, "xyz");
cx.Call("myfunc", args, result);
std::cout << result << std::endl;
}
Running the example yields the following output on the console:
world
ipsum
bar
undefined
Once exposed to JavaScript the lifetime of your DynamicObject
instance is controlled by the SpiderMonkey garbage collector. See the Object example for details on how to implement a finalizer for your objects and arrays.