in packages/sqrl/src/js/SqrlJs.ts [228:275]
function callToJs(expr: CallExpr, state: JsState): JsExpr {
const funcProps = state.instance.getProps(expr.func);
const exprJs = expr.exprs.map((item) => exprToJs(item, state));
if (funcProps.callbackArgs === true) {
invariant(
exprJs.length >= 1 && exprJs[0] === "this",
"Expected function taking promiseArgs to receive state as first argument"
);
const exprCallbackJs = exprJs.slice(1).map((expr) => {
return `()=>${PromiseJsExpr.ensure(expr)}`;
});
return new PromiseJsExpr(
`functions.${expr.func}(this, [${exprCallbackJs.join(",")}])`
);
}
if (funcProps.promiseArgs === true) {
// Special behavior if we have a function that expects its arguments as
// promises. It should require 'state', and then just ensure remaining
// arguments are all promises.
invariant(
exprJs.length >= 1 && exprJs[0] === "this",
"Expected function taking promiseArgs to receive state as first argument"
);
const promiseArgs = exprJs.slice(1).map((e) => PromiseJsExpr.ensure(e));
return new PromiseJsExpr(
`functions.${expr.func}(this,${promiseArgs.join(",")})`
);
}
const hasPromise = exprJs.some((expr) => expr instanceof PromiseJsExpr);
if (hasPromise) {
if (exprJs.length === 1) {
return new PromiseJsExpr(
`${PromiseJsExpr.ensure(exprJs[0])}.then(functions.${expr.func})`
);
} else {
return new PromiseJsExpr(
`${PromiseJsExpr.ensure(exprJs)}.spread(functions.${expr.func})`
);
}
} else if (funcProps.async) {
return new PromiseJsExpr(`functions.${expr.func}(${exprJs.join(",")})`);
} else {
return `functions.${expr.func}(${exprJs.join(",")})`;
}
}