Skip to content
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

Support ECMAScript modules (ESM) #251

Closed
wants to merge 7 commits into from
Closed

Support ECMAScript modules (ESM) #251

wants to merge 7 commits into from

Conversation

davidtheclark
Copy link
Collaborator

This PR intends to close #224. I don't have more time to work on this today so I'll get what I have up as a draft — feedback welcome! I'd especially appreciate help testing this from people interested in using ESM, both ensuring that it works as expected and ensuring that the expectations are the right ones.

Some notes:

  • ESM is only supported by the asynchronous API, because it is enabled by the asynchronous import() function.
  • So .mjs is only added to the default searchPlaces of the asynchronous API.
  • I turned off the selective branches in CI configuration because I wasn't seeing tests run. It may be that Travis and Appveyor needed to catch up with the main branch name change (from master to main). We'll see.
  • I was having some trouble early on with Jest, so tried using the jest-circus test runner. Turns out that wasn't the problem at all, but I left in that update.
  • This PR is set to merge into a v8 branch, in case there's anything else in the issue queue that anybody wants to get into v8.

@codecov-io
Copy link

Codecov Report

Merging #251 (7c28c3e) into v8 (1834605) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##                v8      #251   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            9         9           
  Lines          227       235    +8     
  Branches        46        47    +1     
=========================================
+ Hits           227       235    +8     
Impacted Files Coverage Δ
src/ExplorerBase.ts 100.00% <ø> (ø)
src/index.ts 100.00% <100.00%> (ø)
src/loaders.ts 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1834605...7c28c3e. Read the comment docs.

@davidtheclark
Copy link
Collaborator Author

davidtheclark commented Feb 14, 2021

Known to-dos:

@davidtheclark
Copy link
Collaborator Author

By using the --experimental-vm-modules flag and some workarounds for the inability to clear the ESM loader cache, the tests are now passing for me locally. But on Travis, they are not, with segmentation faults in Node 10 and 14 and something else in Node 12 I don't understand yet.

@@ -16,6 +17,18 @@ const loadJs: LoaderSync = function loadJs(filepath) {
return result;
};

const loadJs: LoaderAsync = async function loadJs(filepath) {
// This logic is validated by tests running in Node versions that don't
// support dynamic imports, like Node 10.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it specific versions of Node 10 that don't support dynamic import syntax?

Using this site, 9.2.0 gives a SyntaxError, but 10.1.0 doesn't.

I think this will fail when the syntax is supported, but the feature is not (f.e. when --experimental-modules is needed).

Since v10 EOL is just around the corner, it's probably easier to just wait until then (2021-04-30), and drop support for it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since v10 EOL is just around the corner, it's probably easier to just wait until then (2021-04-30), and drop support for it.

I would just drop support for Node.js 10 now. It's 10 days left. This will not be released until then anyway.

// support dynamic imports, like Node 10.
/* istanbul ignore else */
if (canUseDynamicImport()) {
const imported = await import(filepath);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An import call will syntax error in node versions that do not support it. In a PR I'm fiddling with to support ESM in tape I side step this syntax error by conditionally requiring another file containing the import statement...

The conditional require:
https://github.com/lohfu/tape/blob/esm-support/bin/tape#L29

The separate file:
https://github.com/lohfu/tape/blob/esm-support/bin/load-module-esm-support.js

Since dynamic imports seem to be up to 5 times slower than require, we conditionally use import or require by checking file extensions and get-package-type. As you probably load far less files this might not be necessary for you.

Copy link

@lohfu lohfu May 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you dont want to conditionally use require vs import, you could just use the function you create to check dynamic import support, https://github.com/davidtheclark/cosmiconfig/pull/251/files#diff-e61e569af4ed5c2bd19c648e11225dd502296f0931b339c88cb82288a493e6adR6.

ie something like:

let dynamicImport;

try {
  dynamicImport = new Function('id', 'return import(id);');
} catch (e) {} 

// later

const loadJs: LoaderAsync = async function loadJs(filepath) {
  if (dynamicImport) {
    const imported = await dynamicImport(filepath);

    return imported.default;
  } else {
    return loadJsSync(filepath, null);
  }
};

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it appears it's even trickier... versions 10.0.0 - 12.16 and 13.0 - 13.1 support the import keyword, but will throw a "Not Supported" error when called. See inspect-js/has-dynamic-import#2 for an attempted work around.

@perrin4869
Copy link

The segfault issue is probably caused by nodejs/node#35889

@davidtheclark
Copy link
Collaborator Author

Just posted this note at the top of the README:

MAINTAINERS WANTED! If you're interested in taking over and maintaining Cosmiconfig, please let @davidtheclark know (with an issue or email). I'd like to hand over the keys completely, so I'm looking for owners, not people who just want to merge a PR or two! You can make the decisions about what happens in v8 and subsequent versions, how the package balances stability and opinionated features, and so on. Take a look at open issues and PRs to learn about possibilities that have been on people's minds over the years.

If you're interested in taking ownership of the package and moving this feature forward, let me know!

@d-fischer
Copy link
Member

This was superseded by #304, which is now merged.

@d-fischer d-fischer closed this Jun 4, 2023
@jrandolf jrandolf deleted the esm branch September 1, 2023 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants