Skip to content

Commit 8f408cc

Browse files
authored
Check resolution of tslib per file (#58654)
1 parent 1d026a9 commit 8f408cc

18 files changed

+711
-32
lines changed

src/compiler/checker.ts

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,9 +1461,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
14611461
// they no longer need the information (for example, if the user started editing again).
14621462
var cancellationToken: CancellationToken | undefined;
14631463

1464-
var requestedExternalEmitHelperNames = new Set<string>();
1465-
var requestedExternalEmitHelpers: ExternalEmitHelpers;
1466-
var externalHelpersModule: Symbol;
14671464
var scanner: Scanner | undefined;
14681465

14691466
var Symbol = objectAllocator.getSymbolConstructor();
@@ -49512,42 +49509,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4951249509
}
4951349510

4951449511
function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) {
49515-
if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) {
49512+
if (compilerOptions.importHelpers) {
4951649513
const sourceFile = getSourceFileOfNode(location);
4951749514
if (isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & NodeFlags.Ambient)) {
4951849515
const helpersModule = resolveHelpersModule(sourceFile, location);
4951949516
if (helpersModule !== unknownSymbol) {
49520-
const uncheckedHelpers = helpers & ~requestedExternalEmitHelpers;
49521-
for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) {
49522-
if (uncheckedHelpers & helper) {
49523-
for (const name of getHelperNames(helper)) {
49524-
if (requestedExternalEmitHelperNames.has(name)) continue;
49525-
requestedExternalEmitHelperNames.add(name);
49526-
49527-
const symbol = resolveSymbol(getSymbol(getExportsOfModule(helpersModule), escapeLeadingUnderscores(name), SymbolFlags.Value));
49528-
if (!symbol) {
49529-
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name);
49530-
}
49531-
else if (helper & ExternalEmitHelpers.ClassPrivateFieldGet) {
49532-
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) {
49533-
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 4);
49517+
const links = getSymbolLinks(helpersModule);
49518+
links.requestedExternalEmitHelpers ??= 0 as ExternalEmitHelpers;
49519+
if ((links.requestedExternalEmitHelpers & helpers) !== helpers) {
49520+
const uncheckedHelpers = helpers & ~links.requestedExternalEmitHelpers;
49521+
for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) {
49522+
if (uncheckedHelpers & helper) {
49523+
for (const name of getHelperNames(helper)) {
49524+
const symbol = resolveSymbol(getSymbol(getExportsOfModule(helpersModule), escapeLeadingUnderscores(name), SymbolFlags.Value));
49525+
if (!symbol) {
49526+
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name);
4953449527
}
49535-
}
49536-
else if (helper & ExternalEmitHelpers.ClassPrivateFieldSet) {
49537-
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) {
49538-
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 5);
49528+
else if (helper & ExternalEmitHelpers.ClassPrivateFieldGet) {
49529+
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) {
49530+
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 4);
49531+
}
4953949532
}
49540-
}
49541-
else if (helper & ExternalEmitHelpers.SpreadArray) {
49542-
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 2)) {
49543-
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 3);
49533+
else if (helper & ExternalEmitHelpers.ClassPrivateFieldSet) {
49534+
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) {
49535+
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 5);
49536+
}
49537+
}
49538+
else if (helper & ExternalEmitHelpers.SpreadArray) {
49539+
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 2)) {
49540+
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 3);
49541+
}
4954449542
}
4954549543
}
4954649544
}
4954749545
}
4954849546
}
49547+
links.requestedExternalEmitHelpers |= helpers;
4954949548
}
49550-
requestedExternalEmitHelpers |= helpers;
4955149549
}
4955249550
}
4955349551
}
@@ -49610,10 +49608,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4961049608
}
4961149609

