From: Roger Meier Date: Thu, 12 Jan 2012 21:38:29 +0000 (+0000) Subject: THRIFT-1267 Node.js can't throw exceptions X-Git-Tag: 0.9.1~470 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=eaa61d8fda8c5f326311d952bc19a851a8427db7;p=common%2Fthrift.git THRIFT-1267 Node.js can't throw exceptions Patch: Henrique Mendonca git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1230797 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/.gitignore b/.gitignore index cfe1185d..24529c9f 100644 --- a/.gitignore +++ b/.gitignore @@ -210,6 +210,9 @@ /test/hs/Makefile.in /test/log/ /test/test.log +/test/nodejs/gen-nodejs/ +/test/nodejs/Makefile +/test/nodejs/Makefile.in /test/perl/gen-* /test/perl/Makefile /test/perl/Makefile.in diff --git a/compiler/cpp/src/generate/t_js_generator.cc b/compiler/cpp/src/generate/t_js_generator.cc index 6a27886e..5a5b59e8 100644 --- a/compiler/cpp/src/generate/t_js_generator.cc +++ b/compiler/cpp/src/generate/t_js_generator.cc @@ -518,10 +518,10 @@ void t_js_generator::generate_js_struct_definition(ofstream& out, if (gen_node_) { if (is_exported) { - out << "var " << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = " << - "module.exports." << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = function(args) {\n"; + out << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = " << + "module.exports." << tstruct->get_name() << " = function(args) {\n"; } else { - out << "var " << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = function(args) {\n"; + out << js_namespace(tstruct->get_program()) << tstruct->get_name() << " = function(args) {\n"; } } else { out << js_namespace(tstruct->get_program()) << tstruct->get_name() <<" = function(args) {\n"; @@ -557,6 +557,17 @@ void t_js_generator::generate_js_struct_definition(ofstream& out, } } + // Early returns for exceptions + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = get_true_type((*m_iter)->get_type()); + if (t->is_xception()) { + out << indent() << "if (args instanceof " << js_type_namespace(t->get_program()) << t->get_name() << ") {" << endl + << indent() << indent() << "this." << (*m_iter)->get_name() << " = args;" << endl + << indent() << indent() << "return;" << endl + << indent() << "}" << endl; + } + } + out << indent() << "if (args) {" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { @@ -736,19 +747,18 @@ void t_js_generator::generate_service(t_service* tservice) { render_includes() << endl; if (gen_node_) { - if (tservice->get_extends() != NULL) { - f_service_ << - "var " << tservice->get_extends()->get_name() << - " = require('./" << tservice->get_extends()->get_name() << "')" << endl << - "var " << tservice->get_extends()->get_name() << "Client = " << - tservice->get_extends()->get_name() << ".Client" << endl << - "var " << tservice->get_extends()->get_name() << "Processor = " << - tservice->get_extends()->get_name() << ".Processor" << endl; - - } - + if (tservice->get_extends() != NULL) { f_service_ << - "var ttypes = require('./" + program_->get_name() + "_types');" << endl; + "var " << tservice->get_extends()->get_name() << + " = require('./" << tservice->get_extends()->get_name() << "')" << endl << + "var " << tservice->get_extends()->get_name() << "Client = " << + tservice->get_extends()->get_name() << ".Client" << endl << + "var " << tservice->get_extends()->get_name() << "Processor = " << + tservice->get_extends()->get_name() << ".Processor" << endl; + } + + f_service_ << + "var ttypes = require('./" + program_->get_name() + "_types');" << endl; } generate_service_helpers(tservice); @@ -772,7 +782,7 @@ void t_js_generator::generate_service_processor(t_service* tservice) { vector::iterator f_iter; f_service_ << - "var " << js_namespace(tservice->get_program()) << service_name_ << "Processor = " << + js_namespace(tservice->get_program()) << service_name_ << "Processor = " << "exports.Processor = function(handler) "; scope_up(f_service_); @@ -836,12 +846,6 @@ void t_js_generator::generate_process_function(t_service* tservice, indent() << "args.read(input);" << endl << indent() << "input.readMessageEnd();" << endl; - // Declare result for non oneway function - if (!tfunction->is_oneway()) { - f_service_ << - indent() << "var result = new " << resultname << "();" << endl; - } - // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); @@ -871,11 +875,11 @@ void t_js_generator::generate_process_function(t_service* tservice, if (!first) { f_service_ << ", "; } - f_service_ << "function (success) {" << endl; + f_service_ << "function (err, result) {" << endl; indent_up(); f_service_ << - indent() << "result.success = success;" << endl << + indent() << "var result = new " << resultname << "((err != null ? err : {success: result}));" << endl << indent() << "output.writeMessageBegin(\"" << tfunction->get_name() << "\", Thrift.MessageType.REPLY, seqid);" << endl << indent() << "result.write(output);" << endl << @@ -959,7 +963,7 @@ void t_js_generator::generate_service_client(t_service* tservice) { if (gen_node_) { f_service_ << - "var " << js_namespace(tservice->get_program()) << service_name_ << "Client = " << + js_namespace(tservice->get_program()) << service_name_ << "Client = " << "exports.Client = function(output, pClass) {"<= 0.2.4" } +} diff --git a/test/nodejs/server.js b/test/nodejs/server.js new file mode 100644 index 00000000..056209db --- /dev/null +++ b/test/nodejs/server.js @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var thrift = require('thrift'); +var Thrift = thrift.Thrift; + +var ThriftTest = require('./gen-nodejs/ThriftTest'), + ttypes = require('./gen-nodejs/ThriftTest_types'); + + +var server = thrift.createServer(ThriftTest, { + testVoid: function(result) { + console.log('testVoid()'); + result(null); + }, + + testString: function(thing, result) { + console.log('testString(\'' + thing + '\')'); + result(null, thing); + }, + + testByte: function(thing, result) { + console.log('testByte(' + thing + ')'); + result(null, thing); + }, + + testI32: function(thing, result) { + console.log('testI32(' + thing + ')'); + result(null, thing); + }, + + testI64: function(thing, result) { + console.log('testI64(' + thing + ')'); + result(null, thing); + }, + + testDouble: function(thing, result) { + console.log('testDouble(' + thing + ')'); + result(null, thing); + }, + + testStruct: function(thing, result) { + console.log('testStruct('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testNest: function(nest, result) { + console.log('testNest('); + console.log(nest); + console.log(')'); + result(null, nest); + }, + + testMap: function(thing, result) { + console.log('testMap('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testStringMap: function(thing, result) { + console.log('testStringMap('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testSet: function(thing, result) { + console.log('testSet('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testList: function(thing, result) { + console.log('testList('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testEnum: function(thing, result) { + console.log('testEnum(' + thing + ')'); + result(null, thing); + }, + + testTypedef: function(thing, result) { + console.log('testTypedef(' + thing + ')'); + result(null, thing); + }, + + testMapMap: function(hello, result) { + console.log('testMapMap(' + hello + ')'); + + var mapmap = []; + var pos = []; + var neg = []; + for (var i = 1; i < 5; i++) { + pos[i] = i; + neg[-i] = -i; + } + mapmap[4] = pos; + mapmap[-4] = neg; + + result(null, mapmap); + }, + + testInsanity: function(argument, result) { + console.log('testInsanity()'); + + var hello = new ttypes.Xtruct(); + hello.string_thing = 'Hello2'; + hello.byte_thing = 2; + hello.i32_thing = 2; + hello.i64_thing = 2; + + var goodbye = new ttypes.Xtruct(); + goodbye.string_thing = 'Goodbye4'; + goodbye.byte_thing = 4; + goodbye.i32_thing = 4; + goodbye.i64_thing = 4; + + var crazy = new ttypes.Insanity(); + crazy.userMap = []; + crazy.userMap[ttypes.Numberz.EIGHT] = 8; + crazy.userMap[ttypes.Numberz.FIVE] = 5; + crazy.xtructs = []; + crazy.xtructs.add(goodbye); + crazy.xtructs.add(hello); + + var first_map = []; + var second_map = []; + + first_map[ttypes.Numberz.TWO] = crazy; + first_map[ttypes.Numberz.THREE] = crazy; + + var looney = new ttypes.Insanity(); + second_map[ttypes.Numberz.SIX] = looney; + + var insane = []; + insane[1] = first_map; + insane[2] = second_map; + + result(null, insane); + }, + + testMulti: function(arg0, arg1, arg2, arg3, arg4, arg5, result) { + console.log('testMulti()'); + + var hello = new ttypes.Xtruct();; + hello.string_thing = 'Hello2'; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = arg2; + result(null, hello); + }, + + testException: function(arg, result) { + console.log('testException('+arg+')'); + if (arg === 'Xception') { + var x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = arg; + result(x); + } else if (arg === 'ApplicationException') { + result(new Thrift.TException(arg)); + } else { + var res = new ttypes.Xtruct(); + res.string_thing = arg; + result(null, res); + } + }, + + testMultiException: function(arg0, arg1, result) { + console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); + if (arg0 === ('Xception')) { + var x = new Xception(); + x.errorCode = 1001; + x.message = 'This is an Xception'; + result(x); + } else if (arg0 === ('Xception2')) { + var x = new Xception2(); + x.errorCode = 2002; + x.struct_thing = new Xtruct(); + x.struct_thing.string_thing = 'This is an Xception2'; + result(x); + } + + var res = new Xtruct(); + res.string_thing = arg1; + result(null, res); + }, + + testOneway: function(sleepFor, result) { + console.log('testOneway(' + sleepFor + ') => sleeping...'); + setTimeout(function(){ + console.log('Done sleeping!'); + }, sleepFor); + result(null); + } +}); + +server.listen(9090); diff --git a/test/test.sh b/test/test.sh index ee74e754..071b5e55 100755 --- a/test/test.sh +++ b/test/test.sh @@ -76,6 +76,7 @@ sockets="ip domain" # we need a test certificate first #sockets="ip ip-ssl domain" + for proto in $protocols; do for trans in $transports; do for sock in $sockets; do @@ -117,3 +118,11 @@ do_test "perl-cpp" "binary" "buffered-ip" \ "perl -I perl/gen-perl/ -I../lib/perl/lib/ perl/TestClient.pl" \ "cpp/TestServer" \ "10" +do_test "nodejs-nodejs" "binary" "framed-ip" \ + "make -C nodejs/ client" \ + "make -C nodejs/ server" \ + "1" +do_test "cpp-nodejs" "binary" "framed-ip" \ + "cpp/TestClient --transport=framed" \ + "make -C nodejs/ server" \ + "1"