Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add moduleDetection compiler flag to allow for changing how modules are parsed#47495

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
weswigham merged 10 commits intomicrosoft:mainfromweswigham:parser-new-signature
Mar 11, 2022

Conversation

@weswigham
Copy link
Member

@weswighamweswigham commentedJan 18, 2022
edited
Loading

The default setting is'auto', where JSX containing files under react-jsx and react-jsxdev are
always parsed as modules, and esm-format files under module: node12+ are always parsed as modules,
in addition to the 'legacy' detection mode's conditions for other files. (Declaration files are exempt from
these new conditions)

The'legacy' mode preserves TS's behavior prior to the introduction of this flag - a file is
parsed as a module if it contains an import, export, or import.meta expression.

In addition, there is a'force' mode that forces all non-declaration files to be parsed as modules.
(Declaration files are still only modules if they contain a top-level import or export.)

This technically breaks the parser API, but it's kinda-sorta backwards compatible so long
as you don't need the functionality associated with more recent compiler flags.

While"auto" is a mostly backwards compatible new default (technically it breaksreact-jsx output, but it does so in a case where the output was nonfunctional and fixes it, so it's fine), most people probably just want to use"force" unless they intend to have script files in their compilation.

"moduleDetection": "auto" (the new default):
Fixes#46723
Fixes#40501
Fixes#47237

"moduleDetection": "force":
Fixes#18232
Fixes#14279

robpalme and nayeemrmn reacted with heart emoji
…re parsedThe default setting is 'auto', where JSX containing files under react-jsx and react-jsxdev arealways parsed as modules, and esm-format files under module: node12+ are always parsed as modules,in addition to the 'legacy' detection mode's conditions for other files. (Declaration files are exempt fromthese new conditions)The 'legacy' mode preserves TS's behavior prior to the introduction of this flag - a file isparsed as a module if it contains an import, export, or import.meta expression.In addition, there is a 'force' mode that forces all non-declaration files to be parsed as modules.(Declaration files are still only modules if they contain a top-level import or export.)This technically breaks the parser API, but it's kinda-sorta backwards compatible so longas you don't need the functionality associated with more recent compiler flags.
@typescript-bottypescript-bot added Author: Team For Milestone BugPRs that fix a bug with a specific milestone labelsJan 18, 2022
@weswighamweswigham requested review fromamcasey,andrewbranch andsandersn and removed request forandrewbranchJanuary 18, 2022 21:27
@sandersn
Copy link
Member

Can you add an explanation to the PR description of why 'legacy' is needed -- basically, what you expect to break if everybody were upgraded to 'auto' with no escape hatch.

@weswigham
Copy link
MemberAuthor

weswigham commentedJan 19, 2022
edited
Loading

Hm, I alluded to it, but it would break people with global script files usingreact-jsx orreact-jsxdev with jsx tags in them thatsomehow were post-processing them to actually work (since they didn't by default, but also weren't an error). Hopefully that's a vanishingly small population.

@andrewbranch
Copy link
Member

esm-format files under module: node12+

Does this include.ts files when there’s a package.json with"type": "module"?

@weswigham
Copy link
MemberAuthor

Yep.

andrewbranch reacted with hooray emoji

Comment on lines +3614 to +3618
* The callback used to set the external module indicator - this is saved to
* be later reused during incremental reparsing, which otherwise lacks the information
* to set this field
*/
/*@internal */setExternalModuleIndicator?:(file:SourceFile)=>void;
Copy link
Member

Choose a reason for hiding this comment

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

which otherwise lacks the information to set this field

Why is this the case now but not before this PR?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Because the module indicator now depends on the compiler options the source file was created with, which the source file retains no direct reference to, and small incremental edits (the kind that don't do a full source file rebuild) don't pass in full options, either, they just reuse the old source file's data - so we have to keep the callback around to reuse in that incremental scenario.

Copy link
Member

Choose a reason for hiding this comment

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

Hm, I forgot that parsing in general, much less incremental parsing, doesn’t have access to CompilerOptions; only the (previously very small) subset of them that it needs. I’m a little worried that this will become a footgun whereby we or other API consumers will accidentally close over and retain something they shouldn’t in this function (it you haven’t seen the implementation, you don’t know a reference to it is stored on the SourceFile—the property is even erased from the public API!). What ifCreateSourceFileOptions took themoduleDetection,module, andtarget from CompilerOptions and stored those, such that the function currently returned bygetSetExternalModuleIndicator would have everything it needs to run on the SourceFile after creation? It would be more properties to store, but more straightforward. It took me a minute to understand the purpose of this indirection.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Hm, while that would be enough for recalculating the correct closure, it doesn't do much to help theimpliedNodeFormat field calculation, which needs extensive host availability anyway. I'm disinclined to make these look likeCompilerOptions because of that - if you just passed in compiler options, you'd be broken in any nodenext type scenarios.

Copy link
Member

Choose a reason for hiding this comment

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

impliedNodeFormat now gets passed intocreateSourceFile (and I wasn’t proposing removing that, for the reason you mentioned), and I was assuming it can’t change duringupdateSourceFile (incremental parsing)—is that right? If so, then incremental parsing doesn’t need to worry aboutimpliedNodeFormat.

@fatcerberus
Copy link

esm-format files under module: node12+ are always parsed as modules

I’m unclear on what constitutes an “esm-format file” if it’s not based on the presence of import/export, seeing as ESM mode is controlled by the runtime, not the file contents. Does this mean node.js semantics, i.e..mts is always a module,.ts is a module only if"type": "module", etc.?

If the above is the case it sounds like I probably want to useforce when targeting ESM in the browser.

@weswigham
Copy link
MemberAuthor

Yes and yes. Esm mode modules are the only ones which transpile to esm output, to whit (cjs mode files transpile to cjs). Honestly, if you're targeting browser modules you probably wantmoduleDetection: force andmodule: esnext, rather thannodenext, since you don't want cjs in your compilation at all.

fatcerberus reacted with thumbs up emoji

Copy link
Member

@sandersnsandersn left a comment

Choose a reason for hiding this comment

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

I think this is a good idea. I made some low-level comments, but I don't understand the higher-level structure enough to make useful comments there.

I'll look at the tests next.

/**
* This is a somewhat unavoidable full tree walk to locate a JSX tag - `import.meta` requires the same,
* but we avoid that walk (or parts of it) if at all possible using the `PossiblyContainsImportMeta` node flag.
* Unfortunately, there's no `NodeFlag` space to do the same for JSX.
Copy link
Member

Choose a reason for hiding this comment

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

should there be? (there might not be any NodeFlags left in any case)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

This bails on the first JSX tag you find in a JSX tag, which is usually almost instantly, so.... probably not? Still, I thinknode.transformFlags & TransformFlags.ContainsJsx probably already tracks the same thing and post-node-factory change should always be set, so... I'll try that out for narrowing the search.

Copy link
Member

@sandersnsandersn left a comment

Choose a reason for hiding this comment

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

Done looking at the tests, just waiting on answers to earlier questions.

@weswighamweswigham requested a review fromsandersnMarch 9, 2022 19:18
@nayeemrmn
Copy link

In addition, there is a'force' mode that forces all non-declaration files to be parsed as modules.
(Declaration files are still only modules if they contain a top-level import or export.)

@weswigham Does having a.cts extension override"moduleDetection": "force"?

@weswigham
Copy link
MemberAuthor

A.cts module is still a module, just a cjs format one instead of an esm one. The flag onforce disables script mode files, which are like, the old global browser global-type scripts.

nayeemrmn reacted with thumbs up emoji

@nayeemrmn
Copy link

Ah okay, the script mode stuff doesn't refer to cjs but old-fashioned browser scripts. Thanks.

@DanielRosenwasserDanielRosenwasser added the Breaking ChangeWould introduce errors in existing code labelApr 7, 2022
@microsoftmicrosoft locked asresolvedand limited conversation to collaboratorsOct 22, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@andrewbranchandrewbranchandrewbranch left review comments

@jakebaileyjakebaileyjakebailey left review comments

@sandersnsandersnsandersn approved these changes

@amcaseyamcaseyAwaiting requested review from amcasey

Assignees

@weswighamweswigham

Labels

Author: TeamBreaking ChangeWould introduce errors in existing codeFor Milestone BugPRs that fix a bug with a specific milestone

Projects

Archived in project

Milestone

No milestone

8 participants

@weswigham@sandersn@andrewbranch@fatcerberus@nayeemrmn@jakebailey@DanielRosenwasser@typescript-bot

[8]ページ先頭

©2009-2025 Movatter.jp