-
-
Notifications
You must be signed in to change notification settings - Fork 751
JSWrapper processing
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 in-line code documentation of jswrap processing can be found in scripts\common.py
and should be consulted and referenced as the master source of truth.
When we build Espruino, we are writing a set of C language functions. In our JavaScript world, we may wish to define global JavaScript objects, functions, properties and other components which map to these C language capabilities.
For example, imagine we have a fantastic C language piece of code that we wish to expose as a JavaScript function call. In JavaScript, I want to code:
var x = foobar("My Name");
such that we will invoke:
JsVar *fooBar(JsVar *name) {
// Code here that implements foobar
}
How do we inform Espruino that such a function is now part of the environment?
The answer is we need to annotate the source code of functions we wish to expose. Within the source code we define C language block comments that have a particular structure. During the Espruino build process, we run a processor (supplied by Espruino) that searches the C code looking for such definitions. These are then used to generate code linkages that result in the honoring of the semantics defined in the comments.
The general structure of the comment look as follows:
/*JSON{
"type": "staticmethod",
"class": "ESP8266WiFi",
"name": "setAutoconnect",
"generate": "jswrap_ESP8266WiFi_setAutoconnect",
"generate_full": "<some code here>",
"params": [
["autoconnect","JsVar","True if we wish to autoconnect."]
],
"return": ["JsVar","A boolean representing our auto connect status"],
"return_object": "Restart"
}*/
All comments begin with "JSON{
" and end with a closing/matching "}
". The format of the content conforms to JSON data encoding.
It is not yet known the meanings and values of these nor which are optional vs mandatory nor whether there are additional settings not yet discovered.
-
type
- Values seen includeclass
,staticmethod
,staticproperty
,method
,property
,function
,variable
,library
,event
,idle
,init
,kill
.
The optional properties params
, return
and return_object
are used to auto generate documentation. The params
is an array of parameters where each parameter is itself as positional array of format:
["<Parameter Name>", "<Variable type>", "<Description>"]
The variable type can be any one of the following:
JsVar
pin
float
- ... others ...
The return
is a property that describes the return type for the wrapper used for documentation generation. It is an array of the format:
["<Variable Type>", "<Description>"]
The return_object
is used to provide assistance to the auto complete function in the Web IDE. It has a value which is a simple string that names the object type returned by this wrapper.
In addition, any comments in the comment block following the close of the JSON will be included in the auto generated documentation for the wrapper.
When the wrapper processor has completed running over the source files that contain wrappers, a new file is generated called gen\jswrapper.c
. It is this file that provides the underlying linkage to the JavaScript environment. The implementation of the wrapper processor can be found in scripts\build_jswrapper.py
.
####type = class
A definition type of class
defines a new class type. When defined, the class
property must also be supplied to define the name of the class to be defined. For example:
/*JSON{
"type": "class",
"class": "MyClass"
}*/
Will create a new JavaScript class type called "MyClass
". A class definition may be used in other definitions to add things such as methods and properties.
####type = staticmethod
A definition type of staticmethod
exposes a method that is not instance specific but yet is scoped to a class. When defined, the class
, name
and generate
properties must also be supplied. For example:
/*JSON{
"type": "staticmethod",
"class": "MyClass",
"name": "myStaticMethod",
"generate": "jswrap_myStaticMethod"
}*/
Since a static method must belong to a JavaScript object, we name the object type that owns it with the class
property. The name
property provides the name of the function that can be called from JavaScript. The generate
property names the C language implementation function that will be invoked when the JavaScript method is called.
To invoke such a function, we supply the name of the class that owns the method and the function name itself.
var x = MyClass.myStaticMethod();
####type = staticproperty
A definition type of staticproperty
exposes a property that is not instance specific but yet is scoped to a class. This definition requires that the class
, name
, and one of generate
or generate_full
be supplied.
/*JSON{
"type": "staticproperty",
"class": "MyClass",
"name": "myProperty",
"generate": "jswrap_myProperty"
}*/
####type = method
This modifier defines a function that can be invoked on an instance of the class. When invoked, the corresponding C language function will be called.
This definitions requires that the class
, name
and generate
properties also be present. For example:
/*JSON{
"type": "method",
"class": "MyClass",
"name": "myMethod",
"generate": "jswrap_myMethod"
}*/
To invoke the function, we need an instance of the class. For example:
var myInstance = new MyClass();
var x = myInstance.myMethod();
####type = property
####type = function
A definition type of function
exposes a global function that is not instance specific.
This definition requires that name
and generate
properties also be present. For example:
/*JSON{
"type": "function",
"name": "myFunction",
"generate": "jswrap_myFunction"
}*/
The function defined here can be invoked without an object reference.
####type = variable
This modifier defines a global variable. This definition requires that name
and generate
also be supplied.
/*JSON{
"type": "variable",,
"name": "myVariableName",
"generate": "jswrap_myVariableName"
}*/
####type = library
A definition type of library
defines a new class that can be loaded with a JavaScript require
mechanism. This definition requires that the class
property be supplied:
/*JSON{
"type": "library",
"class": "MyLibraryClass"
}*/
####type = event
This modifier defines that an event can be emitted from this class.
This definition requires that the class
and name
properties also be present. The name
defines the name of the event that can be generated.
/*JSON{
"type": "event",
"class": "MyClass",
"name": "opened"
}*/
####type = idle
This modifier defines a function that will be invoked during idle processing. This definition requires that the generate
property also be present.
/*JSON{
"type": "idle",
"generate": "jswrap_idleMyService"
}*/
####type = init
This modifier defines a function that will be invoked during initialization. This definition requires that the generate
property also be present.
/*JSON{
"type": "init",
"generate": "jswrap_initMyService"
}*/
####type = kill
This modifier defines a function that will be invoked during destruction. This definition requires that the generate
property also be present.
/*JSON{
"type": "kill",
"generate": "jswrap_killMyService"
}*/
##Designing and coding wrapped functions Since wrapped functions need global exposure, it is recommended that care be taken that there be no naming collisions. A naming mechanism used by Espruino is required to be followed.
File names that contain wrapping definitions must be named jswrap_<name>
.
Functions exposed by wrapping should be named jswrap_<ClassName>_<methodName>
.