Skip to content

Properly support scoped package self name lookups #46212

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

Merged
merged 1 commit into from
Oct 5, 2021
Merged
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
8 changes: 6 additions & 2 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
@@ -1724,11 +1724,15 @@ namespace ts {
if (!scope || !scope.packageJsonContent.exports) {
return undefined;
}
if (typeof scope.packageJsonContent.name !== "string") {
return undefined;
}
const parts = getPathComponents(moduleName); // unrooted paths should have `""` as their 0th entry
if (scope.packageJsonContent.name !== parts[1]) {
const nameParts = getPathComponents(scope.packageJsonContent.name);
if (!every(nameParts, (p, i) => parts[i] === p)) {
return undefined;
}
const trailingParts = parts.slice(2);
const trailingParts = parts.slice(nameParts.length);
return loadModuleFromExports(scope, extensions, !length(trailingParts) ? "." : `.${directorySeparator}${trailingParts.join(directorySeparator)}`, state, cache, redirectedReference);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
tests/cases/conformance/node/index.cts(2,23): error TS1471: Module '@scope/package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.


==== tests/cases/conformance/node/index.ts (0 errors) ====
// esm format file
import * as self from "@scope/package";
self;
==== tests/cases/conformance/node/index.mts (0 errors) ====
// esm format file
import * as self from "@scope/package";
self;
==== tests/cases/conformance/node/index.cts (1 errors) ====
// cjs format file
import * as self from "@scope/package";
~~~~~~~~~~~~~~~~
!!! error TS1471: Module '@scope/package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
self;
==== tests/cases/conformance/node/package.json (0 errors) ====
{
"name": "@scope/package",
"private": true,
"type": "module",
"exports": "./index.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//// [tests/cases/conformance/node/nodePackageSelfNameScoped.ts] ////

//// [index.ts]
// esm format file
import * as self from "@scope/package";
self;
//// [index.mts]
// esm format file
import * as self from "@scope/package";
self;
//// [index.cts]
// cjs format file
import * as self from "@scope/package";
self;
//// [package.json]
{
"name": "@scope/package",
"private": true,
"type": "module",
"exports": "./index.js"
}

//// [index.js]
// esm format file
import * as self from "@scope/package";
self;
//// [index.mjs]
// esm format file
import * as self from "@scope/package";
self;
//// [index.cjs]
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
// cjs format file
const self = __importStar(require("@scope/package"));
self;


//// [index.d.ts]
export {};
//// [index.d.mts]
export {};
//// [index.d.cts]
export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
=== tests/cases/conformance/node/index.ts ===
// esm format file
import * as self from "@scope/package";
>self : Symbol(self, Decl(index.ts, 1, 6))

self;
>self : Symbol(self, Decl(index.ts, 1, 6))

=== tests/cases/conformance/node/index.mts ===
// esm format file
import * as self from "@scope/package";
>self : Symbol(self, Decl(index.mts, 1, 6))

self;
>self : Symbol(self, Decl(index.mts, 1, 6))

=== tests/cases/conformance/node/index.cts ===
// cjs format file
import * as self from "@scope/package";
>self : Symbol(self, Decl(index.cts, 1, 6))

self;
>self : Symbol(self, Decl(index.cts, 1, 6))

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
=== tests/cases/conformance/node/index.ts ===
// esm format file
import * as self from "@scope/package";
>self : typeof self

self;
>self : typeof self

=== tests/cases/conformance/node/index.mts ===
// esm format file
import * as self from "@scope/package";
>self : typeof self

self;
>self : typeof self

=== tests/cases/conformance/node/index.cts ===
// cjs format file
import * as self from "@scope/package";
>self : typeof self

self;
>self : typeof self

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
tests/cases/conformance/node/index.cts(2,23): error TS1471: Module '@scope/package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.


==== tests/cases/conformance/node/index.ts (0 errors) ====
// esm format file
import * as self from "@scope/package";
self;
==== tests/cases/conformance/node/index.mts (0 errors) ====
// esm format file
import * as self from "@scope/package";
self;
==== tests/cases/conformance/node/index.cts (1 errors) ====
// cjs format file
import * as self from "@scope/package";
~~~~~~~~~~~~~~~~
!!! error TS1471: Module '@scope/package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
self;
==== tests/cases/conformance/node/package.json (0 errors) ====
{
"name": "@scope/package",
"private": true,
"type": "module",
"exports": "./index.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//// [tests/cases/conformance/node/nodePackageSelfNameScoped.ts] ////

//// [index.ts]
// esm format file
import * as self from "@scope/package";
self;
//// [index.mts]
// esm format file
import * as self from "@scope/package";
self;
//// [index.cts]
// cjs format file
import * as self from "@scope/package";
self;
//// [package.json]
{
"name": "@scope/package",
"private": true,
"type": "module",
"exports": "./index.js"
}

//// [index.js]
// esm format file
import * as self from "@scope/package";
self;
//// [index.mjs]
// esm format file
import * as self from "@scope/package";
self;
//// [index.cjs]
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
// cjs format file
const self = __importStar(require("@scope/package"));
self;


//// [index.d.ts]
export {};
//// [index.d.mts]
export {};
//// [index.d.cts]
export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
=== tests/cases/conformance/node/index.ts ===
// esm format file
import * as self from "@scope/package";
>self : Symbol(self, Decl(index.ts, 1, 6))

self;
>self : Symbol(self, Decl(index.ts, 1, 6))

=== tests/cases/conformance/node/index.mts ===
// esm format file
import * as self from "@scope/package";
>self : Symbol(self, Decl(index.mts, 1, 6))

self;
>self : Symbol(self, Decl(index.mts, 1, 6))

=== tests/cases/conformance/node/index.cts ===
// cjs format file
import * as self from "@scope/package";
>self : Symbol(self, Decl(index.cts, 1, 6))

self;
>self : Symbol(self, Decl(index.cts, 1, 6))

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
=== tests/cases/conformance/node/index.ts ===
// esm format file
import * as self from "@scope/package";
>self : typeof self

self;
>self : typeof self

=== tests/cases/conformance/node/index.mts ===
// esm format file
import * as self from "@scope/package";
>self : typeof self

self;
>self : typeof self

=== tests/cases/conformance/node/index.cts ===
// cjs format file
import * as self from "@scope/package";
>self : typeof self

self;
>self : typeof self

21 changes: 21 additions & 0 deletions tests/cases/conformance/node/nodePackageSelfNameScoped.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @module: node12,nodenext
// @declaration: true
// @filename: index.ts
// esm format file
import * as self from "@scope/package";
self;
// @filename: index.mts
// esm format file
import * as self from "@scope/package";
self;
// @filename: index.cts
// cjs format file
import * as self from "@scope/package";
self;
// @filename: package.json
{
"name": "@scope/package",
"private": true,
"type": "module",
"exports": "./index.js"
}