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

ESM fix for node 14.13.1 breaking change #1130

Closed
cspotcode opened this issue Oct 11, 2020 · 5 comments · Fixed by #1136
Closed

ESM fix for node 14.13.1 breaking change #1130

cspotcode opened this issue Oct 11, 2020 · 5 comments · Fixed by #1136

Comments

@cspotcode
Copy link
Collaborator

Pretty sure it's cuz the URL protocol for native modules changed from nodejs: to node: and has to do with our necessary forking of node's resolver.

Fix must:

  • be backwards compatible (at least in the short-term). Before 14.13.1 needs to use nodejs:; after needs to use node:
  • test suite updated to run 14.13.0 and 14.13.1 (or at least one 14.x version before and one after)
  • specs should attempt to load native modules without import elision

Relevant conversation starts here: #1007 (comment)

@cspotcode
Copy link
Collaborator Author

Maybe node: vs nodejs: can be feature-detected the first time our resolve implementation is called. defaultResolve('node:fs') and look at what it gives us.

@cspotcode cspotcode mentioned this issue Oct 31, 2020
cspotcode added a commit that referenced this issue Oct 31, 2020
* Test against additional node versions: 14.13.0 and 15

* Add ESM test of builtin module resolution

* Use version number test to switch node's builtin module URI protocol in ESM resolver

* add new test matrix entries to flavors array
@concision
Copy link
Contributor

concision commented Nov 5, 2020

If anyone needs a quick fix (as the linked PR has not been released on npm), experimentally this solution seems to work by early deferring Node.js builtin modules (i.e. null specifier). Might not work in 100% of scenarios - your mileage may vary.

Create a new file ts-node-esm-loader-fix.mjs and set the ESM loader to it (e.g. --loader=./ts-node-esm-loader-fix.mjs):

import url from "url";

// initialize ts-node ESM loader; promise to early initialize
const esmLoader = new Promise(async (resolve, reject) => {
    try {
        resolve(await import("ts-node/esm.mjs"));
    } catch (error) {
        reject(error);
    }
});

// delegate to ts-node ESM loader
export async function resolve(specifier, context, defaultResolve) {
    // resolves change from 'nodejs:' to 'node:'
    if (url.parse(specifier).protocol === null) return defaultResolve(...arguments);
    return (await esmLoader).resolve(...arguments);
}
export async function getFormat() {
    return (await esmLoader).getFormat(...arguments);
}
export async function transformSource() {
    return (await esmLoader).transformSource(...arguments);
}

@cspotcode
Copy link
Collaborator Author

cspotcode commented Nov 5, 2020 via email

@cspotcode
Copy link
Collaborator Author

Npm can install ts-node directly from github instead of npmjs.com, allowing you to use the latest code from master.

@concision
Copy link
Contributor

Ah, I did not realize that npm/yarn will build a module directly from GitHub! Thanks for letting me know! And thank you for your work on ts-node! :)

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 a pull request may close this issue.

2 participants