Skip to content

Conversation

@jakebailey
Copy link
Member

@jakebailey jakebailey commented Nov 11, 2025

I guess to replace my big hammer with a smaller hammer.

#2044

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR reverts PR 2044 and replaces it with a more targeted fix by removing an overly broad check for reparsed nodes in external module indicator detection. The change allows reparsed nodes (those synthesized during parsing) to be properly recognized as external module indicators, which improves CommonJS/ES module handling and type inference.

Key Changes

  • Removed the NodeFlagsReparsed check from isAnExternalModuleIndicatorNode() function
  • Updated 60+ test baselines showing improved compiler behavior and convergence with TypeScript reference implementation

Reviewed Changes

Copilot reviewed 82 out of 82 changed files in this pull request and generated no comments.

File Description
internal/ast/parseoptions.go Removed overly restrictive check that prevented reparsed nodes from being external module indicators
Test baseline files (.types, .symbols, .errors.txt, .js) Updated to reflect improved module detection, better type inference, and proper ES module marker emission
Test diff files (.diff) Many show reduction or elimination of differences from TypeScript reference behavior

@jakebailey
Copy link
Member Author

Going to wait on the other PR since this exposes more problems that would have to be fixed... I am not super content with reverting it

@jakebailey
Copy link
Member Author

Updated; there are still many regressions by removing this.

@ahejlsberg
Copy link
Member

What is the pattern to the regressions you're seeing? I'm still surprised we'd consider excluding reparsed nodes from module determination, just seems wrong to do so.

@jakebailey
Copy link
Member Author

I don't see why we would include them; the old algorithm did not walk into JSDoc nodes, and any other new stuff we stick in the tree to handle expandos or CJS exports and whatnot were not there either, right?

If the PR is filtered to diffs, you can see what's regressing: https://github.com/microsoft/typescript-go/pull/2062/files?file-filters%5B%5D=.go&file-filters%5B%5D=.diff

I can annotate the PR with a few examples.

@jakebailey
Copy link
Member Author

To be clear, I agree that ideally we wouldn't do this, but for the most part the problem is that there are other bugs that this is sort of helping with. I don't think we need to keep it forever.

Comment on lines 7 to 16
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+// #38552
+export var y = exports.x = void 0;
// #38552
exports.y = exports.x = void 0;
+export var x = 1;
exports.x = 1;
+export var y = 2;
exports.y = 2;
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a regression but you'll note that the emit is already wrong; we are emitting actual export var x when we shouldn't. These nodes existing in the tree means we are both detecting it as a module and then printing them back.

Comment on lines +47 to +48
+ ~~~~~~~
+!!! error TS2339: Property 'default' does not exist on type '0'.
Copy link
Member Author

Choose a reason for hiding this comment

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

Strange error appearing here. g.js is exports.default = 0 which breaks for some reason.

Comment on lines +7 to +8
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
Copy link
Member Author

Choose a reason for hiding this comment

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

This file is becoming strict when it shouldn't be; strict is off, alwaysStrict is off, so the determination is only whether or not there's an external module indicator, which Strada must not have had.

Comment on lines 33 to 35
->import('./bug28014') : Promise<{ version: 1; default: { (): void; version: 1; }; }>
+>import('./bug28014') : Promise<{ default: () => void; }>
+>import('./bug28014') : Promise<() => void>
>'./bug28014' : "./bug28014"
Copy link
Member Author

Choose a reason for hiding this comment

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

The type here changes.

Comment on lines +4 to +16
-/a.ts(2,5): error TS2339: Property 'bar' does not exist on type 'typeof import("/node_modules/foo/index")'.
-
-
-==== /a.ts (1 errors) ====
- import foo from "foo";
- foo.bar();
- ~~~
-!!! error TS2339: Property 'bar' does not exist on type 'typeof import("/node_modules/foo/index")'.
-
-==== /node_modules/foo/index.js (0 errors) ====
- exports.default = { bar() { return 0; } }
-
+<no content> No newline at end of file
Copy link
Member Author

Choose a reason for hiding this comment

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

This error disappears.

@ahejlsberg
Copy link
Member

I think a lot of these issues are caused by the re-parser adding a synthetic export modifier to KindCommonJSExport nodes. I don't know why that code is there, but it is causing the isAnExternalModuleIndicatorNode function to return true when it shouldn't. I think a first step should be to remove that export modifier.

@ahejlsberg
Copy link
Member

Ok, it appears the only reason for that synthetic export modifier is so that the binder considers KindCommonJSExport nodes to declare exported symbols. When I remove the export modifier and change the code in declareModuleMember in the binder to always consider KindCommonJSExport nodes to be exports, there are no baseline changes. I will put up a PR to that effect, I think it is a better solution than the blunt instrument of ignoring all reparsed nodes.

Also, I agree there are still issues that need to be fixed in this JS module related code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants