Async Function Pointers
Ordinary JavaScript function objects cannot be serialized across Roku
SceneGraph node or task boundaries. AsyncFunctionPointer<T> tells the Hosanna
Compiler to encode an exported module function as a resolvable string pointer.
Use this type only where an API explicitly carries behavior across an
asynchronous boundary. HsFetchOptions.postProcessFunction is the common
example. Programmatic AppConfig fragment callback arrays are another supported
slot: they can contain exported async-function pointers directly, registered
callback names, or both.
Define an exported handler
import type { IHsFetchResponse } from '@hs-src/hosanna-bridge-core/api';
export function processResponse(response: IHsFetchResponse): void {
console.info('Response processed:', response.ok);
}
Then pass the reference to the typed slot:
this.dispatch(Http.Get, {
url: 'https://api.example.com/data',
postProcessFunction: processResponse,
contextData: { requestKey: 'home' }
});
The HTTP command handler attaches contextData to the response and resolves the
pointer before invoking it.
Keep the function serializable
The referenced function must be:
- declared at module scope;
- exported;
- referenced by its identifier;
- callable without captured local variables or a captured
this; and - compatible with the typed callback signature.
These are invalid:
// Inline function: no exported module identity
const options = {
postProcessFunction: (response: IHsFetchResponse) => {
this.consume(response);
}
};
// Bound instance method: captures an object
const options2 = {
postProcessFunction: this.consume.bind(this)
};
The compiler emits HS-1094 for invalid pointer values, and the Hosanna linter
also checks inline functions, bound values, instance members, and indirect
references in AsyncFunctionPointer contexts.
Preserve the signature
The global type is generic:
type RowHandler = AsyncFunctionPointer<(rowId: string, index: number) => void>;
export function handleRow(rowId: string, index: number): void {
console.info(rowId, index);
}
const handler: RowHandler = handleRow;
Using AsyncFunctionPointer<(...) => ...> retains TypeScript checking at the
call site. An unparameterized AsyncFunctionPointer remains available for
legacy APIs but gives weaker checking.
Resolve a pointer
Framework code on the receiving side calls:
const resolved = hs_resolveAsyncFunctionPointer(handler);
resolved('featured', 0);
On Roku the compiler serialized handler as a module-and-function string. The
runtime finds that module function and returns a wrapper with the module context
needed by generated code. On web, the compatibility implementation returns a
function reference.
Do not resolve arbitrary strings. A missing module, missing function, malformed pointer, or non-pointer input fails at runtime.
Runtime limits
- The Roku wrapper accepts zero to five positional arguments. More than five throws.
- Closures and instance state are not serialized.
- Pointer identity depends on an exported module function remaining present in the compiled output.
- An async exported function can return its normal Hosanna promise, but its arguments are subject to the same serialization and arity constraints.
When a callback needs object state, pass serializable context data and look up
shared services or state inside the exported handler. Do not attempt to smuggle
the owning instance through .bind, .call, or a closure.
For a runnable reference, see
rigs/async/PostProcessFunctionRig.ts in hosanna-ui-samples-public.