-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I'm not entirely sure what you intended we do with this PR.
.travis.yml
Outdated
@@ -14,17 +14,7 @@ matrix: | |||
fast_finish: true | |||
include: | |||
- node_js: '9' | |||
env: TARGET=test.node COVERAGE=true | |||
- node_js: '8' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can't just remove all of these from the build matrix...
@@ -10,7 +10,7 @@ | |||
const spawn = require('child_process').spawn; | |||
const path = require('path'); | |||
const getOptions = require('./options'); | |||
const args = [path.join(__dirname, '_mocha')]; | |||
const args = [path.join(__dirname, '_mocha.js')]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this necessary?
* 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand where this is supposed to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably shouldn't use 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-modules
which 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 <= 8
unless the user passes thees-modules
flag.Currently running a script in node with
--experimental-modules
fails if the file does not have an extension which means thatnode --experimental-modules bin/_mocha
files. 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.