Skip to content

Attempt to fix commonjs module resolution weirdness #1135

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -14746,8 +14746,10 @@ func (c *Checker) resolveESModuleSymbol(moduleSymbol *ast.Symbol, referencingLoc
symbol := c.resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias)
if !dontResolveAlias && symbol != nil {
if !suppressInteropError && symbol.Flags&(ast.SymbolFlagsModule|ast.SymbolFlagsVariable) == 0 && ast.GetDeclarationOfKind(symbol, ast.KindSourceFile) == nil {
compilerOptionName := core.IfElse(c.moduleKind >= core.ModuleKindES2015, "allowSyntheticDefaultImports", "esModuleInterop")
c.error(referencingLocation, diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName)
if ast.GetDeclarationOfKind(symbol, ast.KindJSExportAssignment) == nil {
Copy link
Member

Choose a reason for hiding this comment

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

The original code didn't do something like this; @sandersn is this because the JS the external module symbol isn't the source file anymore?

Copy link
Member

Choose a reason for hiding this comment

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

Also, I think this check could just be in the previous if statement? (But I don't know if it's right in any case.)

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand how this fix is related to the previous code or to the repro in the bug. If you want to know if the file is a commonjs module, there's still CommonJSModuleIndicator in Corsa. But there's nothing about that in the Strada code either.

compilerOptionName := core.IfElse(c.moduleKind >= core.ModuleKindES2015, "allowSyntheticDefaultImports", "esModuleInterop")
c.error(referencingLocation, diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName)
}
return symbol
}
referenceParent := referencingLocation.Parent
Expand Down
26 changes: 26 additions & 0 deletions testdata/baselines/reference/compiler/commonJsModule.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//// [tests/cases/compiler/commonJsModule.ts] ////

=== shared.vars.js ===
const foo = ['bar', 'baz'];
>foo : Symbol(foo, Decl(shared.vars.js, 0, 5))

module.exports = {
>module.exports : Symbol(export=, Decl(shared.vars.js, 0, 27))
>module : Symbol(module.exports)
>exports : Symbol(export=, Decl(shared.vars.js, 0, 27))

foo,
>foo : Symbol(foo, Decl(shared.vars.js, 2, 18))

};

=== index.ts ===
import { foo } from "./shared.vars";
>foo : Symbol(foo, Decl(index.ts, 0, 8))

console.log(foo);
>console.log : Symbol(log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(log, Decl(lib.dom.d.ts, --, --))
>foo : Symbol(foo, Decl(index.ts, 0, 8))

32 changes: 32 additions & 0 deletions testdata/baselines/reference/compiler/commonJsModule.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//// [tests/cases/compiler/commonJsModule.ts] ////

=== shared.vars.js ===
const foo = ['bar', 'baz'];
>foo : string[]
>['bar', 'baz'] : string[]
>'bar' : "bar"
>'baz' : "baz"

module.exports = {
>module.exports = { foo,} : { foo: string[]; }
>module.exports : { foo: string[]; }
>module : { "export=": { foo: string[]; }; }
>exports : { foo: string[]; }
>{ foo,} : { foo: string[]; }

foo,
>foo : string[]

};

=== index.ts ===
import { foo } from "./shared.vars";
>foo : string[]

console.log(foo);
>console.log(foo) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>foo : string[]

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/index.ts(1,23): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
/index.ts(3,16): error TS2671: Cannot augment module './test' because it resolves to a non-module entity.
/index.ts(11,10): error TS2749: 'Abcde' refers to a value, but is being used as a type here. Did you mean 'typeof Abcde'?

Expand All @@ -13,10 +12,8 @@
Abcde
};

==== /index.ts (3 errors) ====
==== /index.ts (2 errors) ====
import { Abcde } from "./test";
~~~~~~~~
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.

declare module "./test" {
~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/index.ts(1,19): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
/index.ts(3,16): error TS2671: Cannot augment module './test' because it resolves to a non-module entity.
/index.ts(7,3): error TS2339: Property 'toFixed' does not exist on type 'string'.

Expand All @@ -8,10 +7,8 @@
a: "ok"
};

==== /index.ts (3 errors) ====
==== /index.ts (2 errors) ====
import { a } from "./test";
~~~~~~~~
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.

declare module "./test" {
~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
bug24934.js(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
use.js(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.


==== bug24934.js (1 errors) ====
export function abc(a, b, c) { return 5; }
module.exports = { abc };
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2309: An export assignment cannot be used in a module with other exported elements.
==== use.js (1 errors) ====
==== use.js (0 errors) ====
import { abc } from './bug24934';
~~~~~~~~~~~~
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
abc(1, 2, 3);

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,26 @@
+++ new.jsExportMemberMergedWithModuleAugmentation.errors.txt
@@= skipped -0, +0 lines =@@
-/index.ts(11,7): error TS2741: Property 'x' is missing in type '{ b: string; }' but required in type 'Abcde'.
+/index.ts(1,23): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
+/index.ts(3,16): error TS2671: Cannot augment module './test' because it resolves to a non-module entity.
+/index.ts(11,10): error TS2749: 'Abcde' refers to a value, but is being used as a type here. Did you mean 'typeof Abcde'?


==== /test.js (0 errors) ====
@@= skipped -10, +12 lines =@@
@@= skipped -10, +11 lines =@@
Abcde
};

-==== /index.ts (1 errors) ====
+==== /index.ts (3 errors) ====
+==== /index.ts (2 errors) ====
import { Abcde } from "./test";
+ ~~~~~~~~
+!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.

declare module "./test" {
+ ~~~~~~~~
+!!! error TS2671: Cannot augment module './test' because it resolves to a non-module entity.
interface Abcde { b: string }
}

@@= skipped -12, +16 lines =@@
@@= skipped -12, +14 lines =@@
// Bug: the type meaning from /test.js does not
// propagate through the object literal export.
const x: Abcde = { b: "" };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
+++ new.jsExportMemberMergedWithModuleAugmentation2.errors.txt
@@= skipped -0, +0 lines =@@
-/index.ts(4,16): error TS2300: Duplicate identifier 'a'.
+/index.ts(1,19): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
+/index.ts(3,16): error TS2671: Cannot augment module './test' because it resolves to a non-module entity.
/index.ts(7,3): error TS2339: Property 'toFixed' does not exist on type 'string'.
-/test.js(2,3): error TS2300: Duplicate identifier 'a'.
Expand All @@ -19,11 +18,8 @@
-!!! related TS6203 /index.ts:4:16: 'a' was also declared here.
};

-==== /index.ts (2 errors) ====
+==== /index.ts (3 errors) ====
==== /index.ts (2 errors) ====
import { a } from "./test";
+ ~~~~~~~~
+!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.

declare module "./test" {
+ ~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@
@@= skipped -0, +0 lines =@@
-bug24934.js(2,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
+bug24934.js(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
+use.js(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.


==== bug24934.js (1 errors) ====
export function abc(a, b, c) { return 5; }
module.exports = { abc };
- ~~~~~~
-!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
-==== use.js (0 errors) ====
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2309: An export assignment cannot be used in a module with other exported elements.
+==== use.js (1 errors) ====
==== use.js (0 errors) ====
import { abc } from './bug24934';
+ ~~~~~~~~~~~~
+!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
abc(1, 2, 3);

abc(1, 2, 3);

This file was deleted.

15 changes: 15 additions & 0 deletions testdata/tests/cases/compiler/commonJsModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @allowJs: true
// @noEmit: true
// @esModuleInterop: true
// @module: commonjs
// @Filename: shared.vars.js
const foo = ['bar', 'baz'];

module.exports = {
foo,
};

// @Filename: index.ts
import { foo } from "./shared.vars";

console.log(foo);