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:
- Parallel execution of AAI commands via forkSendAai
- Parallel execution of selected device JS API calls via forkJsApi
- 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:
- Parses a restricted command string
- Verifies the target method exists on the device
- Verifies the resolved member is callable
- 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