~aperezdc/kiln

4c8606a40a9e8dc64637e482e6cc42cad54469ea — Adrian Perez de Castro 4 years ago fbd377e
Add README.md file
1 files changed, 247 insertions(+), 0 deletions(-)

A README.md
A README.md => README.md +247 -0
@@ 0,0 1,247 @@
Kiln
====

Kiln is an utility library to ease the development of modules for
[JavaScriptCore][] (JSC) with a focus on providing mechanisms for embedders
to dynamically load native modules which use the [JSC GLib API][] to
provide bindings.

Kiln can be used with the following JSC implementations:

- The `javascriptcoregtk-4.0` library provided by the [WebKitGTK][] port.
- The `wpe-webkit-1.0` library provided by the [WPE WebKit][] port.

[JavaScriptCore]: https://trac.webkit.org/wiki/JavaScriptCore
[JSC GLib API]: https://webkitgtk.org/reference/jsc-glib/stable/index.html
[WebKitGTK]: https://webkitgtk.org
[WPE WebKit]: https://wpewebkit.org

A kiln is a large oven for making bricks. One could think about each module
loaded using Kiln as a small brick used to make a complete building.

1. [Building](#building)
2. [Library Usage](#usage)
   1. [Built-in modules](#built-in-modules)
   2. [Plug-in modules](#plug-in-modules)
3. [Utilities](#utilities)
   1. [Loader Module](#loader-module)
   2. [WebExtension](#webextension)
   3. [JSC Shell](#jsc-shell)
   4. [GTK shell](#gtk-shell)
5. [Licensing](#licensing)


Building
--------

Kiln uses [Meson](https://mesonbuild.com) as its build system. The following
options are available:

| Option              | Description |
|:--------------------|:------------|
| `-Dwebkit_port=gtk` | Use the WebKitGTK JSC library. |
| `-Dwebkit_port=wpe` | Use WPE WebKit as the JSC library. |
| `-Djsc_shell=…`     | Whether to build the `kn-jsc` program, a JSC shell that can run JavaScript making use of Kiln plug-in modules, or run as an interactive interpreter. Needs [libedit](https://thrysoee.dk/editline). |
| `-Dgtk_shell=…`     | Whether to build the `kn-gtk` program, a bare-bones application which embeds a web view and can make use of the Kiln [WebExtension](#webextension). This is only available when building with `-Dwebkit_port=gtk` and is mostly useful for development. |
| `-Dweb_extension=…` | Whether to build the Kiln [WebExtension](#webextension). |
| `-Ddocumentation=…` | Whether to build the Kiln manual using [HotDoc](https://hotdoc.github.io/). |

Library Usage
-------------

Once you have a [JSCContext][] created (either manually, or by WebKit itself as
part of a web view) a `KilnLoader` instance can be created to load modules
for that context:

```c
g_autoptr(JSCContext) context = jsc_context_new ();
g_autoptr(KilnLoader) loader = kiln_loader_new (context);
```

[JSCContext]: https://webkitgtk.org/reference/jsc-glib/stable/JSCContext.html

Modules can then be added to the loader in two ways: by instructing the loader
to look for loadable shared libraries (plug-in modules) in the file system, or
by manually specifying the module properties (name, initialization function,
etc.).

### Built-in Modules

Manually specifying modules allows providing bindings for built-in
functionality without the need for building and installing plug-ins. Built-in
modules need to be registered with `kiln_loader_add_module()` before trying to
open them. The following defines a module consisting of a single function
to be exposed to JavaScript:

```c
/* Implementation of the native function. */
static void
builtin_print (JSCValue *value)
{
    g_autofree char *value_string = jsc_value_to_string (value);
    printf ("%s\n", value_string);
}

/* Function that initializes (opens) the module. */
static JSCValue*
open_builtin_print (JSCContext *context, GError **error, void *userdata)
{
    /*
     * If the module cannot be initialized, return NULL and set the GError.
     * The "userdata" parameter will be specified when opening the module.
     * The returned value are the module contents.
     */
    return jsc_value_new_function (context,
                                   "print",
                                   G_CALLBACK (builtin_print),
                                   NULL,            /* userdata */
                                   NULL,            /* destroy_notify */
                                   G_TYPE_NONE,     /* return type */
                                   1,               /* num. of parameters */
                                   JSC_TYPE_VALUE); /* parameter type */
}
```

With the above in place, the module can be registered with the loader:

```c
g_autoptr(GError) error = NULL;
if (!kiln_loader_add_module (loader,
                             "print",            /* module name */
                             open_builtin_print, /* module init function */
                             NULL,               /* userdata */
                             &error))
    g_error ("Cannot register module: %s", error->message);
```

Finally, the module can be “opened” to make the functionality available to
the JavaScript world:

```c
if (!kiln_loader_open_module (loader,
                              "print", /* module name */
                              &error))
    g_error ("Cannot open module: %s", error->message);
```

This last step takes the value returned from the module initialization
function and assigns it to an attribute in the JS global object named
after the module:

```javascript
// Prints "number" using the "builtin_print()" C function.
print(typeof (1 + Number.parseInt("41")));
```


### Plug-in Modules

Plug-ins are loadable shared libraries (on ELF systems, a `.so` file) that
contain a public function named `kiln_<name>_module_open`, where `<name>`
is the module name that it implements, and the signature is as follows:

```
JSCValue* kiln_<name>_module_open (JSCContext*, GError**, void*);
```

This means that the `open_builtin_print()` function from the [built-ins
example](#built-in-modules) could be moved into its own file and renamed
as follows to make it into a loadable plug-in:

```c
G_MODULE_EXPORT JSCValue*
kiln_print_module_open (JSCContext *context, GError **error, void *userdata)
```

This module must be built on its own and installed as `lib<name>.so`, in the
case of the example `print` module:

```
$CC -shared -o libprint.so print.c $(pkg-config wpe-webkit-1.0 --libs --cflags)
```

Once the loadable plug-in module is built, the loader can be taught where
to look for loadable modules:

```c
/* Use the current directory for finding plug-in modules. */
kiln_loader_append_path (loader, ".");

/* Open it. This is exactly the same as for built-in modules. */
if (!kiln_loader_open_module (loader, "print", &error))
    g_error ("Cannot load module: %s", error->message);
```

Note that module names must be unique: if a built-in module was already
added, a loadable one with the same name will not be used.


Utilities
---------

### Loader Module

Using the `kiln_loader_bootstrap` function will register the loader itself in
the `JSCContext` as a module, making it possible to change the module search
paths and load further modules from JavaScript. In the native side, the
following will make the JavaScript module available under the `kiln` name:

```c
kiln_loader_bootstrap (loader, "kiln", NULL);
kiln_loader_open_module (loader, "kiln", NULL);
```

Then, on the JavaScript side:

```javascript
kiln.appendPath("path/to/modules/");
const console = kiln.loadModule("console");
console.log("This was loaded dynamically");
```

### WebExtension

Kiln provides a
[Web Extension](https://webkitgtk.org/reference/webkit2gtk/stable/ch02.html)
which allows to load Kiln modules to be used by content loaded in a
`WebKitWebView`. The built `libkiln-webkit-*.so` library must be installed
in a location where your application [is configured][wkwextdir] to look
for WebExtensions.

The WebExtension is built when configuring the build with
`-Dweb_extension=enabled`.

[wkwextdir]: https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebContext.html#webkit-web-context-set-web-extensions-directory


### JSC Shell

A simple JSC shell named `kn-jsc` is included with Kiln and built when
configuring the build with `-Djsc_shell=enabled`. This shell can load
Kiln plug-in modules, run JavaScript scripts in batch mode, and also
be used as an interactive REPL.

The shell expects a `console` module to be available in the module
path. The implementation can be found in the `modules/` subdirectory and is
built by default. Use `kn-jsc --help` for more information on how to specify
module paths, or to disable this “built-in” (in the sense of always
available).


### GTK Shell

The GTK shell is built when configuring the build with `-Dgtk_shell=enabled`
_and_ `-Dwebkit_port=gtk`. The program is called `kn-gtk`, and is most useful
when the [WebExtension](#webextension) is also built to make it able to
load Kiln modules. The program consists of bare bones browser window
which opens the URL specified in the command line. Check `kn-gtk --help`
for more information on how to specify module paths and the location where the
WebExtension is located.


Licensing
---------

Kiln is distributed under the terms of the [MIT
license](https://opensource.org/licenses/MIT).