void t_js_generator::generate_process_function()

in compiler/cpp/src/thrift/generate/t_js_generator.cc [1486:1686]


void t_js_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
  if (gen_es6_) {
    indent(f_service_) << "process_" + tfunction->get_name() + " (seqid, input, output) {" << '\n';
  } else {
    indent(f_service_) << js_namespace(tservice->get_program()) << service_name_
                      << "Processor.prototype.process_" + tfunction->get_name()
                          + " = function(seqid, input, output) {" << '\n';
  }
  if (gen_ts_) {
    indent_up();
    f_service_ts_ << ts_indent() << "process_" << tfunction->get_name() << "(seqid: number, input: thrift.TProtocol, output: thrift.TProtocol): void;" << '\n';
    indent_down();
  }

  indent_up();

  string argsname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name() + "_args";
  string resultname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name()
                      + "_result";

  indent(f_service_) << js_const_type_ << "args = new " << argsname << "();" << '\n' << indent()
             << "args[Symbol.for(\"read\")](input);" << '\n' << indent() << "input.readMessageEnd();" << '\n';

  // Generate the function call
  t_struct* arg_struct = tfunction->get_arglist();
  const std::vector<t_field*>& fields = arg_struct->get_members();
  vector<t_field*>::const_iterator f_iter;

  // Shortcut out here for oneway functions
  if (tfunction->is_oneway()) {
    indent(f_service_) << "this._handler." << tfunction->get_name() << "(";

    bool first = true;
    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
      if (first) {
        first = false;
      } else {
        f_service_ << ", ";
      }
      f_service_ << "args." << (*f_iter)->get_name();
    }

    f_service_ << ");" << '\n';
    indent_down();

    if (gen_es6_) {
      indent(f_service_) << "}" << '\n';
    } else {
      indent(f_service_) << "};" << '\n';
    }
    return;
  }

  // Promise style invocation
  indent(f_service_) << "if (this._handler." << tfunction->get_name()
             << ".length === " << fields.size() << ") {" << '\n';
  indent_up();

  if (gen_es6_) {
    indent(f_service_) << "new Promise((resolve) => resolve(this._handler." << tfunction->get_name() << ".bind(this._handler)(" << '\n';
  } else {
    string maybeComma = (fields.size() > 0 ? "," : "");
    indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name() << ".bind(this._handler)"
                       << maybeComma << '\n';
  }

  indent_up();
  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
    string maybeComma = (f_iter != fields.end() - 1 ? "," : "");
    indent(f_service_) << "args." << (*f_iter)->get_name() << maybeComma << '\n';
  }
  indent_down();

  if (gen_es6_) {
    indent(f_service_) << "))).then(result => {" << '\n';
  } else {
    indent(f_service_) << ").then(function(result) {" << '\n';
  }

  indent_up();
  f_service_ << indent() << js_const_type_ << "result_obj = new " << resultname << "({success: result});" << '\n'
             << indent() << "output.writeMessageBegin(\"" << tfunction->get_name()
             << "\", Thrift.MessageType.REPLY, seqid);" << '\n' << indent()
             << "result_obj[Symbol.for(\"write\")](output);" << '\n' << indent() << "output.writeMessageEnd();" << '\n'
             << indent() << "output.flush();" << '\n';
  indent_down();

  if (gen_es6_) {
    indent(f_service_) << "}).catch(err => {" << '\n';
  } else {
    indent(f_service_) << "}).catch(function (err) {" << '\n';
  }
  indent_up();
  indent(f_service_) << js_let_type_ << "result;" << '\n';

  bool has_exception = false;
  t_struct* exceptions = tfunction->get_xceptions();
  if (exceptions) {
    const vector<t_field*>& members = exceptions->get_members();
    for (auto member : members) {
      t_type* t = get_true_type(member->get_type());
      if (t->is_xception()) {
        if (!has_exception) {
          has_exception = true;
          indent(f_service_) << "if (err instanceof " << js_type_namespace(t->get_program())
                             << t->get_name();
        } else {
          f_service_ << " || err instanceof " << js_type_namespace(t->get_program())
                     << t->get_name();
        }
      }
    }
  }

  if (has_exception) {
    f_service_ << ") {" << '\n';
    indent_up();
    f_service_ << indent() << "result = new " << resultname << "(err);" << '\n' << indent()
               << "output.writeMessageBegin(\"" << tfunction->get_name()
               << "\", Thrift.MessageType.REPLY, seqid);" << '\n';

    indent_down();
    indent(f_service_) << "} else {" << '\n';
    indent_up();
  }

  f_service_ << indent() << "result = new "
                            "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN,"
                            " err.message);" << '\n' << indent() << "output.writeMessageBegin(\""
             << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << '\n';

  if (has_exception) {
    indent_down();
    indent(f_service_) << "}" << '\n';
  }

  f_service_ << indent() << "result[Symbol.for(\"write\")](output);" << '\n' << indent()
             << "output.writeMessageEnd();" << '\n' << indent() << "output.flush();" << '\n';
  indent_down();
  indent(f_service_) << "});" << '\n';
  indent_down();
  // End promise style invocation

  // Callback style invocation
  indent(f_service_) << "} else {" << '\n';
  indent_up();
  indent(f_service_) << "this._handler." << tfunction->get_name() << "(";

  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
    f_service_ << "args." << (*f_iter)->get_name() << ", ";
  }

  if (gen_es6_) {
    f_service_ << "(err, result) => {" << '\n';
  } else {
    f_service_ << "function (err, result) {" << '\n';
  }
  indent_up();
  indent(f_service_) << js_let_type_ << "result_obj;" << '\n';

  indent(f_service_) << "if ((err === null || typeof err === 'undefined')";
  if (has_exception) {
    const vector<t_field*>& members = exceptions->get_members();
    for (auto member : members) {
      t_type* t = get_true_type(member->get_type());
      if (t->is_xception()) {
        f_service_ << " || err instanceof " << js_type_namespace(t->get_program()) << t->get_name();
      }
    }
  }
  f_service_ << ") {" << '\n';
  indent_up();
  f_service_ << indent() << "result_obj = new " << resultname
             << "((err !== null || typeof err === 'undefined') ? err : {success: result});" << '\n' << indent()
             << "output.writeMessageBegin(\"" << tfunction->get_name()
             << "\", Thrift.MessageType.REPLY, seqid);" << '\n';
  indent_down();
  indent(f_service_) << "} else {" << '\n';
  indent_up();
  f_service_ << indent() << "result_obj = new "
                            "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN,"
                            " err.message);" << '\n' << indent() << "output.writeMessageBegin(\""
             << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << '\n';
  indent_down();
  f_service_ << indent() << "}" << '\n' << indent() << "result_obj[Symbol.for(\"write\")](output);" << '\n' << indent()
             << "output.writeMessageEnd();" << '\n' << indent() << "output.flush();" << '\n';

  indent_down();
  indent(f_service_) << "});" << '\n';
  indent_down();
  indent(f_service_) << "}" << '\n';
  // End callback style invocation

  indent_down();

  if (gen_es6_) {
    indent(f_service_) << "}" << '\n';
  } else {
    indent(f_service_) << "};" << '\n';
  }
}