Repository: mochajs/mocha

Problem statement:
If one among multiple ESM tests has a syntax error, then Mocha doesn’t report which one
### Prerequisites

<!--
Place an `x` between the square brackets on the lines below for every satisfied prerequisite.
-->

- [x] Checked that your issue hasn't already been filed by cross-referencing [issues with the `faq` label](https://github.com/mochajs/mocha/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Afaq%20)
- [x] Checked next-gen ES issues and syntax problems by using the same environment and/or transpiler configuration without Mocha to ensure it isn't just a feature that actually isn't supported in the environment in question or a bug in your code.
- [x] 'Smoke tested' the code to be tested by running it outside the real test suite to get a better sense of whether the problem is in the code under test, your usage of Mocha, or Mocha itself
- [x] Ensured that there is no discrepancy between the locally and globally installed versions of Mocha. You can find them with: `node node_modules/.bin/mocha --version`(Local) and `mocha --version`(Global). We recommend that you _not_ install Mocha globally.

### Description

If I run multiple ESM tests (e.g. via `npm t test*.mjs`), and one of them has a syntax error, then Mocha doesn’t tell me which file it is.

### Steps to Reproduce

Repository with MCVE: https://github.com/rauschma/mocha-test-repo

Execute either of the following two commands:

```
npm t test*.mjs
npm t 'test*.mjs'
```

`test2.mjs` has a syntax error.

**Expected behavior:** I’d like Mocha to tell me which file has the syntax error.

**Actual behavior:** I’m getting the following error message.

```
SyntaxError: Unexpected token '=>'
    at Loader.moduleStrategy (internal/modules/esm/translators.js:117:18)
    at async link (internal/modules/esm/module_job.js:42:21)
```

**Reproduces how often:** 100%

### Versions

- The output of `mocha --version` and `node node_modules/.bin/mocha --version`: 8.2.1 (there is no globally installed Mocha)
- The output of `node --version`: v14.15.4



Hints:

Patch:
diff --git a/lib/esm-utils.js b/lib/esm-utils.js
--- a/lib/esm-utils.js
+++ b/lib/esm-utils.js
@@ -3,7 +3,29 @@ const url = require('url');
 
 const formattedImport = async file => {
   if (path.isAbsolute(file)) {
-    return import(url.pathToFileURL(file));
+    try {
+      return await import(url.pathToFileURL(file));
+    } catch (err) {
+      // This is a hack created because ESM in Node.js (at least in Node v15.5.1) does not emit
+      // the location of the syntax error in the error thrown.
+      // This is problematic because the user can't see what file has the problem,
+      // so we add the file location to the error.
+      // This `if` should be removed once Node.js fixes the problem.
+      if (
+        err instanceof SyntaxError &&
+        err.message &&
+        err.stack &&
+        !err.stack.includes(file)
+      ) {
+        const newErrorWithFilename = new SyntaxError(err.message);
+        newErrorWithFilename.stack = err.stack.replace(
+          /^SyntaxError/,
+          `SyntaxError[ @${file} ]`
+        );
+        throw newErrorWithFilename;
+      }
+      throw err;
+    }
   }
   return import(file);
 };


Test patch:
diff --git a/test/integration/esm.spec.js b/test/integration/esm.spec.js
--- a/test/integration/esm.spec.js
+++ b/test/integration/esm.spec.js
@@ -1,5 +1,7 @@
 'use strict';
-var run = require('./helpers').runMochaJSON;
+var helpers = require('./helpers');
+var run = helpers.runMochaJSON;
+var runMochaAsync = helpers.runMochaAsync;
 var utils = require('../../lib/utils');
 var args =
   +process.versions.node.split('.')[0] >= 13 ? [] : ['--experimental-modules'];
@@ -38,6 +40,17 @@ describe('esm', function() {
     });
   });
 
+  it('should show file location when there is a syntax error in the test', async function() {
+    var fixture = 'esm/syntax-error/esm-syntax-error.fixture.mjs';
+    const err = await runMochaAsync(fixture, args, {stdio: 'pipe'}).catch(
+      err => err
+    );
+    expect(err.output, 'to contain', 'SyntaxError').and(
+      'to contain',
+      'esm-syntax-error.fixture.mjs'
+    );
+  });
+
   it('should recognize esm files ending with .js due to package.json type flag', function(done) {
     if (!utils.supportsEsModules(false)) return this.skip();
 
diff --git a/test/integration/fixtures/esm/syntax-error/esm-syntax-error.fixture.mjs b/test/integration/fixtures/esm/syntax-error/esm-syntax-error.fixture.mjs
new file mode 100644
--- /dev/null
+++ b/test/integration/fixtures/esm/syntax-error/esm-syntax-error.fixture.mjs
@@ -0,0 +1,3 @@
+// This is intentionally a syntax error
+it('should never run because of a syntax error here', => {
+});