in thrift/compiler/generate/t_js_generator.cc [979:1226]
void t_js_generator::generate_service_client(const t_service* tservice) {
string extends = "";
if (gen_node_) {
f_service_ << js_namespace(tservice->program()) << service_name_
<< "Client = "
<< "exports.Client = function(output, pClass) {" << endl;
} else {
f_service_ << js_namespace(tservice->program()) << service_name_
<< "Client = function(input, output) {" << endl;
}
indent_up();
if (gen_node_) {
f_service_ << indent() << " this.output = output;" << endl
<< indent() << " this.pClass = pClass;" << endl
<< indent() << " this.seqid = 0;" << endl
<< indent() << " this._reqs = {};" << endl;
} else {
f_service_ << indent() << " this.input = input;" << endl
<< indent() << " this.output = (!output) ? input : output;"
<< endl
<< indent() << " this.seqid = 0;" << endl;
}
indent_down();
f_service_ << indent() << "};" << endl;
if (tservice->get_extends() != nullptr) {
indent(f_service_) << "Thrift.inherits("
<< js_namespace(tservice->program()) << service_name_
<< "Client, " << tservice->get_extends()->get_name()
<< "Client)" << endl;
} else {
// init prototype
indent(f_service_) << js_namespace(tservice->program()) << service_name_
<< "Client.prototype = {};" << endl;
}
// Generate client method implementations
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::const_iterator f_iter;
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
const t_struct* arg_struct = (*f_iter)->get_paramlist();
const vector<t_field*>& fields = arg_struct->get_members();
vector<t_field*>::const_iterator fld_iter;
string funname = (*f_iter)->get_name();
string arglist = argument_list(arg_struct);
// Open function
f_service_ << js_namespace(tservice->program()) << service_name_
<< "Client.prototype."
<< function_signature(*f_iter, "", gen_node_ || gen_jquery_)
<< " {" << endl;
indent_up();
if (gen_node_) {
f_service_ << indent() << "this.seqid += 1;" << endl
<< indent() << "this._reqs[this.seqid] = callback;" << endl;
} else if (gen_jquery_) {
f_service_ << indent() << "if (callback === undefined) {" << endl;
indent_up();
}
f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");"
<< endl;
if (!gen_node_ && (*f_iter)->qualifier() != t_function_qualifier::one_way) {
f_service_ << indent();
if (!(*f_iter)->get_returntype()->is_void()) {
f_service_ << "return ";
}
f_service_ << "this.recv_" << funname << "();" << endl;
}
if (gen_jquery_) {
indent_down();
f_service_ << indent() << "} else {" << endl;
indent_up();
f_service_ << indent() << "var postData = this.send_" << funname << "("
<< arglist << (arglist.empty() ? "" : ", ") << "true);"
<< endl;
f_service_ << indent() << "return this.output.getTransport()" << endl;
indent_up();
f_service_ << indent()
<< ".jqRequest(this, postData, arguments, this.recv_"
<< funname << ");" << endl;
indent_down();
indent_down();
f_service_ << indent() << "}" << endl;
}
indent_down();
f_service_ << "};" << endl << endl;
// Send function
f_service_ << js_namespace(tservice->program()) << service_name_
<< "Client.prototype.send_"
<< function_signature(*f_iter, "", gen_jquery_) << " {" << endl;
indent_up();
std::string outputVar;
if (gen_node_) {
f_service_ << indent() << "var output = new this.pClass(this.output);"
<< endl;
outputVar = "output";
} else {
outputVar = "this.output";
}
std::string argsname = js_namespace(program_) + service_name_ + "_" +
(*f_iter)->get_name() + "_args";
// Serialize the request header
f_service_ << indent() << outputVar << ".writeMessageBegin('"
<< (*f_iter)->get_name()
<< "', Thrift.MessageType.CALL, this.seqid);" << endl;
f_service_ << indent() << "var args = new " << argsname << "();" << endl;
for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
<< (*fld_iter)->get_name() << ";" << endl;
}
// Write to the stream
f_service_ << indent() << "args.write(" << outputVar << ");" << endl
<< indent() << outputVar << ".writeMessageEnd();" << endl;
if (gen_node_) {
f_service_ << indent() << "return this.output.flush();" << endl;
} else {
if (gen_jquery_) {
f_service_ << indent()
<< "return this.output.getTransport().flush(callback);"
<< endl;
} else {
f_service_ << indent() << "return this.output.getTransport().flush();"
<< endl;
}
}
indent_down();
f_service_ << "};" << endl;
if ((*f_iter)->qualifier() != t_function_qualifier::one_way) {
std::string resultname = js_namespace(tservice->program()) +
service_name_ + "_" + (*f_iter)->get_name() + "_result";
if (gen_node_) {
// Open function
f_service_ << endl
<< js_namespace(tservice->program()) << service_name_
<< "Client.prototype.recv_" << (*f_iter)->get_name()
<< " = function(input,mtype,rseqid) {" << endl;
} else {
t_function recv_function(
(*f_iter)->get_returntype(),
string("recv_") + (*f_iter)->get_name(),
std::make_unique<t_paramlist>(program_));
// Open function
f_service_ << endl
<< js_namespace(tservice->program()) << service_name_
<< "Client.prototype." << function_signature(&recv_function)
<< " {" << endl;
}
indent_up();
std::string inputVar;
if (gen_node_) {
inputVar = "input";
} else {
inputVar = "this.input";
}
if (gen_node_) {
f_service_ << indent()
<< "var callback = this._reqs[rseqid] || function() {};"
<< endl
<< indent() << "delete this._reqs[rseqid];" << endl;
} else {
f_service_ << indent() << "var ret = this.input.readMessageBegin();"
<< endl
<< indent() << "var fname = ret.fname;" << endl
<< indent() << "var mtype = ret.mtype;" << endl
<< indent() << "var rseqid = ret.rseqid;" << endl;
}
f_service_ << indent() << "if (mtype == Thrift.MessageType.EXCEPTION) {"
<< endl
<< indent() << " var x = new Thrift.TApplicationException();"
<< endl
<< indent() << " x.read(" << inputVar << ");" << endl
<< indent() << " " << inputVar << ".readMessageEnd();" << endl
<< indent() << " " << render_recv_throw("x") << endl
<< indent() << "}" << endl;
f_service_ << indent() << "var result = new " << resultname << "();"
<< endl
<< indent() << "result.read(" << inputVar << ");" << endl;
f_service_ << indent() << inputVar << ".readMessageEnd();" << endl
<< endl;
const t_struct* xs = (*f_iter)->get_xceptions();
const std::vector<t_field*>& xceptions = xs->get_members();
vector<t_field*>::const_iterator x_iter;
for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
f_service_ << indent() << "if (null !== result."
<< (*x_iter)->get_name() << ") {" << endl
<< indent() << " "
<< render_recv_throw("result." + (*x_iter)->get_name())
<< endl
<< indent() << "}" << endl;
}
// Careful, only return result if not a void function
if (!(*f_iter)->get_returntype()->is_void()) {
f_service_ << indent() << "if (null !== result.success) {" << endl
<< indent() << " " << render_recv_return("result.success")
<< endl
<< indent() << "}" << endl;
f_service_ << indent()
<< render_recv_throw(
"'" + (*f_iter)->get_name() +
" failed: unknown result'")
<< endl;
} else {
if (gen_node_) {
indent(f_service_) << "callback(null)" << endl;
} else {
indent(f_service_) << "return;" << endl;
}
}
// Close function
indent_down();
f_service_ << "};" << endl;
}
}
}