Skip to content

JSWrapper processing

Gordon Williams edited this page Feb 23, 2017 · 6 revisions

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 include class, 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>.

Clone this wiki locally