-
Notifications
You must be signed in to change notification settings - Fork 0
API: Script Keys and Objects
#Keys
ScriptObjectKeys
and ScriptObjectKey
are the underpinnings of the type system used by all scriptable objects in libscriptobject.
A key is made up from a field name and type (string, int, null, etc.), objects have one or more keys which ultimately describe the type of the object. Consider:
var x = { pi: 3.14159, theAnswer: 42 };
var y = { theAnswer: -42, pi: -3.14159 };
These two objects, x and y, have fields pi and theAnswer which have the same type in both objects. Inside libscriptobject the object instances x and y have keys which are used to describe the object, if we were to compare the keys (name and field type) then we could say the objects are the same 'type' since they are equivalent at the key level:
var x = { pi: double, theAnswer: integer };
var y = { pi: double, theAnswer: integer }; // note the field order has changed
Objects with identical keys can share those keys, resulting in only one instance of an object 'type'. Changing a field name, type, or number of fields either results in a new 'type' or the object sharing a common key object matching that new type.
Being able to track type equivalence for scriptable objects is a useful optimization; we can store a single instance of the keys describing the type and refer to that instance from all type-equivalent objects.
This technique saves both memory and CPU time but has a number of limitations:
- What happens when fields change type or when fields are removed or added?
- What happens if objects contain fields with random-like names (timestamps, GUIDs, etc.)?
Both of these issues defeat the type system but can be mitigated by libscriptobject:
- Fields can be removed from objects, this results in the creation of a new object with new keys
- Fields can be added to an object, this is done by merging objects together - much like JavaScript's
Object.assign()
function. - When objects are declared that are known to have random-like field names the caller can elect out of sharing the object's keys.
#Objects
ScriptObjects
are created by the ScriptObjectFactory
from a ScriptObjectSource
object which defines the properties and values of the fields in the object.
Callers can query the number of fields, their names, types and values. This type information can then in turn be exposed to a scripting engine allowing it access to the object as if it was a native script object instance.
Assuming our embedded scripting engine can make external calls to resolve fields then we could expose an object to the scripting engine thus:
// create a scriptable object
auto obj = ScriptObjectFactory::CreateObject(...);
// create an object `myObj` in the scripting engine context
EngineCreate("myObj", [&](const char* name) { return obj.getString(name); });
// execute some script to return the value of the field `myField`
EngineExecute("return myObj.myField;");
The example above shows a greatly simplified interaction between ScriptObject
and a scripting engine. Typically you will have to provide type conversions, enumerate the objects fields by name, expose the object extents and handle exceptions.
For more information on how to integrate with Mozilla's SpiderMonkey JavaScript engine check out ripcordsoftware/libjsapi. You can see both libscriptobject and libjsapi in action in ripcordsoftware/avancedb.