Skip to content

Worker Module (Plugins)

This module allows to manage Plugins loaded in your app. Cool, but what are Plugins?

Bubbledesk’s Plugins provides a secure, sandboxed and flexible runtime (a worker) for executing WebAssembly (WASM) plugins within the desktop wrapper.
This allows developers to extend app capabilities and Bubbledesk to release features without forcing new builds.

How to create a new plugin

You can find the guide to develop a plugin here.

Overview

Each worker runs in its own hidden webview window (bd-worker) and executes WASM modules (plugins) inside a Web Worker environment. The runtime isolates every execution, providing:

  • File system sandboxing
  • Automatic timeout and queue limits
  • JSON-based communication
  • Cross-platform consistency (macOS, Windows, Linux)

Workers are managed via the JavaScript bridge at Bubbledesk.worker.

Architecture

The system is composed of three layers:

LayerLanguageResponsibility
FrontendJavaScript or TypeScriptProvides the API under Bubbledesk.worker
Backend HostRust + TauriManages worker lifecycle, WASM validation, job queueing, and communication
Execution Layer (Web Worker)JavaScript + WASMExecutes the loaded WebAssembly module and streams stdout/stderr

All communication between host and worker is event-driven via the Tauri IPC system.

API Reference

MethodParametersReturnsDescription
call(method, payload, timeoutMs?)method: string – The module name (e.g. "math.wasm").
payload: WorkerCallPayload – Object describing the function to run and its arguments.
timeoutMs?: number – Optional execution timeout in milliseconds.
Promise<string>Executes a specific function inside a loaded WASM module. Returns a JSON string representing the module’s output.
status()Promise<boolean>Checks if the worker runtime is ready.
restart()Promise<boolean>Restarts the hidden worker webview, useful if it became unresponsive.
modules.list()Promise<string[]>Lists all installed WASM modules available in the sandbox.
modules.remove(name)name: string – Module filename to delete.Promise<boolean>Removes a module from the sandbox directory.
modules.addFromBytes(name, contents)name: string – Name for the new module.
contents: Uint8Array – Raw WASM bytes to store.
Promise<boolean>Adds a module directly from memory bytes (useful for dynamic uploads).
modules.add(name, maxBytes?)name: string – Filename to assign.
maxBytes?: number – Optional limit for file size.
Promise<boolean>Opens a native file picker to select and store a .wasm file in the sandbox.
clearSandbox()Promise<boolean>Clears all temporary runtime data and cached module state.
paths()Promise<{ externalModules: string; sandbox: string; }>Returns absolute paths to the externalModules and sandbox directories.

Each method is asynchronous and returns a Promise.
The return values are typically JSON strings that must be parsed manually.

Worker Payload

FieldTypeDescription
fnstringThe function name to execute inside the WASM module. This corresponds to the operation defined in the Rust plugin’s dispatcher (e.g., "add", "pow", "sqrt").
argsnumber[]Array of numerical arguments passed to the target function. Both positional and object-style argument parsing are supported in the Rust side.
[key: string]anyOptional additional fields. Custom properties can be included in the payload and will be serialized as part of the JSON input sent to the plugin.

The payload is serialized as JSON and sent to the module’s stdin before execution.
Each module must parse it according to its internal logic and return a compatible JSON response.

Input/Output Standard

The communication protocol is line-delimited JSON:

Input (from host → plugin)

The Bubbledesk sandbox passes JSON via stdin from the payload parameter of Bubbledesk.worker.call().

Example:

js
Bubbledesk.worker.call({
    "module_path": "math.wasm",
    "payload": { "fn": "add", "args": [3, 5] }, // <---- stdin
    "caps": { "timeout_ms": 2000, "memory_mb": 32, "stdout_max_kb": 256 },
    "env": { /* optional */ }
});

Output (from plugin → host)

The plugin must write a single line of JSON to stdout, terminated by \n.

Success:

json
{"ok": true, "value": 8} // this is an example

Error:

json
{"ok": false, "error": "division by zero"} // this is an example

This format is mandatory — the worker will reject malformed or multiline JSON.

Module Lifecycle Example

  1. Add a WASM module

    js
    await Bubbledesk.worker.modules.add("math.wasm");
  2. List installed modules

    js
    const mods = await Bubbledesk.worker.modules.list();
    console.log(mods);
  3. Execute a function

    js
    const res = await Bubbledesk.worker.call("math.wasm", {
      fn: "add",
      args: [2, 4]
    });
    console.log(res); // → {"ok":true,"value":6}
  4. Restart worker runtime

    js
    await Bubbledesk.worker.restart();
  5. Clear sandbox

    js
    await Bubbledesk.worker.clearSandbox();

Security and Sandbox

  • Each plugin executes in its own isolated environment.

    Each job runs in a sandboxed folder (/_sandbox/<jobId>), mapped as / inside the module. Here (and here only) you can read/write files with the plugin.

  • No network access or external FS access is allowed.
  • Max 64 concurrent pending jobs.
  • Input limited to 1 MB per call.
  • WASM modules must start with the standard \0asm magic bytes.

Directory Layout

DirectoryPurpose
/_external_modules/Holds installed WASM modules
/_sandbox/<jobId>Temporary runtime area, wiped at startup

Example Workflow

js
await Bubbledesk.worker.modules.add("math.wasm");
const res = await Bubbledesk.worker.call("math.wasm", {
  fn: "pow",
  args: [2, 10]
});
console.log(JSON.parse(res).value); // 1024

Keywords References

  • Plugin = WASM Module
  • Worker = Isolated runtime where the plugins run
  • WASM = WebAssembly

New Plugin

You can find the guide to develop a plugin here.

WebAssembly (WASM)

WebAssembly (WASM) is a portable binary format that enables high-performance code — written in languages (like Rust, C, or C++) — to run safely inside browsers or sandboxed runtimes such as Tauri + browser web worker.

Notes

NOTES

  • Keep functions pure and deterministic, without external side effects.
  • Do not use network: it is blocked by the sandbox.
  • Avoid extra stdout/stderr: only the final JSON output should be printed.
  • All modules must follow the stdin/stdout JSON protocol strictly. Multi-line, non-JSON, or binary outputs will be discarded.

WARNING

Avoid infinite loops or blocking operations inside your WASM module — they will trigger a timeout and the worker will be restarted.

All rights reserved.