4961249610
function resolveHelpersModule(file: SourceFile, errorNode: Node) {
49613-
if (!externalHelpersModule) {
49614-
externalHelpersModule = resolveExternalModule(getImportHelpersImportSpecifier(file), externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol;
49611+
const links = getNodeLinks(file);
49612+
if (!links.externalHelpersModule) {
49613+
links.externalHelpersModule = resolveExternalModule(getImportHelpersImportSpecifier(file), externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol;
4961549614
}
49616-
return externalHelpersModule;
49615+
return links.externalHelpersModule;
4961749616
}
4961849617

4961949618
// GRAMMAR CHECKING

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5953,6 +5953,7 @@ export interface SymbolLinks {
59535953
tupleLabelDeclaration?: NamedTupleMember | ParameterDeclaration; // Declaration associated with the tuple's label
59545954
accessibleChainCache?: Map<string, Symbol[] | undefined>;
59555955
filteredIndexSymbolCache?: Map<string, Symbol> //Symbol with applicable declarations
5956+
requestedExternalEmitHelpers?: ExternalEmitHelpers; // External emit helpers already checked for this symbol.
59565957
}
59575958

59585959
// dprint-ignore
@@ -6139,6 +6140,7 @@ export interface NodeLinks {
61396140
parameterInitializerContainsUndefined?: boolean; // True if this is a parameter declaration whose type annotation contains "undefined".
61406141
fakeScopeForSignatureDeclaration?: "params" | "typeParams"; // If present, this is a fake scope injected into an enclosing declaration chain.
61416142
assertionExpressionType?: Type; // Cached type of the expression of a type assertion
6143+
externalHelpersModule?: Symbol; // Resolved symbol for the external helpers module
61426144
}
61436145

61446146
/** @internal */

tests/baselines/reference/esModuleInteropTslibHelpers.errors.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
file2.ts(1,1): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
2+
file3.ts(1,9): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
3+
file4.ts(1,14): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
24

35

46
==== refs.d.ts (0 errors) ====
@@ -13,11 +15,15 @@ file2.ts(1,1): error TS2354: This syntax requires an imported helper but module
1315
!!! error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
1416
path.resolve("", "../");
1517
export class Foo2 { }
16-
==== file3.ts (0 errors) ====
18+
==== file3.ts (1 errors) ====
1719
import {default as resolve} from "path";
20+
~~~~~~~~~~~~~~~~~~
21+
!!! error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
1822
resolve("", "../");
1923
export class Foo3 { }
20-
==== file4.ts (0 errors) ====
24+
==== file4.ts (1 errors) ====
2125
import {Bar, default as resolve} from "path";
26+
~~~~~~~~~~~~~~~~~~
27+
!!! error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.
2228
resolve("", "../");
2329
export { Bar }
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/package1/index.ts(2,16): error TS2343: This syntax requires an imported helper named '__awaiter' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
2+
3+
4+
==== /tsconfig.json (0 errors) ====
5+
{
6+
"compilerOptions": {
7+
"strict": true,
8+
"target": "ES2016",
9+
"importHelpers": true,
10+
"module": "commonjs",
11+
}
12+
}
13+
14+
==== /package1/index.ts (1 errors) ====
15+
export {};
16+
async function foo(): Promise<void> {}
17+
~~~
18+
!!! error TS2343: This syntax requires an imported helper named '__awaiter' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
19+
async function bar(): Promise<void> {}
20+
21+
==== /package2/index.ts (0 errors) ====
22+
export {};
23+
async function foo(): Promise<void> {}
24+
25+
==== /node_modules/tslib/package.json (0 errors) ====
26+
{
27+
"name": "tslib",
28+
"main": "tslib.js",
29+
"typings": "tslib.d.ts"
30+
}
31+
32+
==== /node_modules/tslib/tslib.d.ts (0 errors) ====
33+
export const notAHelper: any;
34+
35+
==== /node_modules/tslib/tslib.js (0 errors) ====
36+
module.exports.notAHelper = 3;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//// [tests/cases/compiler/tslibMissingHelper.ts] ////
2+
3+
//// [package.json]
4+
{
5+
"name": "tslib",
6+
"main": "tslib.js",
7+
"typings": "tslib.d.ts"
8+
}
9+
10+
//// [tslib.d.ts]
11+
export const notAHelper: any;
12+
13+
//// [tslib.js]
14+
module.exports.notAHelper = 3;
15+
//// [index.ts]
16+
export {};
17+
async function foo(): Promise<void> {}
18+
async function bar(): Promise<void> {}
19+
20+
//// [index.ts]
21+
export {};
22+
async function foo(): Promise<void> {}
23+
24+
25+
//// [index.js]
26+
"use strict";
27+
Object.defineProperty(exports, "__esModule", { value: true });
28+
const tslib_1 = require("tslib");
29+
function foo() {
30+
return tslib_1.__awaiter(this, void 0, void 0, function* () { });
31+
}
32+
function bar() {
33+
return tslib_1.__awaiter(this, void 0, void 0, function* () { });
34+
}
35+
//// [index.js]
36+
"use strict";
37+
Object.defineProperty(exports, "__esModule", { value: true });
38+
const tslib_1 = require("tslib");
39+
function foo() {
40+
return tslib_1.__awaiter(this, void 0, void 0, function* () { });
41+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [tests/cases/compiler/tslibMissingHelper.ts] ////
2+
3+
=== /package1/index.ts ===
4+
export {};
5+
async function foo(): Promise<void> {}
6+
>foo : Symbol(foo, Decl(index.ts, 0, 10))
7+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
8+
9+
async function bar(): Promise<void> {}
10+
>bar : Symbol(bar, Decl(index.ts, 1, 38))
11+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
12+
13+
=== /package2/index.ts ===
14+
export {};
15+
async function foo(): Promise<void> {}
16+
>foo : Symbol(foo, Decl(index.ts, 0, 10))
17+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
18+
19+
=== /node_modules/tslib/tslib.d.ts ===
20+
export const notAHelper: any;
21+
>notAHelper : Symbol(notAHelper, Decl(tslib.d.ts, --, --))
22+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/compiler/tslibMissingHelper.ts] ////
2+
3+
=== /package1/index.ts ===
4+
export {};
5+
async function foo(): Promise<void> {}
6+
>foo : () => Promise<void>
7+
> : ^^^^^^
8+
9+
async function bar(): Promise<void> {}
10+
>bar : () => Promise<void>
11+
> : ^^^^^^
12+
13+
=== /package2/index.ts ===
14+
export {};
15+
async function foo(): Promise<void> {}
16+
>foo : () => Promise<void>
17+
> : ^^^^^^
18+
19+
=== /node_modules/tslib/tslib.d.ts ===
20+
export const notAHelper: any;
21+
>notAHelper : any
22+
> : ^^^
23+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/package1/index.ts(2,16): error TS2343: This syntax requires an imported helper named '__awaiter' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
2+
/package1/other.ts(3,32): error TS2343: This syntax requires an imported helper named '__rest' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
3+
/package2/index.ts(2,16): error TS2343: This syntax requires an imported helper named '__awaiter' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
4+
5+
6+
==== /tsconfig.json (0 errors) ====
7+
{
8+
"compilerOptions": {
9+
"strict": true,
10+
"target": "ES2016",
11+
"importHelpers": true,
12+
"module": "commonjs",
13+
}
14+
}
15+
16+
==== /package1/index.ts (1 errors) ====
17+
export {};
18+
async function foo(): Promise<void> {}
19+
~~~
20+
!!! error TS2343: This syntax requires an imported helper named '__awaiter' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
21+
async function bar(): Promise<void> {}
22+
23+
==== /package1/other.ts (1 errors) ====
24+
export {};
25+
export async function noop(): Promise<void> {}
26+
export function spread({ a, ...rest }: { a: number, b: number}) {
27+
~~~~
28+
!!! error TS2343: This syntax requires an imported helper named '__rest' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
29+
return { c: "c", ...rest };
30+
}
31+
32+
==== /package2/index.ts (1 errors) ====
33+
export {};
34+
async function foo(): Promise<void> {}
35+
~~~
36+
!!! error TS2343: This syntax requires an imported helper named '__awaiter' which does not exist in 'tslib'. Consider upgrading your version of 'tslib'.
37+
38+
==== /package1/node_modules/tslib/package.json (0 errors) ====
39+
{
40+
"name": "tslib",
41+
"main": "tslib.js",
42+
"typings": "tslib.d.ts"
43+
}
44+
45+
==== /package1/node_modules/tslib/tslib.d.ts (0 errors) ====
46+
export const notAHelper: any;
47+
48+
==== /package1/node_modules/tslib/tslib.js (0 errors) ====
49+
module.exports.notAHelper = 3;
50+
51+
==== /package2/node_modules/tslib/package.json (0 errors) ====
52+
{
53+
"name": "tslib",
54+
"main": "tslib.js",
55+
"typings": "tslib.d.ts"
56+
}
57+
58+
==== /package2/node_modules/tslib/tslib.d.ts (0 errors) ====
59+
export const notAHelper: any;
60+
61+
==== /package2/node_modules/tslib/tslib.js (0 errors) ====
62+
module.exports.notAHelper = 3;

0 commit comments

Comments
 (0)