function callToJs()

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(",")})`;
  }
}