diff --git a/test/other/embind_tsgen_main.ts b/test/other/embind_tsgen_main.ts index a3a39683245af..8b4588e85643c 100644 --- a/test/other/embind_tsgen_main.ts +++ b/test/other/embind_tsgen_main.ts @@ -1,30 +1,39 @@ // Example TS program that consumes the emscripten-generated module to to // illustrate how the type definitions are used and test they are workings as // expected. -import moduleFactory from './embind_tsgen.mjs'; -const module = await moduleFactory(); +// The imported file will either be an ES module or a CommonJS module depending +// on the test. +import moduleFactory from './embind_tsgen.js'; -// Test a few variations of passing value_objects with strings. -module.setValObj({ - bar: module.Bar.valueOne, - string: "ABCD", - callback: () => {} -}); +// Async IIFE is required for TSC with commonjs modules. This is not needed for +// ESM output since top level await can be used. +(async function() { -module.setValObj({ - bar: module.Bar.valueOne, - string: new Int8Array([65, 66, 67, 68]), - callback: () => {} -}); + const module = await moduleFactory(); -const valObj = module.getValObj(); -// TODO: remove the cast below when better definitions are generated for value -// objects. -const valString : string = valObj.string as string; + // Test a few variations of passing value_objects with strings. + module.setValObj({ + bar: module.Bar.valueOne, + string: "ABCD", + callback: () => {} + }); -// Ensure nonnull pointers do no need a cast or nullptr check to use. -const obj = module.getNonnullPointer(); -obj.delete(); + module.setValObj({ + bar: module.Bar.valueOne, + string: new Int8Array([65, 66, 67, 68]), + callback: () => {} + }); -console.log('ts ran'); + const valObj = module.getValObj(); + // TODO: remove the cast below when better definitions are generated for value + // objects. + const valString : string = valObj.string as string; + + // Ensure nonnull pointers do no need a cast or nullptr check to use. + const obj = module.getNonnullPointer(); + obj.delete(); + + console.log('ts ran'); + +})(); diff --git a/test/test_other.py b/test/test_other.py index c0c6f33c3d1f0..0162994371a2f 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -3385,21 +3385,24 @@ def test_jspi_add_function(self): self.do_runf('other/test_jspi_add_function.c', 'done') @parameterized({ - '': [[]], - 'with_jsgen': [['-sEMBIND_AOT']] + 'commonjs': [['-sMODULARIZE'], ['--module', 'commonjs', '--moduleResolution', 'node']], + 'esm': [['-sEXPORT_ES6'], ['--module', 'NodeNext', '--moduleResolution', 'nodenext']], + 'esm_with_jsgen': [['-sEXPORT_ES6', '-sEMBIND_AOT'], ['--module', 'NodeNext', '--moduleResolution', 'nodenext']] }) - def test_embind_tsgen(self, opts): + def test_embind_tsgen_end_to_end(self, opts, tsc_opts): # Check that TypeScript generation works and that the program is runs as # expected. self.emcc(test_file('other/embind_tsgen.cpp'), - ['-o', 'embind_tsgen.mjs', '-lembind', '--emit-tsd', 'embind_tsgen.d.ts'] + opts) + ['-o', 'embind_tsgen.js', '-lembind', '--emit-tsd', 'embind_tsgen.d.ts'] + opts) # Test that the output compiles with a TS file that uses the defintions. shutil.copyfile(test_file('other/embind_tsgen_main.ts'), 'main.ts') - # A package file with type=module is needed to enabled ES modules in TSC and - # also run the output JS file as a module in node. - shutil.copyfile(test_file('other/embind_tsgen_package.json'), 'package.json') - cmd = shared.get_npm_cmd('tsc') + ['embind_tsgen.d.ts', 'main.ts', '--module', 'NodeNext', '--moduleResolution', 'nodenext'] + if '-sEXPORT_ES6' in opts: + # A package file with type=module is needed to enabled ES modules in TSC and + # also run the output JS file as a module in node. + shutil.copyfile(test_file('other/embind_tsgen_package.json'), 'package.json') + + cmd = shared.get_npm_cmd('tsc') + ['embind_tsgen.d.ts', 'main.ts', '--target', 'es2021'] + tsc_opts shared.check_call(cmd) actual = read_file('embind_tsgen.d.ts') self.assertFileContents(test_file('other/embind_tsgen_module.d.ts'), actual) diff --git a/tools/link.py b/tools/link.py index c554bf3e1292c..9e468ff8c34e8 100644 --- a/tools/link.py +++ b/tools/link.py @@ -2491,9 +2491,12 @@ def modularize(): src += 'export default %s;\n' % settings.EXPORT_NAME elif not settings.MINIMAL_RUNTIME: src += '''\ -if (typeof exports === 'object' && typeof module === 'object') +if (typeof exports === 'object' && typeof module === 'object') { module.exports = %(EXPORT_NAME)s; -else if (typeof define === 'function' && define['amd']) + // This default export looks redundant, but it allows TS to import this + // commonjs style module. + module.exports.default = %(EXPORT_NAME)s; +} else if (typeof define === 'function' && define['amd']) define([], () => %(EXPORT_NAME)s); ''' % {'EXPORT_NAME': settings.EXPORT_NAME}