-
-
Notifications
You must be signed in to change notification settings - Fork 749
Architecture of JavaScript variables
THIS WIKI IS OUT OF DATE. check out the README.md on GitHub for docs on Espruino internals, or see www.espruino.com for searchable, up to date docs on using Espruino.
The management of JavaScript variables within Espruino is possibly one of the most important areas of the projects.
The code maintaining the JavaScript variables can be found within src\jsvar.c
. Within there you will find a wealth of functions for working with variables.
####JsVar
When programming within the internals of Espruino, we will find that a JavaScript variable is represented by a data structure called a JsVar
. This is the internal representation of the variable.
####Construction
The variables have constructors for working with them. For example, jsvNewFromString
will create a new string variable.
We can also create a new object using jspNewObject()
or from
jsvNewWithFlags(JSV_OBJECT)
. We can set properties on the object using jsvObjectSetChild()
.
To create an array we use jsvNewWithFlags(JSV_ARRAY)
.
Data type | Constructor |
---|---|
String | jsvNewFromString |
int | jsvNewFromInteger |
bool | jsvNewFromFromBool |
####Creating an object and adding properties
We can create an object variable with jspNewObject()
. Next we can add properties to that object with
jsvObjectSetChild(parentObject, "<propertyName>", childJsVar)
The return from jsvObjectSetChild
is itself the value of the childJsVar
which means that if we need, we can unlock a dynamically constructed child. For example:
jsvUnLock(
jsvObjectSetChild(
parentObject,
"<propertyName>",
jsvNewFromString("<my value>")
)
);
####Content access
Since a JsVar is a "container" for data, we may wish to access the content of those variables. We can do so using accessor functions such as jsvGetInteger
.
If we are passed a JsVar instance, we often want to know what kind of variable the
object represents. We can determine that with one of the jsvIs<type>
methods.
####References and Locks Part of the concept of variables are references and locks. References are the number of references to the variable from other JavaScript variables. Locks are the number of references from native code. This comes into play when we consider garbage collection. A variable can possibly be freed if it has > 0 references but it can never be freed if it has > 0 locks.
Q - Kolban 2015-10-05: When a variable is created, is it locked?
####Tracing variables
A function called trace()
is supplied that provides a trace of the variables currently in scope. The trace
function can also take a parameter which is a parent variable and it and all its children will be traced.
An example of a line from a trace entry looks as follows:
#6[r1,l2] Name String [2 blocks] "timers" #8[r2,l1] Array(0) [ ]
####Hidden variables
The special variable called globals
is a JavaScript object that serves as the root of all variables. It contains a special entry called "\xFF
" which is used to be the holder of hidden variables. They are hidden as they are otherwise not accessible with prior knowledge.
Among the architected hidden variables we have:
-
history
- History of commands executed -
HttpS
- HTTP Servers -
modules
- Loaded/accessed modules -
net
- Networks -
timers
- Active timers -
watches
- Active interrupt watches
####Iteration Consider an array. It is obvious that an array can be iterated over. It has some number of entries within it and we can imagine getting the 1st, getting the 2nd and so on. However, the same is also true for objects. If we think of an object as a collection of properties then we might ask for the 1st property, the 2nd property and so on. Unlike arrays which have a well defined content order, the order of retrieval of properties in an object is no assured. The best we can say is that we can iterate over all of them. Next think of a String. It is a sequential collection of characters. It makes sense to get the 1st character, the 2nd character and so on and hence it too has a semantic for iteration.
To generalize each of these, Espruino provides a general variable iterator mechanism. When we iterate over something it is important to think of the iteration as having a state. We might want to ask questions like "do we have anything further to retrieve" or "get me the next value". Both of these are iterable concepts.
The JsvIterator
C structure represents such an iteration. For example, given a JsVar object called "myVar" we
can start iterating over it with:
jsvIteratorNew(&myIterator, myVar)
To determine if there is a value to retrieve, we can call:
jsvIteratorHasElement(&myIterator)
To get the current iterator value within the source object, we can call:
jsvIteratorGetValue(&myIterator)
or to get the key for the value:
jsvIteratorGetKey(&myIterator)
to move to the next element in the variable, we can call:
jsvIteratorNext(&myIterator)
finally, when we are finished iterating, we can release resources with:
jsvIteratorFree(&myIterator)
####Invoking functions passed as variables
Consider the notion of a JsVar that represents a function. How can we invoke that function from within our C code? The answer is to use the jsiQueueEvents()
call. Here is an example invoking the function referenced by the JsVar variable called jsGotIpCallback
which takes two parameters:
JsVar *params[2];
params[0] = jsvNewFromInteger(eventType);
params[1] = details;
jsiQueueEvents(NULL, jsGotIpCallback, params, 2);
####Working with objects
To determine if an object contains a named property, execute jsvObjectGetChild
and see what is returned. Remember to jsvUnLock
it when done.
####Working with Strings
It is not uncommon to want to get at the NULL terminated C string value of a String JsVar. To achieve this execute a jsvGetString
with a buffer sufficiently large to hold the result.
Although we commonly think of strings as a sequence of characters meant for human input or output, within Espruino, we should also consider a string as a sequence of un-interpreted bytes. This can be synonymous with a byte array in other languages. With that in mind we have some useful byte manipulation routines including:
- jsvAppendStringBuf - Append a byte array into our existing JsVar String.
- jsvGetString - Retrieve the buffer of bytes.
- jsvGetStringLength - Determine how big is the buffer of bytes.
- jsvSetString - Replace the content of a buffer of bytes. Buffer must be exact same size.
####Working with Arrays We can get the content of an array of data as a contiguous buffer using the macro `JSV_GET_AS_CHAR_ARRAY(dataPtr, dataLen, jsArrayOfData). This is an unusual macro as the 1st and 2nd parameters create variables. For example:
JSV_GET_AS_CHAR_ARRAY(myData, myLen, myJSarray)
will behave as:
char *myData = pointer to bytes of data;
size_t myLen = length of data;
The data does not live beyond the current stack.
If an object is passed in, the object can have special properties to define chunks of data ... for example:
{
data: [255,0,0],
count: 16
}
will create a buffer of the bytes '255', '0', '0' repeated 16 times.
The object containing {data: xxx, count: xxx}
can also appear in other places such as in an array value.
#####Typed Arrays
Note, jsvIsArray
will return false
for typed arrays.
#Key Functions by category ##Objects
- jsvIsObject
- jsvObjectGetChild
- jsvObjectSetChild
- jsvObjectSetChildAndUnLock
- jsvRemoveChild
- jsvRemoveAllChildren
- jsvRemoveNamedChild
##Strings
- jsvAppendString - Append a C NULL terminated string
- jsvAppendStringBuf - Append a fixed length buffer of bytes
- jsvAppendStringVar
- jsvAppendStringVarComplete
- jsvAsString
- jsvCompareString
- jsvGetConstString
- jsvGetString - Retrieve a buffer of bytes
- jsvGetStringIndexOf
- jsvGetStringLength - Determine the length of a buffer of bytes
- jsvGetCharInString
- jsvNewFromStringVar
- jsvNewFromString - Create a JsVar from a string.
- jsvNewStringOfLength
- jsvIsEmptyString
- jsvIsString
- jsvIsStringNumericInt
- jsvIsStringNumericStrict
- jsvIsStringEqualOtStartsWith
- jsvIsStringEqual
- jsvIsStringEqualAndUnlock
- jsvSetString - Replace the content of a buffer of bytes. Buffer must be exact same size.
- jsvStringTrimRight
##Booleans
- jsvGetBool
- jsvIsBoolean
- jsvNewFromBool
##Arrays
- jsvGetArrayIndexOf
- jsvGetArrayItem
- jsvGetArrayItems
- jsvGetArrayLength