-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
fix(typescript-estree): change mjs/mts files to always be parsed as ESM #9121
base: main
Are you sure you want to change the base?
fix(typescript-estree): change mjs/mts files to always be parsed as ESM #9121
Conversation
Thanks for the PR, @goldentrash! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
* Ensure that `mjs`/`mts` files are always treated as ESM | ||
*/ | ||
if (typeof code === 'string' && isESM(options)) { | ||
code += '\n' + 'export {}'; |
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 cannot change the code at all.
Doing so changes the resulting AST and its ranges.
This may also cause lint rules to report on code that doesn't exist.
We need to accomplish this without mutating the passed code at all.
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.
Ah! I hadn't thought of that, you're right.
I'll think of another way to do it.
Thanks for the review :)
Hi @bradzacher , I've spent the last few days thinking of other ways to achieve our goal without modifying the I found the code below and it seems to be acceptable. /** @internal */
export function getSetExternalModuleIndicator(options: CompilerOptions): (file: SourceFile) => void {
// TODO: Should this callback be cached?
switch (getEmitModuleDetectionKind(options)) {
case ModuleDetectionKind.Force:
// All non-declaration files are modules, declaration files still do the usual isFileProbablyExternalModule
return (file: SourceFile) => {
file.externalModuleIndicator = isFileProbablyExternalModule(file) || !file.isDeclarationFile || undefined;
};
case ModuleDetectionKind.Legacy:
// Files are modules if they have imports, exports, or import.meta
return (file: SourceFile) => {
file.externalModuleIndicator = isFileProbablyExternalModule(file);
};
case ModuleDetectionKind.Auto:
// If module is nodenext or node16, all esm format files are modules
// If jsx is react-jsx or react-jsxdev then jsx tags force module-ness
// otherwise, the presence of import or export statments (or import.meta) implies module-ness
const checks: ((file: SourceFile, options: CompilerOptions) => Node | true | undefined)[] = [isFileProbablyExternalModule];
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
checks.push(isFileModuleFromUsingJSXTag);
}
checks.push(isFileForcedToBeModuleByFormat);
const combined = or(...checks);
const callback = (file: SourceFile) => void (file.externalModuleIndicator = combined(file, options));
return callback;
}
} Would this be acceptable? |
PR Checklist
Overview
Change
mjs
/mts
files to always be parsed by ESMHow I solved this problem - new apporach
setExternalModuleIndicator
to always returntrue
if the file ismjs
/mts
.How I solved this problemIf the extension of the file ismjs
/mts
viaParseOptions.filePath
, add an empty export at the end of the source code: (export {};
)This method was inspired by a long-time favorite method for resolvingisolatedModules
errors that originate from tsconfig settings.According to MDN documentation, this method does not affect functionality or logic.export {}
does not export an empty object — it's a no-op declaration that exports nothing (an empty name list).Reasons not to modify
convertNode
andcreateSourceFile
./tyscript-estree/src/convert.ts/Converter/convertNode
, modifyingsourceType
when it iscase SyntaxKind.SourceFile
does not make sense, I have left the details in the issue.createSourceFile
relies on an external module called typescript (ts.createSourceFile
), tweaking the parameters of this module is the only way to keep it out of scope of typescript-eslint.AdjustingsetExternalModuleIndicator
doesn't make sense, I've left the details in an issue.impliedNodeFormat
doesn't make sense, I've left the details in an issue.Why I thought it was in-appropriate to look for another API instead of
ts.createSourceFile
.typescript-estree
relies heavily on the return value ofts.createSourceFile
.breaking-change
.If you have any feedback on function/variable naming or code block repositioning, I'll take it on board and fix the PR.