Implement externalModuleIndicator
The infamous externalModuleIndicator field requires access to info like the module setting of the closest package.json in order to work in some situations. This is normally "fine"; just make a sidecar that the Program holds onto. But unfortunately, externalModuleIndicator is needed to know whether or not a given file needs to be reparsed to deal with top-level await, so needs to be there at parse time. This means that it's technically an input to parse, not something on the side.
To deal with this, I've eliminated the SourceFileMetaData sidecar, moving it back onto SourceFile and populating it during parse. This means less AST reuse, however, the info here is effectively entirely derived from the FS (the path and what's on disk), so it's unlikely files that only differed by this metadata were actually sharing anything.
Fixing this eliminates a bunch of random diffs.
I need to look in more detail later, but my immediate thought is that the cache key could have the pre-computed value of “force this file to be a module” instead of all the compiler options that might contribute to that value. Right now, differing moduleResolution or jsx settings will prevent source file reuse, but that needn’t be true if both projects have --moduleDetection force.
That was my thought too, but the trouble is that the indicator is an AST node, because we need to be able to point diagnostics at it in some situations. But, for these new cases they're basically all just what used to be "true", so potentially that would work as a plain boolean passed in.
I'm just not sure that we'll actually end up in the situation where that reuse would have happened, though.
I think it’s pretty common for monorepos to have projects where these settings differ, but the actual parse doesn’t. It seems silly to not be able to share common declaration files between those projects, when the declaration files themselves are never affected by moduleDetection in the first place.
This PR is pretty broken now; I'm going to redo it, not eliminate the metadata sidecar and instead still pass stuff into the parser as an input, which should produce the smallest diff.
We discussed a new way to do reparsing, however that's a much more difficult undertaking, not just because it means redoing things, but also because reparsing happening in the parser during the initial parse means that the Parser struct is still there and populated with stuff like the identifier list and so on (maybe other important state), so it needs a little bit of thinking.