forkjoin

Parallel device execution helpers built on top of the virtual-thread submitter
from module:sigma/vt. This module is designed for batch execution across
multiple device workers and provides:

  1. Parallel execution of AAI commands via forkSendAai
  2. Parallel execution of selected device JS API calls via forkJsApi
  3. Aggregation of asynchronous results into ArrayOutput format via
    collectResults

The module avoids using {@code eval()} for dynamic device API execution.
Instead, it performs a controlled parse of command strings in the form:

methodName(arg1, arg2, ...)

and safely dispatches them to the target device instance.

Supported argument literal types for string commands:

  • number → 123, -1, 3.14
  • boolean → true, false
  • null → null
  • undefined → undefined
  • quoted string → "abc", 'abc'

Not supported in command strings:

  • object literals → { a: 1 }
  • array literals → [1, 2]
  • arbitrary JS → alert(1), foo.bar(), x + y

This restriction is intentional and improves safety, predictability, and
compatibility in embedded JavaScript runtimes such as Rhino/RingoJS-like
environments.

Methods

(static) __getLastErrorNow(dev) → (nullable) {string}

Reads the current last-error string from a device as soon as possible.

This helper is typically used after a failed or null-returning AAI call to
retrieve device-side diagnostic information.

Parameters:
Name Type Description
dev Object

The device instance exposing {@code sendAai()}.

Returns:

Returns the last error string when available; otherwise {@code null}.

Type
string

(static) collectResults(workers, futures, timeoutSecondsnullable) → {*}

Waits for all futures and merges them into an ArrayOutput return object.

Each future is expected to resolve to an object of the form:

{ value: *, error: ?string }

If a future throws, times out, or otherwise fails while waiting, the exception
string is stored as the error for the corresponding device.

Parameters:
Name Type Attributes Description
workers Array.<Object>

Worker list. Each worker must contain a {@code device} instance.

futures Array.<Object>

Future list produced by forkSendAai or forkJsApi.

timeoutSeconds number <nullable>

Per-future timeout in seconds. Defaults to {@code 30}.

Returns:

Returns the value of {@code xao.getReturn()}, preserving the existing
ArrayOutput integration contract used by the surrounding system.

Type
*

(static) executeOnDevice(dev, commandStr) → {*}

Executes a parsed device method safely without using {@code eval()}.

This function:

  1. Parses a restricted command string
  2. Verifies the target method exists on the device
  3. Verifies the resolved member is callable
  4. Invokes the method with the parsed arguments

Example:

  • {@code executeOnDevice(dev, "click(100, 200)")}
  • {@code executeOnDevice(dev, "pgDn()")}
Parameters:
Name Type Description
dev Object

Target device instance.

commandStr string

Restricted command string in the form {@code methodName(...)}.

Throws:

Throws if:

  • the command format is invalid
  • the method does not exist
  • the target member is not callable
  • the arguments contain unsupported literals
Type
Error
Returns:

Returns the original result of the device method invocation.

Type
*

(static) forkJsApi(workers, cmd) → {Array.<Object>}

Executes a device JavaScript API command on all workers in parallel.

The command must be a restricted string in the form:

methodName(...)

Example:

  • {@code "click(100, 200)"}
  • {@code "pgDn()"}
  • {@code "inputText('hello')"}

Internally the command is parsed and dispatched without using {@code eval()}.

Parameters:
Name Type Description
workers Array.<Object>

Worker list. Each worker must contain a {@code device} instance.

cmd string

Restricted device command string.

Returns:

Returns an array of futures. Each future resolves to:
{@code { value: *, error: ?string }}.

Type
Array.<Object>

(static) forkSendAai(workers, aaiObj) → {Array.<Object>}

Executes the same AAI request on all workers in parallel.

Each worker is expected to have a {@code device} property. Execution is
submitted through the virtual-thread helper and returns one future per worker.

Result normalization rules:

  • If {@code sendAai()} returns {@code null}, the function attempts to read the
    device's last error and returns it as an error payload.
  • If the return value is an object containing {@code retval}, that field is
    automatically unwrapped.
  • Any thrown exception is captured and converted into a string error.
Parameters:
Name Type Description
workers Array.<Object>

Worker list. Each worker must contain a {@code device} instance.

aaiObj Object

The AAI command object passed directly to {@code dev.sendAai(aaiObj)}.

Returns:

Returns an array of futures. Each future resolves to:
{@code { value: *, error: ?string }}.

Type
Array.<Object>

(static) parseCommand(commandStr) → {Object}

Parses a restricted device command string into a method name and argument list.

Accepted syntax:

  • {@code click(100, 200)}
  • {@code pgDn()}
  • {@code inputText("hello")}

Security properties:

  • Only a simple identifier is allowed as method name
  • Only a single top-level call expression is allowed
  • Arguments are parsed as restricted literals, not executable code
Parameters:
Name Type Description
commandStr string

The raw command string.

Throws:

Throws if the command format is invalid or contains unsupported syntax.

Type
Error
Returns:

Parsed method name and evaluated argument values.

Type
Object

(static) parseLiteral(token) → {*}

Converts a single raw argument token into a safe JavaScript value.

Supported token formats:

  • numeric literals: {@code 1}, {@code -2}, {@code 3.14}
  • booleans: {@code true}, {@code false}
  • null: {@code null}
  • undefined: {@code undefined}
  • quoted strings: {@code "abc"}, {@code 'abc'}
Parameters:
Name Type Description
token string

Raw argument token.

Throws:

Throws if the token is not a supported literal.

Type
Error
Returns:

Parsed JavaScript value.

Type
*

(static) splitArguments(argsStr) → {Array.<string>}

Splits a raw argument string into top-level argument tokens.

This parser supports commas outside quoted strings and handles escaped quote
characters inside quoted string literals.

Examples:

  • {@code "100, 200"} → ["100", "200"]
  • {@code "'a,b', 123"} → ["'a,b'", "123"]
  • {@code "\"hello\", true, null"} → [""hello"", "true", "null"]

This function intentionally does not support nested objects, arrays, or
arbitrary JavaScript expressions.

Parameters:
Name Type Description
argsStr string

The raw substring inside the parentheses.

Throws:

Throws if the argument string contains unterminated quotes.

Type
Error
Returns:

A list of trimmed raw argument tokens.

Type
Array.<string>

(static) unescapeQuotedString(s) → {string}

Unescapes a quoted JavaScript-like string literal.

Supported escape sequences:

  • {@code \\}
  • {@code \"}
  • {@code \'}
  • {@code \n}
  • {@code \r}
  • {@code \t}
Parameters:
Name Type Description
s string

String content without outer quotes.

Returns:

The unescaped string value.

Type
string