WIP: use dynamic import to load es module tests.#3253
Conversation
When the --es-modules flag is provided import() will be used to load all test files.
node 9.6 will not allow script files without .js extensions when --experimental-modules flag is passed. I think node 9.7 will allow this so this commit can be reverted then.
Node versions less than 9.6 do not support dynamic es imports. Currently using instanbul to calculate codecoverage calls some script without a .js file extension which causes the tests to fail. Hopefully in v9.7 this will be fixed.
856c911 to
10736aa
Compare
Adds an integration test that uses cjs modules but is called with the --es-modules flag.
0108699 to
e1ad789
Compare
Dynamic imports are async and therefore errors need to be explicitly handled.
|
This seems to break AppVeyor's build, but why? |
boneskull
left a comment
There was a problem hiding this comment.
Thanks. I'm not entirely sure what you intended we do with this PR.
| include: | ||
| - node_js: '9' | ||
| env: TARGET=test.node COVERAGE=true | ||
| - node_js: '8' |
There was a problem hiding this comment.
we can't just remove all of these from the build matrix...
| const path = require('path'); | ||
| const getOptions = require('./options'); | ||
| const args = [path.join(__dirname, '_mocha')]; | ||
| const args = [path.join(__dirname, '_mocha.js')]; |
| * Load registered files via es6 dynamic imports. | ||
| * | ||
| * Note: `eval` is used in this function or else mocha will not | ||
| * compile on older node versions. |
There was a problem hiding this comment.
I don't understand where this is supposed to work.
There was a problem hiding this comment.
The new import() operator allows ECMAScript Modules to be loaded dynamically. The hope was that tests written as modules (i.e. tests including import obj from './script.js' statements) can be loaded into Mocha using dynamic imports without having to first use a transpiler to convert ECMAScript Modules into common js modules.
There was a problem hiding this comment.
right, but I'm unclear on why we're removing old versions of Node.js from the matrix.
Current support for modules in node is experimental. It is likely that mocha will want to wait untill node starts properly supporting modules before merging this pr.
if we're going to break backwards compatibility, then it'd have to wait until the oldest version of Node.js that supports modules is no longer maintained. that'll be a few years. so, that's why I'm trying to understand what I'm supposed to do with this...
There was a problem hiding this comment.
Sorry, I didn't mean to add that change to the pull request, I will revert it.
The idea was that mocha could add a new CLI flag which would cause mocha to use the new import() instead of require() to load test files.
This new CLI flag could only be used on the most recent versions of node but mocha would work normally if this flag was not set.
The tests fail because I added a test for the new flag and travis/appveyor runs this test on old versions of node, I didn't know how to work around that.
| file = path.resolve(file); | ||
| suite.emit('pre-require', global, file, self); | ||
| return eval('import(file)') | ||
| .then(function (module) { |
|
Why was this PR closed? I am currently using Mocha together with |
|
Until modules are unflagged and/or no longer considered "experimental", I'm concerned about adopting something too soon. Specifically, when there's agreement in core around interop between |
|
Thanks for the reply: it's a fair reason. I was worried that there was an issue with the PR preventing it from working. Still, it's good to know that it's a Node stability issue instead and that you are able to add support for it when possible. |
|
I was a bit optimistic with this PR, definately need to wait until modules are finalised in node. The other problem, which is why my work was so hacky, is that the dynamic |
|
Hi, A possible way to prepare the support for ESM would be to force the current imports to be async by default: replace the resolution code from Looking at the PR, it seems that most of the code is already async. I am not familiar enough with mocha's codebase so maybe my suggestion is not needed. I just hope that Mocha will be able to support ESM when available. |
|
@demurgos from memory it should be fairly straightforward to make that change |
Description of the Change
Uses the new (and as yet highly experimental) support in node for dynamically loading modules using
const obj = await import('./file-name.mjs');.I have added a new command line flag
--es-moduleswhich causes mocha to useimport()instead ofrequire()to load test files.This allows tests to
import obj from './somefile.mjs'without having to transpile tests before running them.Obviously this only works in the very latest node version. This commit does not break mocha in
node <= 8unless the user passes thees-modulesflag.Currently running a script in node with
--experimental-modulesfails if the file does not have an extension which means thatnode --experimental-modules bin/_mochafiles. From my understanding (see nodejs/node#18728) node v9.7 will be able to run scripts without the .js extension.Alternate Designs
Current design works fine as long as users are happy to use a transpiler.
Why should this be in core?
Cannot be implemented outside of core.
Benefits
Tests can be written as es modules.
Possible Drawbacks
Current support for modules in node is experimental. It is likely that mocha will want to wait untill node starts properly supporting modules before merging this pr.
Applicable issues
#3006
Probably semver minor but could be major.