-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
module: add module.detectSyntax #57731
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
module: add module.detectSyntax #57731
Conversation
Review requested:
|
0179219
to
30c7248
Compare
import { detectSyntax } from 'node:module'; | ||
// This could be CommonJS if we interpret < and > as greater and lesser, | ||
// or it could be TypeScript if we interpret them as type parameters. | ||
// In this case, it will be interpreted as TypeScript. |
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.
this seems potentially problematic, since TS isn't a syntactic superset of JS. Perhaps in this case it could return an array of two choices?
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.
it's an edge case, how do you detect it? 😄 I guess it has to be clear its heuristic, it trades some correctness for convenience
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.
if it can be parsed as both, then it's the edge case.
since this function is intended to be used by libraries and not by most users, it seems like correctness is the better tradeoff to make here. Doing result?.[0] ?? result
isn't that inconvenient, but allows the choice and visibility into the edge cases.
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 only way I see to disambiguate the syntax is to compileScript
and see if it works, and attempt to strip types and if the output is different, it means its an edge case.
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.
Sure, that seems fine to me.
The internal function is named Especially as the world transitions to ESM, it’s not a safe assumption to conclude that any file lacking ESM syntax is therefore CommonJS. That’s the assumption that Node’s module syntax detection makes for the purposes of running an ambiguous file, where CommonJS is the longstanding default behavior; but a new API shouldn’t assume that code that isn’t unambiguously ESM is therefore CommonJS (or anything else). If you want to provide something useful for libraries, I would suggest exposing the internal |
That is partially relevant. |
Co-authored-by: Geoffrey Booth <[email protected]>
What is the use case that this function solves? The comment you cite, #57298 (comment), has a need to know how Node will run a particular file, including based on all those other indicators like file extension and |
Other steps to detect the syntax are already covered by other APIs. This api will eventually group all those functionality in one. But this is something that is needed, especially for .ts files |
I’m not seeing what exactly the use case is here. Also if the lower-level APIs like |
This is litteraly a wrapper around |
I can see use cases for exposing I am hesitant about the API in this PR, since it returns strings that look like the module hook formats or the module conditions, but are determined via different rules than how Node internally determines module formats or conditions. That strikes me as having great potential for user confusion and frustration, and it wouldn’t solve the problem that prompted this PR. If we’re going to provide an API for “how would Node handle a particular path?” or “how would Node evaluate a particular string?” then these APIs should return the same answers as Node internals would. |
For mochajs/mocha#5314, should mocha read the file and use this new |
Yes that is the idea |
I think for mochajs/mocha#5314, we should not rely on TypeScript module syntax to determine its module format. TypeScript module syntax is not reliable, e.g. as tsconfig.json For frameworks like mocha, it should defer to node's built-in module loader to determine module format. Not TS syntax. This may be useful, when strip-types is the dominant flavour though (?). |
detectSyntax('export const a: number = 1;'); // 'module-typescript' | ||
detectSyntax('const a: number = 1;'); // 'commonjs-typescript' | ||
detectSyntax('const foo;'); // Invalid syntax, returns undefined | ||
``` |
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.
Maybe this should instead return two booleans where one indicates if the code contained module specific syntax and the other whether it contained typescript syntax? Stating const a = 1;
is commonjs isn't exactly accurate because that can't be determined solely from the text, as alluded to in the description.
Fixes some issue that libraries have to determine the syntax of certain files
#57298 (comment)
since they rely on executing them and checking the error message