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

OptionDefaultDescription
dirLoad every *.js in this directory, sorted by filename. POSIX only.
configPath to a list file naming the scripts to load (see below).
scriptLoad a single script file.
memory_limit67108864Engine heap cap in bytes (64 MiB).
stack_limit1048576JavaScript stack cap in bytes (1 MiB).
time_limit1000Per-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.