diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index 27240e4f0b5..e7c95b5d928 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -68,6 +68,7 @@ class t_js_generator : public t_oop_generator { gen_jquery_ = false; gen_ts_ = false; gen_es6_ = false; + gen_esm_ = false; gen_episode_file_ = false; bool with_ns_ = false; @@ -83,6 +84,8 @@ class t_js_generator : public t_oop_generator { with_ns_ = true; } else if( iter->first.compare("es6") == 0) { gen_es6_ = true; + } else if ( iter->first.compare("esm") == 0) { + gen_esm_ = true; } else if( iter->first.compare("imports") == 0) { parse_imports(program, iter->second); } else if (iter->first.compare("thrift_package_output_directory") == 0) { @@ -105,6 +108,10 @@ class t_js_generator : public t_oop_generator { throw std::invalid_argument("invalid switch: [-gen js:with_ns] is only valid when using node.js"); } + if (!gen_node_ && gen_esm_) { + throw std::invalid_argument("invalid switch: [-gen js:esm] is only valid when using node.js"); + } + // Depending on the processing flags, we will update these to be ES6 compatible js_const_type_ = "var "; js_let_type_ = "var "; @@ -278,13 +285,6 @@ class t_js_generator : public t_oop_generator { return js_namespace(p); } - std::string js_export_namespace(t_program* p) { - if (gen_node_) { - return "exports."; - } - return js_namespace(p); - } - bool has_js_namespace(t_program* p) { if (no_ns_) { return false; @@ -374,6 +374,11 @@ class t_js_generator : public t_oop_generator { */ bool gen_es6_; + /** + * True if we should generate ES modules, instead of CommonJS. + */ + bool gen_esm_; + /** * True if we will generate an episode file. */ @@ -452,7 +457,7 @@ void t_js_generator::init_generator() { f_episode_.open(f_episode_file_path); } - const auto f_types_name = outdir + program_->get_name() + "_types.js"; + const auto f_types_name = outdir + program_->get_name() + "_types" + (gen_esm_ ? ".mjs" : ".js"); f_types_.open(f_types_name.c_str()); if (gen_episode_file_) { const auto types_module = program_->get_name() + "_types"; @@ -478,7 +483,13 @@ void t_js_generator::init_generator() { } if (gen_node_) { - f_types_ << js_const_type_ << "ttypes = module.exports = {};" << '\n'; + if (gen_esm_) { + // Import the current module, so we can reference it as ttypes. This is + // fine in ESM, because it allows circular imports. + f_types_ << "import * as ttypes from './" + program_->get_name() + "_types.mjs';" << '\n'; + } else { + f_types_ << js_const_type_ << "ttypes = module.exports = {};" << '\n'; + } } string pns; @@ -507,12 +518,26 @@ void t_js_generator::init_generator() { */ string t_js_generator::js_includes() { if (gen_node_) { - string result = js_const_type_ + "thrift = require('thrift');\n" - + js_const_type_ + "Thrift = thrift.Thrift;\n"; + string result; + + if (gen_esm_) { + result += "import { Thrift } from 'thrift';\n"; + } else { + result += js_const_type_ + "thrift = require('thrift');\n" + + js_const_type_ + "Thrift = thrift.Thrift;\n"; + } if (!gen_es6_) { - result += js_const_type_ + "Q = thrift.Q;\n"; + if (gen_esm_) { + result += "import { Q } from 'thrift';\n"; + } else { + result += js_const_type_ + "Q = thrift.Q;\n"; + } + } + if (gen_esm_) { + result += "import Int64 from 'node-int64';"; + } else { + result += js_const_type_ + "Int64 = require('node-int64');\n"; } - result += js_const_type_ + "Int64 = require('node-int64');\n"; return result; } string result = "if (typeof Int64 === 'undefined' && typeof require === 'function') {\n " + js_const_type_ + "Int64 = require('node-int64');\n}\n"; @@ -594,7 +619,7 @@ string t_js_generator::get_import_path(t_program* program) { return "./" + import_file_name; } - const string import_file_name_with_extension = import_file_name + ".js"; + const string import_file_name_with_extension = import_file_name + (gen_esm_ ? ".mjs" : ".js"); auto module_name_and_import_path_iterator = module_name_2_import_path.find(import_file_name); if (module_name_and_import_path_iterator != module_name_2_import_path.end()) { @@ -638,7 +663,11 @@ void t_js_generator::generate_typedef(t_typedef* ttypedef) { * @param tenum The enumeration */ void t_js_generator::generate_enum(t_enum* tenum) { - f_types_ << js_type_namespace(tenum->get_program()) << tenum->get_name() << " = {" << '\n'; + if (gen_esm_) { + f_types_ << "export const " << tenum->get_name() << " = {" << '\n'; + } else { + f_types_ << js_type_namespace(tenum->get_program()) << tenum->get_name() << " = {" << '\n'; + } if (gen_ts_) { f_types_ts_ << ts_print_doc(tenum) << ts_indent() << ts_declare() << "enum " @@ -680,7 +709,11 @@ void t_js_generator::generate_const(t_const* tconst) { string name = tconst->get_name(); t_const_value* value = tconst->get_value(); - f_types_ << js_type_namespace(program_) << name << " = "; + if (gen_esm_) { + f_types_ << "export const " << name << " = "; + } else { + f_types_ << js_type_namespace(program_) << name << " = "; + } f_types_ << render_const_value(type, value) << ";" << '\n'; if (gen_ts_) { @@ -859,9 +892,18 @@ void t_js_generator::generate_js_struct_definition(ostream& out, vector::const_iterator m_iter; if (gen_node_) { + string commonjs_export = ""; + + if (is_exported) { + if (gen_esm_) { + out << "export "; + } else { + commonjs_export = " = module.exports." + tstruct->get_name(); + } + } + string prefix = has_js_namespace(tstruct->get_program()) ? js_namespace(tstruct->get_program()) : js_const_type_; - out << prefix << tstruct->get_name() << - (is_exported ? " = module.exports." + tstruct->get_name() : ""); + out << prefix << tstruct->get_name() << commonjs_export; if (gen_ts_) { f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class " << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "") @@ -1198,7 +1240,7 @@ void t_js_generator::generate_js_struct_writer(ostream& out, t_struct* tstruct) * @param tservice The service definition */ void t_js_generator::generate_service(t_service* tservice) { - string f_service_name = get_out_dir() + service_name_ + ".js"; + string f_service_name = get_out_dir() + service_name_ + (gen_esm_ ? ".mjs" : ".js"); f_service_.open(f_service_name.c_str()); if (gen_episode_file_) { f_episode_ << service_name_ << ":" << thrift_package_output_directory_ << "/" << service_name_ << '\n'; @@ -1282,7 +1324,11 @@ void t_js_generator::generate_service(t_service* tservice) { << tservice->get_extends()->get_name() << "');" << '\n'; } - f_service_ << js_const_type_ << "ttypes = require('./" + program_->get_name() + "_types');" << '\n'; + if (gen_esm_) { + f_service_ << "import * as ttypes from './" + program_->get_name() + "_types.mjs';" << '\n'; + } else { + f_service_ << js_const_type_ << "ttypes = require('./" + program_->get_name() + "_types');" << '\n'; + } } generate_service_helpers(tservice); @@ -1317,27 +1363,28 @@ void t_js_generator::generate_service_processor(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; - if (gen_node_) { - string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : js_const_type_; - f_service_ << prefix << service_name_ << "Processor = " << "exports.Processor"; - if (gen_ts_) { - f_service_ts_ << '\n' << "declare class Processor "; - if (tservice->get_extends() != nullptr) { - f_service_ts_ << "extends " << tservice->get_extends()->get_name() << ".Processor "; - } - f_service_ts_ << "{" << '\n'; - indent_up(); + std::string service_var; + if (!gen_node_ || has_js_namespace(tservice->get_program())) { + service_var = js_namespace(tservice->get_program()) + service_name_ + "Processor"; + f_service_ << service_var; + } else { + service_var = service_name_ + "Processor"; + f_service_ << js_const_type_ << service_var; + }; + if (gen_node_ && gen_ts_) { + f_service_ts_ << '\n' << "declare class Processor "; + if (tservice->get_extends() != nullptr) { + f_service_ts_ << "extends " << tservice->get_extends()->get_name() << ".Processor "; + } + f_service_ts_ << "{" << '\n'; + indent_up(); - if(tservice->get_extends() == nullptr) { - f_service_ts_ << ts_indent() << "private _handler: object;" << '\n' << '\n'; - } - f_service_ts_ << ts_indent() << "constructor(handler: object);" << '\n'; - f_service_ts_ << ts_indent() << "process(input: thrift.TProtocol, output: thrift.TProtocol): void;" << '\n'; - indent_down(); + if(tservice->get_extends() == nullptr) { + f_service_ts_ << ts_indent() << "private _handler: object;" << '\n' << '\n'; } - } else { - f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Processor = " - << "exports.Processor"; + f_service_ts_ << ts_indent() << "constructor(handler: object);" << '\n'; + f_service_ts_ << ts_indent() << "process(input: thrift.TProtocol, output: thrift.TProtocol): void;" << '\n'; + indent_down(); } bool is_subclass_service = tservice->get_extends() != nullptr; @@ -1419,6 +1466,12 @@ void t_js_generator::generate_service_processor(t_service* tservice) { if (gen_node_ && gen_ts_) { f_service_ts_ << "}" << '\n'; } + + if(gen_esm_) { + f_service_ << "export { " << service_var << " as Processor };" << '\n'; + } else { + f_service_ << "exports.Processor = " << service_var << ";" << '\n'; + } } /** @@ -1702,9 +1755,10 @@ void t_js_generator::generate_service_client(t_service* tservice) { bool is_subclass_service = tservice->get_extends() != nullptr; + string client_var = js_namespace(tservice->get_program()) + service_name_ + "Client"; if (gen_node_) { - string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : js_const_type_; - f_service_ << prefix << service_name_ << "Client = " << "exports.Client"; + string prefix = has_js_namespace(tservice->get_program()) ? "" : js_const_type_; + f_service_ << prefix << client_var; if (gen_ts_) { f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class " << "Client "; @@ -1714,8 +1768,7 @@ void t_js_generator::generate_service_client(t_service* tservice) { f_service_ts_ << "{" << '\n'; } } else { - f_service_ << js_namespace(tservice->get_program()) << service_name_ - << "Client"; + f_service_ << client_var; if (gen_ts_) { f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class " << service_name_ << "Client "; @@ -2204,6 +2257,12 @@ void t_js_generator::generate_service_client(t_service* tservice) { indent_down(); f_service_ << "};" << '\n'; } + + if(gen_esm_) { + f_service_ << "export { " << client_var << " as Client };" << '\n'; + } else if(gen_node_) { + f_service_ << "exports.Client = " << client_var << ";" << '\n'; + } } std::string t_js_generator::render_recv_throw(std::string var) { diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am index 9503f04c9e1..5be81615352 100644 --- a/lib/nodejs/Makefile.am +++ b/lib/nodejs/Makefile.am @@ -20,9 +20,14 @@ stubs: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen js:node -o test/ $(top_srcdir)/test/v0.16/ThriftTest.thrift -deps: $(top_srcdir)/package.json +deps-root: $(top_srcdir)/package.json $(NPM) install $(top_srcdir)/ || $(NPM) install $(top_srcdir)/ +deps-test: test/package.json test/package-lock.json + cd test/ && $(NPM) install && cd .. + +deps: deps-root deps-test + all-local: deps precross: deps stubs diff --git a/lib/nodejs/test/binary.test.js b/lib/nodejs/test/binary.test.js index 187cd187434..cff6bdcb244 100644 --- a/lib/nodejs/test/binary.test.js +++ b/lib/nodejs/test/binary.test.js @@ -18,7 +18,7 @@ */ const test = require("tape"); -const binary = require("thrift/binary"); +const binary = require("thrift/lib/nodejs/lib/thrift/binary"); const cases = { "Should read signed byte": function(assert) { diff --git a/lib/nodejs/test/client.js b/lib/nodejs/test/client.mjs similarity index 90% rename from lib/nodejs/test/client.js rename to lib/nodejs/test/client.mjs index 31ea06e2f0d..5588c920eaf 100644 --- a/lib/nodejs/test/client.js +++ b/lib/nodejs/test/client.mjs @@ -19,17 +19,15 @@ * under the License. */ -const assert = require("assert"); -const thrift = require("thrift"); -const helpers = require("./helpers"); +import assert from "assert"; +import thrift from "thrift"; +import helpers from "./helpers.js"; -const ThriftTest = require(`./${helpers.genPath}/ThriftTest`); -const ThriftTestDriver = require("./test_driver").ThriftTestDriver; -const ThriftTestDriverPromise = require("./test_driver") - .ThriftTestDriverPromise; -const SecondService = require(`./${helpers.genPath}/SecondService`); +const ThriftTest = await import(`./${helpers.genPath}/ThriftTest.${helpers.moduleExt}`); +import { ThriftTestDriver, ThriftTestDriverPromise } from "./test_driver.mjs"; +const SecondService = await import(`./${helpers.genPath}/SecondService.${helpers.moduleExt}`); -const program = require("commander"); +import program from "commander"; program .option( @@ -55,6 +53,7 @@ program ) .option("--es6", "Use es6 code") .option("--es5", "Use es5 code") + .option("--esm", "Use es modules") .parse(process.argv); const host = program.host; @@ -172,4 +171,4 @@ function runTests() { }); } -exports.expressoTest = function() {}; +export const expressoTest = function() {}; diff --git a/lib/nodejs/test/helpers.js b/lib/nodejs/test/helpers.js index f3c27b3d1f1..0ccd1ef198d 100644 --- a/lib/nodejs/test/helpers.js +++ b/lib/nodejs/test/helpers.js @@ -18,7 +18,7 @@ */ "use strict"; -const thrift = require("../lib/thrift"); +const thrift = require("thrift"); module.exports.transports = { buffered: thrift.TBufferedTransport, @@ -32,7 +32,36 @@ module.exports.protocols = { header: thrift.THeaderProtocol }; -module.exports.ecmaMode = process.argv.includes("--es6") ? "es6" : "es5"; -module.exports.genPath = process.argv.includes("--es6") - ? "gen-nodejs-es6" - : "gen-nodejs"; +const variant = (function() { + if (process.argv.includes("--es6")) { + return "es6"; + } else if (process.argv.includes("--esm")) { + return "esm"; + } else { + return "es5"; + } +})(); + +module.exports.ecmaMode = ["esm", "es6"].includes(variant) ? "es6" : "es5"; +const genPath = module.exports.genPath = (function() { + if (variant == "es5") { + return "gen-nodejs"; + } else { + return `gen-nodejs-${variant}`; + } +})(); + +const moduleExt = module.exports.moduleExt = variant === "esm" ? "mjs" : "js"; + +/** + * Imports a types module, correctly handling the differences in esm and commonjs + */ +module.exports.importTypes = async function(filename) { + const typesModule = await import(`./${genPath}/${filename}.${moduleExt}`); + + if (variant === "esm") { + return typesModule; + } else { + return typesModule.default; + } +} diff --git a/lib/nodejs/test/package-lock.json b/lib/nodejs/test/package-lock.json new file mode 100644 index 00000000000..859c8dffdd9 --- /dev/null +++ b/lib/nodejs/test/package-lock.json @@ -0,0 +1,50 @@ +{ + "name": "test", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "thrift": "file:../../.." + } + }, + "../../..": { + "version": "0.22.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "browser-or-node": "^1.2.1", + "isomorphic-ws": "^4.0.1", + "node-int64": "^0.4.0", + "q": "^1.5.0", + "ws": "^5.2.3" + }, + "devDependencies": { + "@types/node": "^10.12.6", + "@types/node-int64": "^0.4.29", + "@types/q": "^1.5.1", + "buffer-equals": "^1.0.4", + "commander": "^2.14.1", + "connect": "^3.6.6", + "eslint": "^5.7.0", + "eslint-config-prettier": "^3.1.0", + "eslint-plugin-prettier": "^3.0.0", + "html-validator-cli": "^2.0.0", + "jsdoc": "^4.0.2", + "json-int64": "^1.0.2", + "nyc": "^15.0.0", + "prettier": "^1.14.3", + "tape": "^4.9.0", + "typescript": "^3.1.6", + "utf-8-validate": "^5.0.0" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/thrift": { + "resolved": "../../..", + "link": true + } + } +} diff --git a/lib/nodejs/test/package.json b/lib/nodejs/test/package.json new file mode 100644 index 00000000000..22220ec724a --- /dev/null +++ b/lib/nodejs/test/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "thrift": "file:../../.." + } +} diff --git a/lib/nodejs/test/server.js b/lib/nodejs/test/server.mjs similarity index 85% rename from lib/nodejs/test/server.js rename to lib/nodejs/test/server.mjs index 677839aea2b..26354f2bf5b 100644 --- a/lib/nodejs/test/server.js +++ b/lib/nodejs/test/server.mjs @@ -19,11 +19,11 @@ * under the License. */ -const fs = require("fs"); -const path = require("path"); -const thrift = require("../lib/thrift"); -const program = require("commander"); -const helpers = require("./helpers"); +import fs from "fs"; +import path from "path"; +import thrift from "thrift"; +import program from "commander"; +import helpers from "./helpers.js"; program .option( @@ -47,11 +47,12 @@ program .option("--callback", "test with callback style functions") .option("--es6", "Use es6 code") .option("--es5", "Use es5 code") + .option("--esm", "Use es modules") .parse(process.argv); -const ThriftTest = require(`./${helpers.genPath}/ThriftTest`); -const SecondService = require(`./${helpers.genPath}/SecondService`); -const { ThriftTestHandler } = require("./test_handler"); +const ThriftTest = await import(`./${helpers.genPath}/ThriftTest.${helpers.moduleExt}`); +const SecondService = await import(`./${helpers.genPath}/SecondService.${helpers.moduleExt}`); +import { ThriftTestHandler } from "./test_handler.mjs"; const port = program.port; const domainSocket = program.domainSocket; @@ -113,8 +114,8 @@ if (ssl) { type === "websocket" ) { options.tls = { - key: fs.readFileSync(path.resolve(__dirname, "server.key")), - cert: fs.readFileSync(path.resolve(__dirname, "server.crt")) + key: fs.readFileSync(path.resolve(import.meta.dirname, "server.key")), + cert: fs.readFileSync(path.resolve(import.meta.dirname, "server.crt")) }; } } diff --git a/lib/nodejs/test/test-cases.js b/lib/nodejs/test/test-cases.mjs similarity index 85% rename from lib/nodejs/test/test-cases.js rename to lib/nodejs/test/test-cases.mjs index 02c566fbf53..b687afeac3f 100644 --- a/lib/nodejs/test/test-cases.js +++ b/lib/nodejs/test/test-cases.mjs @@ -19,13 +19,14 @@ "use strict"; -const helpers = require("./helpers"); -const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); -const Int64 = require("node-int64"); +import helpers from "./helpers.js"; +import Int64 from "node-int64"; + +const ttypes = await helpers.importTypes(`ThriftTest_types`); //all Languages in UTF-8 /*jshint -W100 */ -const stringTest = (module.exports.stringTest = +export const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " + "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, " + "Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, " + @@ -50,27 +51,27 @@ const stringTest = (module.exports.stringTest = "Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " + "Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, " + "Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " + - "Bân-lâm-gú, 粵語"); + "Bân-lâm-gú, 粵語"; /*jshint +W100 */ -const specialCharacters = (module.exports.specialCharacters = +export const specialCharacters = 'quote: " backslash:' + " forwardslash-escaped: / " + " backspace: \b formfeed: \f newline: \n return: \r tab: " + ' now-all-of-them-together: "\\/\b\n\r\t' + " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><" + - ' char-to-test-json-parsing: ]] "]] \\" }}}{ [[[ '); + ' char-to-test-json-parsing: ]] "]] \\" }}}{ [[[ '; -const mapTestInput = (module.exports.mapTestInput = { +export const mapTestInput = { a: "123", "a b": "with spaces ", same: "same", "0": "numeric key", longValue: stringTest, stringTest: "long key" -}); +}; -const simple = [ +export const simple = [ ["testVoid", undefined], ["testString", "Test"], ["testString", ""], @@ -103,32 +104,32 @@ for (let i = 0; i < 5; ++i) { mapout[i] = i - 10; } -const deep = [ +export const deep = [ [ "testList", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] ] ]; -const deepUnordered = [ +export const deepUnordered = [ ["testMap", mapout], ["testSet", [1, 2, 3]], ["testStringMap", mapTestInput] ]; -const out = new ttypes.Xtruct({ +export const out = new ttypes.Xtruct({ string_thing: "Zero", byte_thing: 1, i32_thing: -3, i64_thing: 1000000 }); -const out2 = new ttypes.Xtruct2(); +export const out2 = new ttypes.Xtruct2(); out2.byte_thing = 1; out2.struct_thing = out; out2.i32_thing = 5; -const crazy = new ttypes.Insanity({ +export const crazy = new ttypes.Insanity({ userMap: { "5": 5, "8": 8 }, xtructs: [ new ttypes.Xtruct({ @@ -146,7 +147,7 @@ const crazy = new ttypes.Insanity({ ] }); -const crazy2 = new ttypes.Insanity({ +export const crazy2 = new ttypes.Insanity({ userMap: { "5": 5, "8": 8 }, xtructs: [ { @@ -164,17 +165,7 @@ const crazy2 = new ttypes.Insanity({ ] }); -const insanity = { +export const insanity = { "1": { "2": crazy, "3": crazy }, "2": { "6": { userMap: {}, xtructs: [] } } }; - -module.exports.simple = simple; -module.exports.deep = deep; -module.exports.deepUnordered = deepUnordered; - -module.exports.out = out; -module.exports.out2 = out2; -module.exports.crazy = crazy; -module.exports.crazy2 = crazy2; -module.exports.insanity = insanity; diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh index 144832ee43d..c5a0d572355 100755 --- a/lib/nodejs/test/testAll.sh +++ b/lib/nodejs/test/testAll.sh @@ -35,25 +35,23 @@ REPORT_PREFIX="${DIR}/../coverage/report" COUNT=0 -export NODE_PATH="${DIR}:${DIR}/../lib:${NODE_PATH}" - testServer() { - echo " [ECMA $1] Testing $2 Client/Server with protocol $3 and transport $4 $5"; + echo " [Variant: $1] Testing $2 Client/Server with protocol $3 and transport $4 $5"; RET=0 if [ -n "${COVER}" ]; then - ${ISTANBUL} cover ${DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint -- --type $2 -p $3 -t $4 $5 & + ${ISTANBUL} cover ${DIR}/server.mjs --dir ${REPORT_PREFIX}${COUNT} --handle-sigint -- --type $2 -p $3 -t $4 $5 & COUNT=$((COUNT+1)) else - node ${DIR}/server.js --${1} --type $2 -p $3 -t $4 $5 & + node ${DIR}/server.mjs --${1} --type $2 -p $3 -t $4 $5 & fi SERVERPID=$! sleep 0.1 if [ -n "${COVER}" ]; then - ${ISTANBUL} cover ${DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} -- --${1} --type $2 -p $3 -t $4 $5 || RET=1 + ${ISTANBUL} cover ${DIR}/client.mjs --dir ${REPORT_PREFIX}${COUNT} -- --${1} --type $2 -p $3 -t $4 $5 || RET=1 COUNT=$((COUNT+1)) else - node ${DIR}/client.js --${1} --type $2 -p $3 -t $4 $5 || RET=1 + node ${DIR}/client.mjs --${1} --type $2 -p $3 -t $4 $5 || RET=1 fi kill -2 $SERVERPID || RET=1 wait $SERVERPID @@ -94,6 +92,10 @@ mkdir ${DIR}/gen-nodejs-es6 ${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/v0.16/ThriftTest.thrift ${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift ${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/Int64Test.thrift +mkdir ${DIR}/gen-nodejs-esm +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-esm --gen js:node,es6,esm ${THRIFT_FILES_DIR}/v0.16/ThriftTest.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-esm --gen js:node,es6,esm ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-esm --gen js:node,es6,esm ${THRIFT_FILES_DIR}/Int64Test.thrift # generate episodic compilation test code TYPES_PACKAGE=${EPISODIC_DIR}/node_modules/types-package @@ -130,11 +132,11 @@ do do for transport in buffered framed do - for ecma_version in es5 es6 + for gen_variant in es5 es6 esm do - testServer $ecma_version $type $protocol $transport || TESTOK=1 - testServer $ecma_version $type $protocol $transport --ssl || TESTOK=1 - testServer $ecma_version $type $protocol $transport --callback || TESTOK=1 + testServer $gen_variant $type $protocol $transport || TESTOK=1 + testServer $gen_variant $type $protocol $transport --ssl || TESTOK=1 + testServer $gen_variant $type $protocol $transport --callback || TESTOK=1 done done done diff --git a/lib/nodejs/test/test_driver.js b/lib/nodejs/test/test_driver.mjs similarity index 96% rename from lib/nodejs/test/test_driver.js rename to lib/nodejs/test/test_driver.mjs index 7c9a91914bf..85e9c8a3498 100644 --- a/lib/nodejs/test/test_driver.js +++ b/lib/nodejs/test/test_driver.mjs @@ -26,15 +26,18 @@ // supports an optional callback function which is called with // a status message when the test is complete. -const test = require("tape"); +import test from "tape"; -const helpers = require("./helpers"); -const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); -const TException = require("thrift").Thrift.TException; -const Int64 = require("node-int64"); -const testCases = require("./test-cases"); +import helpers from "./helpers.js"; +import thrift from "thrift"; +import Int64 from "node-int64"; +import * as testCases from "./test-cases.mjs"; -exports.ThriftTestDriver = function(client, callback) { +const ttypes = await import(`./${helpers.genPath}/ThriftTest_types.${helpers.moduleExt}`); + +const TException = thrift.Thrift.TException; + +export const ThriftTestDriver = function(client, callback) { test( "NodeJS Style Callback Client Tests", { skip: helpers.ecmaMode === "es6" }, @@ -162,7 +165,7 @@ exports.ThriftTestDriver = function(client, callback) { } }; -exports.ThriftTestDriverPromise = function(client, callback) { +export const ThriftTestDriverPromise = function(client, callback) { test("Promise Client Tests", function(assert) { const checkRecursively = makeRecursiveCheck(assert); diff --git a/lib/nodejs/test/test_handler.js b/lib/nodejs/test/test_handler.mjs similarity index 95% rename from lib/nodejs/test/test_handler.js rename to lib/nodejs/test/test_handler.mjs index 317a7c81016..e7f13125111 100644 --- a/lib/nodejs/test/test_handler.js +++ b/lib/nodejs/test/test_handler.mjs @@ -19,9 +19,11 @@ //This is the server side Node test handler for the standard // Apache Thrift test service. -const helpers = require("./helpers"); -const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); -const TException = require("thrift").Thrift.TException; +import helpers from "./helpers.js"; +import thrift from "thrift"; + +const ttypes = await helpers.importTypes(`ThriftTest_types`); +const TException = thrift.Thrift.TException; function makeSyncHandler() { return function(thing) { @@ -217,4 +219,4 @@ identityHandlers.forEach(function(label) { asyncHandlers[label] = makeAsyncHandler(label); }); -exports.ThriftTestHandler = asyncHandlers; +export { asyncHandlers as ThriftTestHandler };