mod_javascript
Run JavaScript as hub plug-ins. Part of the bundled plug-ins.
mod_javascript embeds the QuickJS engine and runs .js files as uhub
plug-ins. Scripts register handlers on a global uhub object and act on users
through the objects they are handed — no compiler, and no plug-in ABI to match.
This page covers loading and configuring the plug-in. The scripting API itself — events,
verdicts, the user object and worked examples — is documented on the
JavaScript plug-in API page.
New in uhub 0.8.0, and optional: it is not built unless the hub is configured with JavaScript support.
Building
The engine (quickjs-ng) is a git submodule pinned to a release. Fetch it, then enable the option:
git submodule update --init third_party/quickjs
cmake -DJAVASCRIPT_SUPPORT=ON .. # or: zig build -Djavascript=true
Loading
# every *.js in a directory, loaded in filename order
plugin /var/lib/uhub/mod_javascript.so "dir=/etc/uhub/js.d"
# a list file naming scripts and their individual options
plugin /var/lib/uhub/mod_javascript.so "config=/etc/uhub/javascript.conf"
# a single script
plugin /var/lib/uhub/mod_javascript.so "script=/etc/uhub/welcome.js motd=Hi %n"
Configuration
| Option | Default | Description |
|---|---|---|
dir | — | Load every *.js in this directory, sorted by filename. POSIX only. |
config | — | Path to a list file naming the scripts to load (see below). |
script | — | Load a single script file. |
memory_limit | 67108864 | Engine heap cap in bytes (64 MiB). |
stack_limit | 1048576 | JavaScript stack cap in bytes (1 MiB). |
time_limit | 1000 | Per-callback wall-clock budget in milliseconds. A handler that exceeds it is interrupted. |
dir, config and script may be combined and repeated. Any
other key=value on the plug-in line is passed to every script as
uhub.config — that is how motd=Hi %n above reaches
uhub.config.motd.
The script list file
config= reads one script per line: a path, then optional per-script options.
# starts a comment and blank lines are ignored.
# /etc/uhub/javascript.conf
welcome.js motd=Welcome to the hub, %n!
chat_only.js
flood.js grace=3
Relative paths resolve against the list file's own directory. The per-script options become
that script's uhub.config and override anything set on the plug-in line, so the
same script can be loaded twice with different settings.
Behaviour
Each script runs in its own JavaScript context — its own globals and its own
uhub.config — sharing a single engine instance. For an interceptable event the
scripts run in load order until one returns a verdict other than uhub.DEFAULT;
notification events reach all of them.
A script that fails to parse, or throws while being evaluated, prevents the hub from
starting and the error is logged. An exception thrown later, inside a handler, is
logged and treated as DEFAULT — the hub keeps running.
Scripts are read once at startup; editing a file takes effect on the next restart.
Sandbox
Scripts get the uhub API and nothing else. QuickJS's std and
os modules are not exposed, so a script has no filesystem, network or process
access. Every callback runs under the time_limit watchdog so a runaway loop cannot
wedge the single-threaded hub, the engine is bounded by memory_limit and
stack_limit, and script files get the same integrity check as .so
plug-ins — a group- or world-writable file is refused.
Examples
JavaScript ports of three bundled plug-ins ship in doc/js/ of the source tree:
welcome.js (mod_welcome),
chat_only.js (mod_chat_only) and
flood.js (mod_flood), plus an example
javascript.conf. More recipes are on the
JavaScript plug-in API page.