ScriptHost.h header

#include <ew/app/ScriptHost.h>

Namespace ew::app

ScriptHost class

class ew::app::ScriptHost

A sandboxed JavaScript host for user macros and automation (DESIGN §4.16 "embedded scripting" / §6.11 extensibility host; the language is DECIDED as JavaScript via Qt's QJSEngine, §9/§482).

It evaluates a script string against a persistent QJSEngine and returns its result or a clear error, never throwing out to the caller. A per-run time budget interrupts a runaway script (an accidental infinite loop) so a bad macro cannot hang the application. Host objects registered with registerGlobal() – most importantly the project "world" bridge layered on top – become global objects the script can call, so a macro can read and (through the undoable command stack) modify the project. QJSEngine already sandboxes scripts from the filesystem, network, and process, so a script can only reach what the host explicitly exposes.

The engine is thread-affine: construct and call a ScriptHost on one thread (the GUI thread for the desktop console), where any registered world bridge also lives, so a script's mutations run on the thread that owns the project. Globals persist across evaluate() calls on the same host, so a later macro can build on definitions an earlier one made.

Members

ew::app::ScriptHost::ScriptHost()

Constructs a host with a fresh, empty JavaScript engine.

ew::app::ScriptHost::~ScriptHost()

Destroys the host and its engine.

ew::app::ScriptHost::ScriptHost(const ScriptHost &)=delete

Not copyable.

ScriptHost & ew::app::ScriptHost::operator=(const ScriptHost &)=delete

Not copyable.

ew::app::ScriptHost::ScriptHost(ScriptHost &&)=delete

Not movable.

ScriptHost & ew::app::ScriptHost::operator=(ScriptHost &&)=delete

Not movable.

ScriptResult ew::app::ScriptHost::evaluate(const QString &script)

Evaluates script and returns its result as text, or an error. A syntax error, an uncaught thrown value, or a run that exceeds the time budget (see setTimeoutMs) all come back as ScriptResult{ok=false, error=...} rather than an exception. The engine is reset to a non-interrupted state before each run, so a host stays usable after a timeout.

void ew::app::ScriptHost::registerGlobal(const QString &name, QObject *object)

Exposes object to scripts under the global name name: its Q_INVOKABLE methods and Q_PROPERTYs become a JavaScript object at globalThis[name]. The host does NOT take ownership – object must outlive the host (or be re-registered). A no-op for a null object or an empty name.

void ew::app::ScriptHost::setTimeoutMs(int timeoutMs)

Sets the runaway time budget in milliseconds: a single evaluate() whose script runs longer is interrupted and reported as an error. Defaults to 5000 ms. A non-positive value disables the guard (use only for trusted callers) – an infinite loop then hangs the calling thread.

int ew::app::ScriptHost::timeoutMs() const

The current runaway time budget in milliseconds (see setTimeoutMs).

ScriptResult struct

struct ew::app::ScriptResult

The outcome of running a script through a ScriptHost: whether it completed without error, its result rendered as text (the value the script evaluated to), and a human-readable error message when it failed.

Members

bool ew::app::ScriptResult::ok = false

True when the script ran to completion without throwing (and without being interrupted).

QString ew::app::ScriptResult::value

The script's result as text – the string form of the value the last statement evaluated to, or empty when that value is undefined. Meaningful only when ok is true.

QString ew::app::ScriptResult::error

A human-readable error ("Name: message (line N)") when ok is false: a syntax error, a thrown/uncaught runtime error, or the interruption of a script that ran past the timeout.

QString ew::app::ScriptResult::consoleOutput

Everything the script printed via console.log/info/debug/warn/error during this run, one message per line (warnings/errors prefixed [warn] /[error] ), with no trailing newline. Empty when the script printed nothing. Captured whether or not ok is true, so a macro that logs progress before throwing still shows its output.

bool operator==(const ScriptResult &, const ScriptResult &)=default

Results compare equal when every field matches.