Skip to content

only search require calls in JS files #28168

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

Closed
wants to merge 4 commits into from

Conversation

ajafff
Copy link
Contributor

@ajafff ajafff commented Oct 26, 2018

require('foo') in TypeScript files has no special meaning. Therefore we don't need to look it up and treat it like an import. It used to be in the same function as the lookup of dynamic imports to find both in one full AST walk.

  • removed useless parameters as the SourceFile was already in scope
  • split lookup function into two separate functions
  • only look for require calls in JS files
  • only look at JSDoc when searching ImportTypeNode in JS files (require will never be in JSDoc anyway)
  • slightly optimized the regex while keeping it readable

Followup on #28104 /cc @sandersn

@ajafff
Copy link
Contributor Author

ajafff commented Oct 26, 2018

This change uncovered some pretty surprising behavior: if you have require('something') in your code (it could even be a local function named require), it would resolve that module like a regular import and include its declaration file into the program.
For the same reason @types/node was implicitly included in the compilation of src/compiler. After this change I had to explicitly reference that declaration file to make it compile again.

@sandersn
Copy link
Member

@DanielRosenwasser and I had a long discussion about @types/node, since this incorrect behaviour has existed since April 2017 [1]. I think it's OK to take this fix as long as we note that it's a breaking change and improve the "Are you missing node" error.

Specifically,
Change "Try npm i @types/node" to
"Try npm i @types/node and then add node to the types field in your tsconfig."

Adding @DanielRosenwasser to the review for signoff on the error message change.

[1] Note that the behaviour has existed for longer in JS, but is probably a good idea there.

@sandersn
Copy link
Member

There's also a number of new "Cannot find module 'x'" messages in the prettier user test. Mind checking those out? jake runtests ru=user t=prettier, and then you can open the project in $ts/tests/cases/user/prettier/prettier

@ajafff
Copy link
Contributor Author

ajafff commented Oct 28, 2018

There's also a number of new "Cannot find module 'x'" messages in the prettier user test.

There are baseline changes, but they are the same in this branch an in master.

I think it's OK to take this fix as long as we note that it's a breaking change and improve the "Are you missing node" error.

I agree the proposed error message makes more sense, but I don't think it's strictly related to this PR. There are a few more error messages suggesting installing @types/jquery, @types/jest or @types/mocha. Should they be changed, too?

Note that this change will not only break code that implicitly relies on @types/node. It will break compilation of TypeScript files that contain require('foo') where 'foo' resolves to a declaration file containing declarations of ambient modules or global variables which are used in the program without being explicitly referenced (through import, types in tsconfig or a type reference directive).

if ((file.flags & NodeFlags.PossiblyContainsDynamicImport)) {
collectDynamicImports();
}
if (isJavaScriptFile) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can still keep this a single pass by passing regexp instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's possible, but IMO not very useful. It would save around 4 lines of code just to add new code to get determine the correct regexp to use. It also adds complexity by moving the regexp out of the function where its matches are used.
I doubt having a single pass of a complex regexp outperforms two passes with a simple regex each (also considering potential inlining).

Copy link
Member

Choose a reason for hiding this comment

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

It will save pass I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Like I already said: I don't think there will be a noticeable difference in performance because of optimizations in the VM (like inlining). It's not like we are walking the whole AST twice.

@RyanCavanaugh
Copy link
Member

What's the observable breaking change here?

@ajafff
Copy link
Contributor Author

ajafff commented Jan 25, 2019

What's the observable breaking change here?

Having types: [] in tsconfig.json would normally prevent non-module declaration files from introducing any global augmentations.
But if you had require('foo') or a JSDoc import import('foo') in a TypeScript file, that was resolved to @types/foo, these declaration files were added to the program and thus can augment the global namespace.

This occurred to me in this PR because there is require('fs') which caused @types/node to be loaded. This implicitly introduced require, module and all those other global declarations.
This was counterintuitive as require and JSDoc import-types shouldn't have any special meaning in TS files.

@sandersn sandersn added the For Backlog Bug PRs that fix a backlog bug label Feb 1, 2020
@sheetalkamat
Copy link
Member

Dont think its worth taking this at point given people might be depending on this behavior by now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Backlog Bug PRs that fix a backlog bug
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants